Var d as DateTime
Const sd = "2024-03-10 "
Var s, st() As String
st = Array("00:00", "00:30", "01:00", "01:30", "02:00", "02:30", "03:00")
For each t As String in st
s = sd + t
d = DateTime.FromString(s, Nil, New TimeZone("America/New_York"))
system.DebugLog s+" -> "+d.SQLDateTime
Next
break
The example is showing the offset conversion due to DST for existing places in time. But the results seems weird and incorrect. If the date/time is like day 32 in a month ending at 31 it raises an exception for example.
The Xojo time zone does not change, still America/NY -14400 all the time, DST or not.
DST ends at 02:00, so in real life, your “smart clock” should show 01:58, 01:59, 01:00, 01:01…
Seems like the DateTime.FromString() silently nulled the conflicting period 02:00 to 02:59 at the end of DST, and translates as is before 02:00:00 after 02:59:59.
A better way to handle this is storing current real time as GMT+00:00, and just taking care of DST for presentation.
The example (for March) is “spring forward”, so 01:58, 01:59, 03:00, 03:01…
On Mac time of 02:00 creates an exception.
On Windows time goes down to 0:00 for any minute between 02:00 and 02:59 (for what I saw in your example).
There are other countries with “spring forward” at 00:00 to 01:00, so 00:00-00:59 doesn’t exists. I wonder what will happen on Windows if such a TZ is set for let’s say 00:30 and Windows tries to go down to 00:00 (the same as it happens with your New York test) if 00:00 does not exist for that country/TZ. That’s all.
A not “writable” date/time representation should be as is, “not writable”. So in a spring forward that creates a non-representable period of time in such time zone, trying so should raise an exception, and at the same time provide a “nearest conversion” as possible, so people opting to ignore the exception could end with a kind of valid value with a small error they opted having it. The behavior should be consistent amongst all platforms, and documented, including examples.
The current behavior is not consistent in all platforms, and results are random and not well documented.
ho boy, you guys wrote a lot here and from > 1979-05-27 I see that the chat jumped to totally different dates and even non existing ones , why in the world someone would write 32 March Rick ?
The idea was to be able to keep the dates as they are and maybe to have back the format of Simple Date and DateTime as the new one, as honestly most of the times in our case on the birth date you need the date not the time, and that time wastes space on the db side just because it Is added there. Now with the modern pcs is less likely to care someone for few bits but this could lead to some mess in case we need tot alter data and add hours on dates
As for my case, it seems that both Belgium and Romania had DST at that date so what do I do ? I just setup the timezone for my area where do I process the data and it should be solved @AlbertoD ? or do I still need to add the time as well, and now have the headache to map and search for the dates when DST was applied or not and start messing with dates ?
Not only write as also calculate it. As someone that processed lots of contents sent by 3rd parties, many as CSV files, I’ve got things as “”, NULL, 0000-00-00, 2017-00-01, 2018-13-13, 2019-02-31, etc
Well encoding says UTF8, but I guess something is fishy there as even the content on some is messed up so that might be the case on my side , I will have to check .
DateTime requires the Time component even if you are only providing the Date. On your example “2019-08-01” converts to a DateTime that really is “2019-08-01 00:00” and some TimeZone. As DateTime is DST aware if your TimeZone/Country “spring forward” at 00:00:00 of that day then that DateTime does not exist and you get an Exception.
As the USA “spring forward” at 02:00 hrs there are no Dates at 00:00 hrs that do not exist in the USA but in other countries there are dates that do not exist at 00:00.
That means that Romania “spring forward” on “1979-05-27 00:00” to “1979-05-27 01:00” making “1979-05-27 00:00” not existing and causing OP’s exception.
It should not cause a Exception if your TimeZone is, for example, USA Central time as there is no “spring forward” in the USA at 00:00 hrs on May 27, 1979. The same as most countries for that date.
You can test this code in your computer, preferable using Mac but I guess Windows will also show an exception:
//Bucharest is in Romania
Var d as DateTime = DateTime.FromString("1979-05-27", Nil, New TimeZone("Europe/Bucharest"))
I hope it is clear now and this helps find a way to avoid this Exception.
Sorry, its not mentioned in the documentation that DateTime is aware of DST and in my opinion throwing an exception is the wrong way to handle this situation, as no-one can know each day and time worldwide when a DST has or can occur.
So this looks like a bug for me - a better way to handle this is to use a correct value for the DST - so “1979-05-27” will be translated into “1979-05-27 01:00:00” if your timezone is set to Romania…
Function to convert string to nearest valid value, also convert time from one zone to another:
Public Function DateTimeZoned(dateTimeStr As String, toZone As TimeZone = Nil, fromZone As TimeZone = Nil) As DateTime
If toZone = Nil Then toZone = TimeZone.Current
If fromZone = Nil Then fromZone = TimeZone.Current
// Convert date/time from origin zone to a DateTime UTC
Var d As DateTime = DateTime.FromString(dateTimeStr , Nil, _
New TimeZone(fromZone.SecondsFromGMT))
// Convert the GMT date/time in secs to the target TZ
Return New DateTime(d.SecondsFrom1970, toZone)
End Function
// example:
Var zRO As New TimeZone("Europe/Bucharest")
Var d1, d2, d3 As DateTime
d1 = DateTimeZoned("1979-05-27 00:00") // Local zone
d2 = DateTimeZoned("1979-05-27 00:00", zRO) // Local to Bucharest
d3 = DateTimeZoned("1979-05-27 00:00", zRO, zRO) // Bucharest to Bucharest = The same as d1 if you're there
MessageBox d1.SQLDateTime + EndofLine + d1.Timezone.Abbreviation + "->" + d1.Timezone.Abbreviation + _
" / " + d1.SecondsFrom1970.ToString("#0.0000####") + EndOfLine + EndOfLine + _
d2.SQLDateTime + EndofLine + d1.Timezone.Abbreviation + "->" + zRO.Abbreviation + _
" / " + d2.SecondsFrom1970.ToString("#0.0000####") + EndOfLine + EndOfLine + _
d3.SQLDateTime + EndofLine + zRO.Abbreviation + "->" + zRO.Abbreviation + _
" / " + d3.SecondsFrom1970.ToString("#0.0000####") + EndOfLine
Quit