Shahin Dohan
Shahin Dohan

Reputation: 6907

Adjust "Daylight Saving Time" (DST) option in .NET, just like Windows

I'm trying to replicate the Windows Date & Time settings in a UWP application, and I'm having a bad time dealing with Daylight Saving Time (DST) settings.

I managed to get everything working, I can change the system time and timezone just fine from my app, but the option Adjust for daylight saving time automatically is confusing me.

At first I thought it was enough to check TimeZoneInfo.SupportsDaylightSavingTime, then I found out that I probably also need to check if the currently selected date/time is in DST range by doing TimeZoneInfo.IsDaylightSavingTime.

Well, I thought I had it right, but after testing, my own "Adjust DST" option is not the same as the Windows setting, and since I can't see the Windows source code, I have no idea what other conditions they are checking to disable/enable it.

My UWP application:

Date & Time settings in my UWP app

Windows settings:

Windows Date & Time settings

Am I still missing something here? My other question regarding this can be found here for those who are interested.

Maybe some MS devs with insider information can tell me the logic behind this toggle switch :-)

Thank you in advance!

UPDATE:

Results from tzutil show that when date is 16th May, 2011 and timezone is Moscow (UTC+3), turning off DST by using the command tzutil /s "Russian Standard Time_dstoff" simply returns "Russian Standard Time" without _dstoff because DST is not applicable, and that lines up with what Windows reports.

But, then why does .NET's TimeZoneInfo class say this? .NET says current datetime is in DST range Tried also with:

var currentDateTime = new DateTime(2011, 5, 16, 0, 0, 0, DateTimeKind.Local);
var isDst = TimeZoneInfo.Local.IsDaylightSavingTime(currentDateTime); //True

So, .NET says the current date is in DST range, but DST cannot be turned off using TZUTIL nor from Windows settings?

Maybe I'm missing something very obvious here, but I don't see it...

UPDATE:

Changing month to February, turns Adjust DST toggle on in Windows, due to adjustment rules? But, in Helsinki, we also have these transitions, and the toggle isn't disabled? What's different?

UPDATE:

Decided not to do any of this, and just check TimeZoneInfo.SupportsDaylightSavingTime. It's not worth anyone's time or energy to do it exactly like Windows does.

Upvotes: 2

Views: 6434

Answers (1)

Matt Johnson-Pint
Matt Johnson-Pint

Reputation: 241420

A few things to address your questions:

  • Don't use the System.TimeZone class at all - ever. It has lots of problems, and there are better alternatives. For most .NET code, use System.TimeZoneInfo instead. Since you said you are writing a UWP application, you might also benefit from Windows.Globalization.Calendar and Windows.Globalization.DateTimeFormatting.DateTimeFormatter classes. Open source libraries such as Noda Time can also be a good choice.

    In the first code block you showed, you are using System.TimeZone.IsDaylightSavingTime. The remarks in the docs explain the results you are seeing:

    "Because the TimeZone class supports a single daylight saving time adjustment rule, the IsDaylightSavingTime(DateTime) method applies the current adjustment rule to any date, regardless of whether the adjustment rule was in effect on that date. Assuming that the operating system itself has accurate historic daylight saving time data, a more accurate result is available by using the TimeZoneInfo.IsDaylightSavingTime method. Whenever possible, use the TimeZoneInfo.IsDaylightSavingTime method."

  • In the second code block you showed, you are correctly using System.TimeZoneInfo.IsDaylightSavingTime and are getting True when you expected False. Though this is confusing, and arguably incorrect, it is explainable:

    • In 2011, Moscow started the calendar year at UTC+3. It then changed its offset to UTC+4 on March 27 at 2:00 AM (reference here). This was a change in standard time, and not a DST related change.
    • The data structures in Windows (TIME_ZONE_INFORMATION, DYNAMIC_TIME_ZONE_INFORMATION, and more specifically, REG_TZI_FORMAT) do not support a change in standard offset in the middle of a calendar year. They were designed without this sort of change in mind - a very long time ago.
    • In order to accommodate the change in local time, it is modeled in Windows as a DST change, where the DST period starts on March 27th at 2:00 AM and runs through the very end of the year. This keeps the local time accurate over the transition, at the expense of returning inaccurate information from APIs that state or infer that their results are related explicitly to DST (such as System.TimeZoneInfo.IsDaylightSavingTime).
    • Thus, think of such methods as telling you if a period's local time is at a higher offset from UTC than at some other point in the year. It might be related to DST, or it might be related to a change in standard time.
  • As far as I can tell, Windows does indeed look to this data to determine whether to show the option or not. If there is a transition in the current calendar year (as determined by the system clock), then the option will be presented - regardless of if this transition was related to DST or due to some other reason.

Additionally, some general advice:

  • Most applications should not be trying to change the system time, time zone, or DST settings. Though indeed there are ways to do this, it can have drastic consequences. These are system-wide global settings, which will effect everything on the computer - not just your application.

    In particular, changing the time too drastically can impact the ability to authenticate correctly with other systems. For example, Windows Authentication (Active Directory, SSPI, etc.) uses Kerberos - which has a 5-minute tolerance from UTC. Additionally, accessing web sites that use security certificates (HTTPS, SSL, TLS, etc.) can fail if the certificate is expired or has not yet been issued, according to the system clock. Thus, the safest path to success is to set time automatically, and not allow the user to deviate.

    While changing the time zone and/or DST settings doesn't affect auth, it is still a global setting. Anywhere on the machine that is working with local time will pick up on this setting - not just your application.

  • If you are indeed going to be changing the time zone, keep in mind you may need to clear the local time zone cache to pick up on the new setting in your application. See this question and answer for more details.

  • If your intent was just to change the time zone for your application, then just keep track of the TimeZoneInfo.Id of the selected time zone and apply it through TimeZoneInfo.ConvertTime and related methods where needed.

  • You probably do not need to have a setting to disable automatic DST adjustment. The existence of this setting existing in Windows at all, is a legacy artifact from the original implementation of the time zone settings from the early days WinNT and Win9x. Most users should leave it on.

    Turning it off has only one legitimate use case these days, which is when a government announces a change in time zone from one that had DST to one that doesn't have DST (or has "permanent DST") and there is no other existing time zone entry that has the same base offset without DST and when said government does not provide enough time for Microsoft to create and distribute a new time zone entry for the affected region before the change goes into effect. Such things do happen, but are rare. IMHO, It would be reasonable for this setting to disappear at some point in the future. (Just my personal opinion, not speaking for Microsoft on this.)

Upvotes: 4

Related Questions