2

British Summer time adjusts clocks forward in March and back in October every year. During 1968 to 1971 the UK trialed BST as a permanent option, such that the clocks where put forward 1 hour in March 1968 and not reverted back until October 1971.

I am creating dates in Javascript, serializing them as JSON and posting to a WebApi.

Currently using windows 7 as a development environment, Windows is NOT recognizing that period as BST. For example 01/01/1970 should be Daylight Saving time, however

new System.DateTime(1970, 01, 01, 00, 00, 00).IsDaylightSavingTime();

returns false.

also...

System.TimeZone.CurrentTimeZone.GetDaylightChanges(1970)
{System.Globalization.DaylightTime}
    Delta: {01:00:00}
    End: {25/10/1970 02:00:00}
    Start: {29/03/1970 01:00:00}

1970 should have a rule covering the entire year as the whole year was BST.

Is there a patch to correct the flaw in Windows?

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
user1654348
  • 283
  • 4
  • 12
  • No. There's no BST - it's just an informal acronym. Your code though doesn't show any attempt to use a *specific* timezone. It uses the *current* one implicitly which I'll bet doesn't have such a rule. – Panagiotis Kanavos Aug 08 '18 at 13:15
  • The de-facto standard for time zones is the IANA timezone database. For London, the timezone is `Europe/London`. If timezones matter you should use a library like [NodaTime](https://nodatime.org/) which includes the IANA database – Panagiotis Kanavos Aug 08 '18 at 13:19
  • That's just it; Timezones don't matter, the client and server are in the same time zone so serializing and de-serializing a time should follow the same rules, however they are not. For dates within this 1968 - 1971 time period, date are being serialized and de-serialized (on the same machine) potentially losing an hour. – user1654348 Aug 08 '18 at 13:37
  • Why do you assume there's any such rule in your *current* timezone? Or that timezone rules go that far back? This has nothing to do with serialization or deserialization, unless you *forget* to include the offset or IANA timezone name – Panagiotis Kanavos Aug 08 '18 at 13:45
  • If you care about offsets *don't* assume. Don't use DateTime, use DateTimeOffset. Use the ISO8601 format *with* the offset when serializing. If you care about time *zones*, use the IANA timezone names and a library that supports them. The rules go back to the 1800s – Panagiotis Kanavos Aug 08 '18 at 13:47
  • there's no DST when the entire year has a *single* offset. – Panagiotis Kanavos Aug 08 '18 at 14:01
  • What I am more interested in: Why do you need to know whether a datetime is DST to send the datetime to a webservice? That seems wrong. – NineBerry Aug 08 '18 at 15:08
  • In addition to the duplicate linked, see also [this one](https://stackoverflow.com/q/26156260/634824) and [this one](https://stackoverflow.com/q/47104967/634824). Thanks. – Matt Johnson-Pint Aug 08 '18 at 21:47

3 Answers3

3

Update

There is a bug after all, or rather GMT Standard Time doesn't contain UK-specific rules. Between 1968 and 1970 the offset for the UK changed to +1:00 and there was no DST.

The real problem is that the offset is wrong for the UK for that period :

var date= new DateTime(1970,1,1,0,0,0,DateTimeKind.Local);
var tzi = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
var offset=tzi.GetUtcOffset(date);

offset is 00:00:00. Oooops!

For 1970-08-01 the offset is 01:00:00 and IsDaylightSavingTime() returns True.

PS: SQL Server's AT TIME ZONE uses the Windows time zone names. This could be an even bigger source of problems with historical data.

Original

There's no bug. When the entire year has a single offset it doesn't make sense to talk about Daylight Saving Time.

The IANA timezone database shows that 1970-01-01 did not use DST. The offset was +1:00. Using NodaTime :

var london = DateTimeZoneProviders.Tzdb["Europe/London"];

// Time zone conversions
var localDate = new LocalDateTime(1970, 1, 1, 0, 0, 00);
var before = london.AtStrictly(localDate);

Console.WriteLine($"{before} {before.IsDaylightSavingTime()} {before.Offset}");

This returns :

1970-01-01T00:00:00 Europe/London (+01) DST:False +01

For 1971-11-01 the result is :

1971-11-01T00:00:00 Europe/London (+00) DST:False +00

At that point the offset changed from +1:00 to +00:00 and the DST rule was reintroduced.

The results are more interesting for summer dates.

1971-07-30 returns :

1971-07-30T00:00:00 Europe/London (+01) DST:False +01

Which is correct - there were no DST rules in effect on that date. The offset was fixed at +1.

1972-07-30 returns :

1972-07-30T00:00:00 Europe/London (+01) DST:True +01

The offset is the same, because the DST rules were in effect on that date.

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
  • It's not a bug, it's just that Windows does not have historical data going back that far. See the duplicate link. Also, in general, Windows time zone data is only guaranteed to be reliable from 2010 forward (mentioned in the MS DST/TZ policy page [here](https://support.microsoft.com/en-us/help/22803/daylight-saving-time)). Some zones may have earlier data, but there are no guarantees that they all will. – Matt Johnson-Pint Aug 08 '18 at 21:41
  • @MattJohnson all the more reason to *not* use Windows timezones in SQL Server, says the travel agency developer. No GDS reports the *Windows* tz name anyway. How does `AT TIME ZONE` work on SQL Server on *Linux* anyway? – Panagiotis Kanavos Aug 09 '18 at 07:31
  • @MattJohnson or rather, to avoid paying ticket refunds, GDSs and travel agencies will *avoid* Windows timezones like the plague. If it leads to liability, it has to be treated as a bug – Panagiotis Kanavos Aug 09 '18 at 07:34
2

Windows does not have a separate time zone for the United Kingdom. The time zone used by Windows in the United Kingdom ("GMT Standard Time") is shared with Ireland and Portugal.

That's why historic deviations that only applied to the United Kingdom are not reflected.

Borders of countries have changed a lot even in the last 200 years and until quite recently (only a few decades ago) very small regions in Europe had their own definition of time zones and they changed frequently. Windows cannot reflect that complex information. If you need that information you need to use a dedicated database.

NineBerry
  • 26,306
  • 3
  • 62
  • 93
1

As has been stated in the comments, the code you presented is using the current timezone on the computer you are running that code. This might be the UK but it's not a good idea to assume. The below code takes into account the comments above:

var tzi = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
var dt = new DateTime(1970, 1, 2, 0, 0, 0, DateTimeKind.Utc);

var isDlt = tzi.IsDaylightSavingTime(dt);

This also returns false though so the bug as you state does indeed exist. I very much doubt there is a patch but if you were so inclined you could quite easily write an extension method that uses the IANA database to determine if a given date is during daylight saving.

You might also want to look at the documentation for TimeZoneInfo.GetAdjustmentRules - https://msdn.microsoft.com/en-us/library/system.timezoneinfo.getadjustmentrules(v=vs.110).aspx

Chris Wyatt
  • 142
  • 8
  • Reason I am not specifying the timezone is because it will be UK based regardless; so don't need to. It definitely IS a flaw, I just cant see how i never came across it before, or how MS has not fixed it. – user1654348 Aug 08 '18 at 13:41
  • Also, this is in Microsoft's documentation for GetDayLightChanges(): "Because the TimeZone class supports only one daylight saving time adjustment rule, the GetDaylightChanges method applies the current adjustment rule to any year, regardless of whether the adjustment rule actually applies to that year." – Chris Wyatt Aug 08 '18 at 13:53
  • @ChrisWyatt when the same offset is used throughout the year there's no DST. The *offset* in that period was +1:00 instead of 00:00. There's no bug – Panagiotis Kanavos Aug 08 '18 at 14:03
  • It's a matter of semantics then. IANA happen to consider it standard time with an offset but politically at least it is referred to as summer time. – Chris Wyatt Aug 08 '18 at 14:29
  • @ChrisWyatt it's not semantics when it makes you lose your flight. Just say `Russia` to any online travel agent - 3 rule changes in the last 5 years. It gets worse. SQL Server on Windows at least uses Windows timezone names for the `AT TIME ZONE` expression. Which makes it a bit useless for said travel agents – Panagiotis Kanavos Aug 08 '18 at 14:57
  • @ChrisWyatt - The docs you referenced are about the .NET `TimeZone` class specifically. The `TimeZoneInfo` class does not have the problem of being able to handle multiple adjustment rules. The `TimeZone` docs do say to use `TimeZoneInfo` instead. The only problem in this particular case is that "GMT Standard Time" does not have any historical information, because Windows generally doesn't track historical time zone changes earlier than 2010. – Matt Johnson-Pint Aug 08 '18 at 21:46