Reputation: 93
I had an issue where dates were out by one day when displaying on an asp.net web form. These dates are only used for display so I can pass them as strings to resolved the issue, but I'm curious about why I'm seeing this behaviour.
I'm in Ireland, and while Ireland is more or less in line with GMT, we use IST (Irish Standard Time) during summer instead of DST and then revert to GMT for Winter. This has the same effect as being on GMT, but "officially" is slightly different.
As we're not on GMT, in the past, IST and DST didn't always line up.
For example, in 1958, IST started in the 20th April and ended on the 5th October whereas, DST started on the 27th of April and ended on 26th of October.
So if a date between the 5th and 26th of October 1958 is passed to JS, JS will display it as the previous day.
I wrote this this code to try and understand what's going on:
DateTime date = new DateTime(1958, 10, 4);
while (date <= new DateTime(1958, 10, 30))
{
Console.WriteLine($"normal : {date} | isDst? : {date.IsDaylightSavingTime()}");
Console.WriteLine($"universal: {date.ToUniversalTime()} | isDst? : {date.ToUniversalTime().IsDaylightSavingTime()}");
Console.WriteLine($"local : {date.ToLocalTime()} | isDst? : {date.ToLocalTime().IsDaylightSavingTime()}");
Console.WriteLine("-------------------------");
date = date.AddDays(1);
}
Which produced this output (truncated):
So I can see there are a number of days being mis identified as DST days, but it doesn't seem like that would cause this? If both .Net and JS though they were DST days, then surely the end result should be correct?
Additionally, why is there a 2 hour difference between the output of ToUniversalTime and ToLocalTime during DST?
Here's a screenshot of JS processing a few dates duirng this problematic window
You can see that JS (or chrome?) is aware that during the 5th to the 27th of that year, Ireland is no longer on GMT+1 (even though it still says it's IST) so why is the date passed from VB an incorrect date? I though they both got their datetime information from the same source i.e. the host pc?
Upvotes: 0
Views: 488
Reputation: 241808
You appear to be running .NET on Windows, in which case .NET is using the Windows time zone data for your local time zone.
The Windows time zone data does not have the full history of time zone changes from all time. Microsoft's policy only guarantees historical data is present for dates from 2010 forward, though some time zones have historical data before then.
Conversely, Chrome is using time zone data from ICU, which uses IANA time zone data. IANA time zones have historical data since at least 1970, though many time zones have historical data before then.
With specific regard to Ireland, IANA has Irish time zone data going back to 1880. Windows has no history for Ireland at all, so it assumes the current rule has always been in effect. In reality, the current rule has been in effect since Oct 1968, so any dates before then will only have accurate time zone information in the IANA data.
If you run the same .NET code you showed above on Linux or MacOS, you'll see that .NET will use IANA time zone data on those platforms and your results will match up for 1958. Or, if you pick a more recent date your results will match on Windows too.
In short - don't run these sorts of tests on old dates and expect to get the same fidelity that you'll get with modern dates.
You also asked:
Additionally, why is there a 2 hour difference between the output of
ToUniversalTime
andToLocalTime
during DST?
Your date
variables are all DateTime
where .Kind
is DateTimeKind.Unspecified
. The IsDaylightSavingTime
method will treat such values as if they belonged to the local time zone, as if they actually had DateTimeKind.Local
. The same is true for the ToUniversalTime
method, however, the ToLocalTime
method will assume that DateTime
values with DateTimeKind.Unspecified
kind are actually in terms of UTC - as if they were DateTimeKind.Utc
. Thus, when DST is in effect, date.ToUniversalTime()
shifts an hour backward, and date.ToLocalTime()
shifts an hour forward.
You can avoid such ambiguities by using DateTimeOffset
instead of DateTime
.
Upvotes: 1