I have a timestamp string in the form “20220513” and want to modify it to the form “2022-05-13”. Is using the .Middle() method (3x) with concatenation the only way to go? It works; it just seems a little unwieldy.
You could do RegEx, but the Middle() approach is probably fine.
Or split, change array and join, but that may be slower.
Parsing the string manually is probably the best solution as I can’t think of a locale that uses that as a date format. If you want the extra validation that the framework can provide, you can do something like this:
var dateString as String = "20220513"
var d as new DateTime( dateString.Left(4).ToInteger, dateString.Middle(4, 2).ToInteger, dateString.Right(2).ToInteger )
var result as String = d.SQLDate
The framework will throw InvalidArgumentExceptions if the supplied values to the DateTime constructor are outside the expected range in addition to OutOfBoundsExceptions if your parsing exceeds the length of the string.
This will do it
dim theDate as string = "20220513"
msgbox Format(val(theDate), "0000\-00\-00")
(Feel free to translate to API2 if you want)
This won’t work with API2’s ToString, IIRC, due to the switch to using the unicode number format patterns.
You can see the difference with this code, which results in a value of 20,220,513
.
theDate.ToDouble.ToString( "0000\-00\-00" )
Likewise, using ToInteger results in 20220513
.
I looked at the Number Format Patterns spec and don’t see an arbitrary escape defined (I may be overlooking it, so please correct me if I’m wrong), so your solution would seem to only function with the API 1.0 Format function.
Oh well.
Thats progress I guess.
Maybe wrap it up with a replaceall ? (not a user of API2 myself)
theDate.ToDouble.ToString( "0000\-00\-00" ).Replaceall(",","-")
That would still give an incorrect value of 20-220-513
. The good news is that, checking the documentation and analyzing in the IDE, Format doesn’t actually appear to be deprecated. I thought that it was. So your original solution would work just fine without a deprecation warning and it also doesn’t complain about val()
so…yeah.
Why do you use Double at all??? Converting a String representing a Date into a Double - why would you think that improves anything? On the contrary: THAT is where you get your problems.
He used Val()
, I was doing a 1:1 conversion of the code he provided to API2 based on his suggestion. It showed the difference quite well, I think.
See the rest of the discussion. Format versus ToString is the main problem point as using ToInteger also fails.
Why ?
Can’t you convert that to a computer Date - instead of a String - and display the Date for the human eye / keeping the computer Date object for the application internal use ?
If you have a short string and a defined format, what could be simpler as to cut it and concatenate the pieces to a result?
Two MVP‘s gave answers that overcomplicates the actual task. Are you serious?
Even better is to convert all received dates to a Double containing the number of seconds since the epoch. That way date comparisons and increments by e.g. a week become trivial, and time zone ceases to be a problem. Then, for display to the user, convert to the format of their choice rather than yours.
I provided one that does give some validation in the form of thrown exceptions in the case of invalid input. Sure, you could just slice the string and concatenate, which is what they said they’re already doing in the first post. No need for us to suggest what they’re already doing.
They are just answering with “other ways to go”.
I guess if the question was:
- is it the best way to go?
- is it the fastest way to go?
- is it the safest way to go?
the answers could be different.
I have learned a lot from answers that do not simply answer my problem but give ideas that I was not aware. Maybe OP could need validation, maybe needs to convert to datetime object to better handle the situation, or maybe learning that format can help and .ToString uses a different format pattern than Format.
All of this is helpful when you want to learn because much of the time there is not a single way to do things. Maybe we can find other ways easier/clearer/safer/faster.
@AlbertoD and all others, you‘re right, there are always many ways to go. But when the OP has already gone the simplest way, why make it more complicate?
And BTW: The question was not to convert a string into a date and display it in a locale format or wharever. He asked for a simpler way and no one provides one. The answers (of the MVP‘s) are fine, but I miss the remark as like „If you want more than reformat that string then you can use RegEx, the DateTime class etc.“.
Thanks to this thread I learned that Format and .ToString don’t use the same pattern.
If someone just answered "you can use left(4) and right(2) too, and the thread was not answered anymore then I will still believe that the format pattern for String is the same as in Format. I don’t use .ToString much and less with a format pattern but is always good to know where things are different.
I know it is in the docs but I’m sure that I will not look at them until something is not working as I expect.
Personally I thank those that give extra answers (validation, be aware of the input/source, etc). It gives me an opportunity to learn.
I like the approach complicate once, simplify everything after, like:
Module StringDateTime
Public Function ToSQLDate(Extends dts As String) As String
Var dt As DateTime
Try
If dts.Length=8 Then
dt = DateTime.FromString(dts.Left(4)+"-"+dts.Middle(4,2)+"-"+dts.Right(2))
Else
dt = DateTime.FromString(dts) // Maybe something valid
End
Catch // Invalid date
Return ""
End
Return dt.SQLDate
End Function
End Module
Use as
Var s As String = "20220513"
MessageBox s.ToSQLDate
He asked for a simpler way and no one provides one.
Really?
does
Format(val(theDate), "0000\-00\-00")
look harder than
var d as new DateTime( dateString.Left(4).ToInteger, dateString.Middle(4, 2).ToInteger, dateString.Right(2).ToInteger )
var result as String = d.SQLDate
I do like Rick’s answer, however, as once it is written, usage later (assuming it needs to be used in multiple places in the app) becomes simpler, and has vaildation
The date as 8 characters is coming from an application that I didn’t write – I’m working with what I have. What I’m actually dealing with is a filename in the form:
log-20220514.txt
These files are collected in a folder and I want to be able to remove all but the last 14 days worth of logs (based on the date in the filename). This is the code that tells me how old the file is.
Var today As DateTime = DateTime.Now
// "log-20220513.txt" --> "2022-05-13"
fname = fname.Middle(4, 4) + "-" + fname.Middle(8, 2) + "-" + fname.Middle(10, 2)
Var target As DateTime = DateTime.FromString(fname)
Var dif As DateInterval = today - target
Return dif.days
I am new to Xojo, so I I ask questions.