1

Closed

Time zone functionality not working

description

First let me thank you for publishing a .net solution for the Olson database. This will be very helpful.

I do have questions on functionality that I can't get to work. I am not sure whether I am doing something wrong. I read the writeup at http://www.codeproject.com/useritems/UsingtimezonesinNET.asp and that's where I got the sample code. I converted it to vb.net.

I can't get DST offsets to work correctly. This is what i tried for the Central/Chicago time zone:

Use cases below
Closed Aug 18, 2007 at 9:38 PM by schizoidboy
Maybe more bugs will follow...

comments

schizoidboy wrote Aug 10, 2007 at 2:40 AM

This is a bug in GetDaylightChanges which assumes that Rules are sorted by end date, whereas the proximity of rules may be due either to start date or end date, so we cannot depend solely on getting Rules "next to" the initially found rule.

MARIOIGREC wrote Aug 13, 2007 at 6:49 PM

Thank you fixing this so prompty. 1, 2, 3, and 5 are working. I am still having trouble with 4. I expanded the tests (the code is below), which show the following: 4a. With time zone set to central time (America/Chicago), for dates < year 2007, zone.ToUniversalTime always returns UTC times offset by 6 hours (as if DST was on year around). Example: --------- Converting local time to UTC -------------DST on rule <= 2006 for America/Chicago: Apr Sun>=1 2:00 (2am (8:00 UTC) becomes 3am)zone.ToUniversalTime('2006-04-02 01:00'): '4/2/2006 7:00:00 AM'zone.ToUniversalTime('2006-04-02 01:30'): '4/2/2006 7:30:00 AM'zone.ToUniversalTime('2006-04-02 02:00'): '4/2/2006 8:00:00 AM'zone.ToUniversalTime('2006-04-02 02:30'): '4/2/2006 8:30:00 AM'zone.ToUniversalTime('2006-04-02 03:00'): '4/2/2006 9:00:00 AM'zone.ToUniversalTime('2006-04-02 03:30'): '4/2/2006 9:30:00 AM'zone.ToUniversalTime('2006-04-02 04:00'): '4/2/2006 10:00:00 AM'zone.ToUniversalTime('2006-05-10 03:00'): '5/10/2006 9:00:00 AM' 4b. With time zone set to central time (America/Chicago), for dates >= year 2007, zone.ToUniversalTime always returns UTC times offset by 5 hours (as if DST was off year around). Example: DST on rule >= 2007 for America/Chicago: Mar Sun>=8 2:00 (2am (8:00 UTC) becomes 3am)zone.ToUniversalTime('2007-03-11 01:00'): '3/11/2007 6:00:00 AM'zone.ToUniversalTime('2007-03-11 01:30'): '3/11/2007 6:30:00 AM'zone.ToUniversalTime('2007-03-11 02:00'): '3/11/2007 7:00:00 AM'zone.ToUniversalTime('2007-03-11 02:30'): '3/11/2007 7:30:00 AM'zone.ToUniversalTime('2007-03-11 03:00'): '3/11/2007 8:00:00 AM'zone.ToUniversalTime('2007-03-11 03:30'): '3/11/2007 8:30:00 AM'zone.ToUniversalTime('2007-03-11 04:00'): '3/11/2007 9:00:00 AM'zone.ToUniversalTime('2007-05-10 03:00'): '5/10/2007 8:00:00 AM' 4c. Both in America/Chicago and Europe/Paris zones, zone.ToLocalTime returns the time unconverted (UTC and local time is the same). Example: --------- Converting UTC to local time -------------DST on rule <= 2006 for America/Chicago: Apr Sun>=1 2:00 (2am (8:00 UTC) becomes 3am)zone.ToLocalTime('2006-04-02 07:00'): '4/2/2006 7:00:00 AM'zone.ToLocalTime('2006-04-02 07:30'): '4/2/2006 7:30:00 AM'zone.ToLocalTime('2006-04-02 08:00'): '4/2/2006 8:00:00 AM'zone.ToLocalTime('2006-04-02 08:30'): '4/2/2006 8:30:00 AM'zone.ToLocalTime('2006-04-02 09:00'): '4/2/2006 9:00:00 AM' 4d. With the zone set to Europe/Paris, zone.ToUniversalTime always returns an offset at 2 hours, which is as if DST was on year around. This is similar to the behavior of America/Chicago zone for year <= 2006. Example: DST on rule for Europe/Paris: Mar lastSun 1:00u (2am (1:00 UTC) becomes 3am)zone.ToUniversalTime('2007-03-25 00:00'): '3/24/2007 10:00:00 PM'zone.ToUniversalTime('2007-03-25 01:00'): '3/24/2007 11:00:00 PM'zone.ToUniversalTime('2007-03-25 02:00'): '3/25/2007'zone.ToUniversalTime('2007-03-25 02:30'): '3/25/2007 12:30:00 AM'zone.ToUniversalTime('2007-03-25 03:00'): '3/25/2007 1:00:00 AM'zone.ToUniversalTime('2007-03-25 03:30'): '3/25/2007 1:30:00 AM'zone.ToUniversalTime('2007-03-25 04:00'): '3/25/2007 2:00:00 AM'zone.ToUniversalTime('2007-03-25 04:30'): '3/25/2007 2:30:00 AM'zone.ToUniversalTime('2007-09-12 03:00'): '9/12/2007 1:00:00 AM' --------------------------------------My complete testing code: Dim s2 as string = "" Dim zone As PublicDomain.TzTimeZone Dim dtDate As PublicDomain.TzDateTime s2 &= "============ Zone America/Chicago (GMT-06:00) =============" & vbCrLf zone = PublicDomain.TzTimeZone.GetTimeZone(PublicDomain.TzConstants.TimezoneAmericaChicago) s2 &= "zone.StandardName: '" & zone.StandardName & "'" & vbCrLf s2 &= "zone.GetUtcOffset(Now).TotalHours: '" & zone.GetUtcOffset(Now).TotalHours.ToString & "'" & vbCrLf s2 &= "zone.ToUniversalTime(now): '" & zone.ToUniversalTime(Now) & "'" & vbCrLf s2 &= "zone.DaylightName(): '" & zone.DaylightName() & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2004).Start: '" & zone.GetDaylightChanges(2004).Start & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2004).End: '" & zone.GetDaylightChanges(2004).End & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2005).Start: '" & zone.GetDaylightChanges(2005).Start & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2005).End: '" & zone.GetDaylightChanges(2005).End & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2006).Start: '" & zone.GetDaylightChanges(2006).Start & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2006).End: '" & zone.GetDaylightChanges(2006).End & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2007).Start: '" & zone.GetDaylightChanges(2007).Start & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2007).End: '" & zone.GetDaylightChanges(2007).End & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2008).Start: '" & zone.GetDaylightChanges(2008).Start & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2008).End: '" & zone.GetDaylightChanges(2008).End & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2009).Start: '" & zone.GetDaylightChanges(2009).Start & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2009).End: '" & zone.GetDaylightChanges(2009).End & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2010).Start: '" & zone.GetDaylightChanges(2010).Start & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2010).End: '" & zone.GetDaylightChanges(2010).End & "'" & vbCrLf s2 &= "--------------" & vbCrLf dtDate = New PublicDomain.TzDateTime(zone.ToLocalTime(DateTime.UtcNow), zone) dtDate.DateTimeLocal = "2007-09-12 03:00" s2 &= "dtDate.DateTimeLocal = '2007-09-12 03:00'" & vbCrLf s2 &= "zone.GetUtcOffset(dtDate).TotalHours: '" & zone.GetUtcOffset(dtDate.DateTimeLocal).TotalHours & "'" & vbCrLf dtDate.DateTimeLocal = "2007-12-12 03:00" s2 &= "dtDate.DateTimeLocal = '2007-12-12 03:00'" & vbCrLf s2 &= "zone.GetUtcOffset(dtDate).TotalHours: '" & zone.GetUtcOffset(dtDate.DateTimeLocal).TotalHours & "'" & vbCrLf s2 &= "zone.IsDaylightSavingTime(Now): '" & zone.IsDaylightSavingTime(Now) & "'" & vbCrLf s2 &= "zone.IsDaylightSavingTime('2007-09-15'): '" & zone.IsDaylightSavingTime("2007-09-15") & "'" & vbCrLf s2 &= "zone.IsDaylightSavingTime('2007-12-15'): '" & zone.IsDaylightSavingTime("2007-12-15") & "'" & vbCrLf s2 &= "zone.IsDaylightSavingTime('2008-09-15'): '" & zone.IsDaylightSavingTime("2008-09-15") & "'" & vbCrLf s2 &= "zone.IsDaylightSavingTime('2008-12-15'): '" & zone.IsDaylightSavingTime("2008-12-15") & "'" & vbCrLf s2 &= "zone.IsDaylightSavingTime('2016-09-15'): '" & zone.IsDaylightSavingTime("2016-09-15") & "'" & vbCrLf s2 &= "zone.IsDaylightSavingTime('2016-12-15'): '" & zone.IsDaylightSavingTime("2016-12-15") & "'" & vbCrLf s2 &= "zone.IsDaylightSavingTime('1974-09-15'): '" & zone.IsDaylightSavingTime("1974-09-15") & "'" & vbCrLf s2 &= "zone.IsDaylightSavingTime('1974-12-15'): '" & zone.IsDaylightSavingTime("1974-12-15") & "'" & vbCrLf s2 &= "--------- Converting local time to UTC -------------" & vbCrLf s2 &= "DST on rule <= 2006 for America/Chicago: Apr Sun>=1 2:00 (2am (8:00 UTC) becomes 3am)" & vbCrLf s2 &= "zone.ToUniversalTime('2006-04-02 01:00'): '" & zone.ToUniversalTime("2006-04-02 01:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2006-04-02 01:30'): '" & zone.ToUniversalTime("2006-04-02 01:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2006-04-02 02:00'): '" & zone.ToUniversalTime("2006-04-02 02:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2006-04-02 02:30'): '" & zone.ToUniversalTime("2006-04-02 02:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2006-04-02 03:00'): '" & zone.ToUniversalTime("2006-04-02 03:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2006-04-02 03:30'): '" & zone.ToUniversalTime("2006-04-02 03:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2006-04-02 04:00'): '" & zone.ToUniversalTime("2006-04-02 04:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2006-05-10 03:00'): '" & zone.ToUniversalTime("2006-05-10 03:00") & "'" & vbCrLf s2 &= "DST off rule <= 2006 for America/Chicago: Nov Sun>=1 2:00 (2am (7:00 UTC) becomes 1am)" & vbCrLf s2 &= "zone.ToUniversalTime('2006-10-29 00:00'): '" & zone.ToUniversalTime("2006-10-29 00:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2006-10-29 00:30'): '" & zone.ToUniversalTime("2006-10-29 00:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2006-11-04 01:00'): '" & zone.ToUniversalTime("2006-11-04 01:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2006-11-04 01:30'): '" & zone.ToUniversalTime("2006-11-04 01:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2006-11-04 02:00'): '" & zone.ToUniversalTime("2006-11-04 02:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2006-11-04 02:30'): '" & zone.ToUniversalTime("2006-11-04 02:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2006-11-04 03:00'): '" & zone.ToUniversalTime("2006-11-04 03:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2006-12-12 03:00'): '" & zone.ToUniversalTime("2006-12-12 03:00") & "'" & vbCrLf s2 &= "DST on rule >= 2007 for America/Chicago: Mar Sun>=8 2:00 (2am (8:00 UTC) becomes 3am)" & vbCrLf s2 &= "zone.ToUniversalTime('2007-03-11 01:00'): '" & zone.ToUniversalTime("2007-03-11 01:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-03-11 01:30'): '" & zone.ToUniversalTime("2007-03-11 01:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-03-11 02:00'): '" & zone.ToUniversalTime("2007-03-11 02:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-03-11 02:30'): '" & zone.ToUniversalTime("2007-03-11 02:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-03-11 03:00'): '" & zone.ToUniversalTime("2007-03-11 03:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-03-11 03:30'): '" & zone.ToUniversalTime("2007-03-11 03:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-03-11 04:00'): '" & zone.ToUniversalTime("2007-03-11 04:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-05-10 03:00'): '" & zone.ToUniversalTime("2007-05-10 03:00") & "'" & vbCrLf s2 &= "DST off rule >= 2007 for America/Chicago: Nov Sun>=1 2:00 (2am (7:00 UTC) becomes 1am)" & vbCrLf s2 &= "zone.ToUniversalTime('2007-11-04 00:00'): '" & zone.ToUniversalTime("2007-11-04 00:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-11-04 01:00'): '" & zone.ToUniversalTime("2007-11-04 01:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-11-04 01:30'): '" & zone.ToUniversalTime("2007-11-04 01:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-11-04 02:00'): '" & zone.ToUniversalTime("2007-11-04 02:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-11-04 02:30'): '" & zone.ToUniversalTime("2007-11-04 02:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-11-04 03:00'): '" & zone.ToUniversalTime("2007-11-04 03:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-11-04 03:30'): '" & zone.ToUniversalTime("2007-11-04 03:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-12-12 03:00'): '" & zone.ToUniversalTime("2007-12-12 03:00") & "'" & vbCrLf s2 &= "DST on rule >= 2007 for America/Chicago: Mar Sun>=8 2:00 (2am (8:00 UTC) becomes 3am)" & vbCrLf s2 &= "zone.ToUniversalTime('2008-03-09 01:00'): '" & zone.ToUniversalTime("2008-03-09 01:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-03-09 01:30'): '" & zone.ToUniversalTime("2008-03-09 01:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-03-09 02:00'): '" & zone.ToUniversalTime("2008-03-09 02:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-03-09 02:30'): '" & zone.ToUniversalTime("2008-03-09 02:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-03-09 03:00'): '" & zone.ToUniversalTime("2008-03-09 03:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-03-09 03:30'): '" & zone.ToUniversalTime("2008-03-09 03:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-03-09 04:00'): '" & zone.ToUniversalTime("2008-03-09 04:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-05-10 03:00'): '" & zone.ToUniversalTime("2008-05-10 03:00") & "'" & vbCrLf s2 &= "DST off rule >= 2007 for America/Chicago: Nov Sun>=1 2:00 (2am (7:00 UTC) becomes 1am)" & vbCrLf s2 &= "zone.ToUniversalTime('2008-11-02 00:00'): '" & zone.ToUniversalTime("2008-11-02 00:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-11-02 01:00'): '" & zone.ToUniversalTime("2008-11-02 01:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-11-02 01:30'): '" & zone.ToUniversalTime("2008-11-02 01:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-11-02 02:00'): '" & zone.ToUniversalTime("2008-11-02 02:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-11-02 02:30'): '" & zone.ToUniversalTime("2008-11-02 02:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-11-02 03:00'): '" & zone.ToUniversalTime("2008-11-02 03:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-11-02 03:30'): '" & zone.ToUniversalTime("2008-11-02 03:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-12-12 03:00'): '" & zone.ToUniversalTime("2008-12-12 03:00") & "'" & vbCrLf s2 &= "--------- Converting UTC to local time -------------" & vbCrLf s2 &= "DST on rule <= 2006 for America/Chicago: Apr Sun>=1 2:00 (2am (8:00 UTC) becomes 3am)" & vbCrLf s2 &= "zone.ToLocalTime('2006-04-02 07:00'): '" & zone.ToLocalTime("2006-04-02 07:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2006-04-02 07:30'): '" & zone.ToLocalTime("2006-04-02 07:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2006-04-02 08:00'): '" & zone.ToLocalTime("2006-04-02 08:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2006-04-02 08:30'): '" & zone.ToLocalTime("2006-04-02 08:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2006-04-02 09:00'): '" & zone.ToLocalTime("2006-04-02 09:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2006-04-02 09:30'): '" & zone.ToLocalTime("2006-04-02 09:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2006-04-02 10:00'): '" & zone.ToLocalTime("2006-04-02 10:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2006-05-10 03:00'): '" & zone.ToLocalTime("2006-05-10 03:00") & "'" & vbCrLf s2 &= "DST off rule <= 2006 for America/Chicago: Nov Sun>=1 2:00 (2am (7:00 UTC) becomes 1am)" & vbCrLf s2 &= "zone.ToLocalTime('2006-10-29 06:00'): '" & zone.ToLocalTime("2006-10-29 06:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2006-10-29 06:30'): '" & zone.ToLocalTime("2006-10-29 06:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2006-11-04 07:00'): '" & zone.ToLocalTime("2006-11-04 07:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2006-11-04 07:30'): '" & zone.ToLocalTime("2006-11-04 07:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2006-11-04 08:00'): '" & zone.ToLocalTime("2006-11-04 08:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2006-11-04 08:30'): '" & zone.ToLocalTime("2006-11-04 08:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2006-11-04 09:00'): '" & zone.ToLocalTime("2006-11-04 09:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2006-12-12 03:00'): '" & zone.ToLocalTime("2006-12-12 03:00") & "'" & vbCrLf s2 &= "DST on rule >= 2007 for America/Chicago: Mar Sun>=8 2:00 (2am (8:00 UTC) becomes 3am)" & vbCrLf s2 &= "zone.ToLocalTime('2007-03-11 07:00'): '" & zone.ToLocalTime("2007-03-11 07:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-03-11 07:30'): '" & zone.ToLocalTime("2007-03-11 07:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-03-11 08:00'): '" & zone.ToLocalTime("2007-03-11 08:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-03-11 08:30'): '" & zone.ToLocalTime("2007-03-11 08:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-03-11 09:00'): '" & zone.ToLocalTime("2007-03-11 09:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-03-11 09:30'): '" & zone.ToLocalTime("2007-03-11 09:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-03-11 10:00'): '" & zone.ToLocalTime("2007-03-11 10:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-05-10 03:00'): '" & zone.ToLocalTime("2007-05-10 03:00") & "'" & vbCrLf s2 &= "DST off rule >= 2007 for America/Chicago: Nov Sun>=1 2:00 (2am (7:00 UTC) becomes 1am)" & vbCrLf s2 &= "zone.ToLocalTime('2007-11-04 06:00'): '" & zone.ToLocalTime("2007-11-04 06:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-11-04 06:30'): '" & zone.ToLocalTime("2007-11-04 06:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-11-04 07:00'): '" & zone.ToLocalTime("2007-11-04 07:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-11-04 07:30'): '" & zone.ToLocalTime("2007-11-04 07:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-11-04 08:00'): '" & zone.ToLocalTime("2007-11-04 08:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-11-04 08:30'): '" & zone.ToLocalTime("2007-11-04 08:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-11-04 09:00'): '" & zone.ToLocalTime("2007-11-04 09:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-12-12 03:00'): '" & zone.ToLocalTime("2007-12-12 03:00") & "'" & vbCrLf s2 &= "DST on rule >= 2007 for America/Chicago: Mar Sun>=8 2:00 (2am (8:00 UTC) becomes 3am)" & vbCrLf s2 &= "zone.ToLocalTime('2008-03-09 07:00'): '" & zone.ToLocalTime("2008-03-09 07:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-03-09 07:30'): '" & zone.ToLocalTime("2008-03-09 07:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-03-09 08:00'): '" & zone.ToLocalTime("2008-03-09 08:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-03-09 08:30'): '" & zone.ToLocalTime("2008-03-09 08:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-03-09 09:00'): '" & zone.ToLocalTime("2008-03-09 09:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-03-09 09:30'): '" & zone.ToLocalTime("2008-03-09 09:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-03-09 10:00'): '" & zone.ToLocalTime("2008-03-09 10:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-05-10 03:00'): '" & zone.ToLocalTime("2008-05-10 03:00") & "'" & vbCrLf s2 &= "DST off rule >= 2007 for America/Chicago: Nov Sun>=1 2:00 (2am (7:00 UTC) becomes 1am)" & vbCrLf s2 &= "zone.ToLocalTime('2008-11-02 06:00'): '" & zone.ToLocalTime("2008-11-02 06:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-11-02 06:30'): '" & zone.ToLocalTime("2008-11-02 06:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-11-02 07:00'): '" & zone.ToLocalTime("2008-11-02 07:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-11-02 07:30'): '" & zone.ToLocalTime("2008-11-02 07:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-11-02 08:00'): '" & zone.ToLocalTime("2008-11-02 08:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-11-02 08:30'): '" & zone.ToLocalTime("2008-11-02 08:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-11-02 09:00'): '" & zone.ToLocalTime("2008-11-02 09:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-12-12 03:00'): '" & zone.ToLocalTime("2008-12-12 03:00") & "'" & vbCrLf s2 &= vbCrLf ''Get a common time zone 'zone = TzTimeZone.ZoneUsEastern '// Get a zone in the time zone database by the constant 'zone = TzTimeZone.GetTimeZone(TzConstants.TimezoneEuropeParis) 's2 &= "zone.StandardName: '" & zone.StandardName & "'" & vbCrLf s2 &= "============ Zone Europe/Paris (GMT+01:00) =============" & vbCrLf 'Get a zone in the database by its name zone = PublicDomain.TzTimeZone.GetTimeZone("Europe/Paris") s2 &= "zone = PublicDomain.TzTimeZone.GetTimeZone('Europe/Paris')" & vbCrLf s2 &= "zone.GetUtcOffset(Now).TotalHours: '" & zone.GetUtcOffset(Now).TotalHours.ToString & "'" & vbCrLf s2 &= "zone.ToUniversalTime(now): '" & zone.ToUniversalTime(Now) & "'" & vbCrLf s2 &= "zone.DaylightName(): '" & zone.DaylightName() & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2004).Start: '" & zone.GetDaylightChanges(2004).Start & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2004).End: '" & zone.GetDaylightChanges(2004).End & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2005).Start: '" & zone.GetDaylightChanges(2005).Start & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2005).End: '" & zone.GetDaylightChanges(2005).End & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2006).Start: '" & zone.GetDaylightChanges(2006).Start & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2006).End: '" & zone.GetDaylightChanges(2006).End & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2007).Start: '" & zone.GetDaylightChanges(2007).Start & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2007).End: '" & zone.GetDaylightChanges(2007).End & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2008).Start: '" & zone.GetDaylightChanges(2008).Start & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2008).End: '" & zone.GetDaylightChanges(2008).End & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2009).Start: '" & zone.GetDaylightChanges(2009).Start & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2009).End: '" & zone.GetDaylightChanges(2009).End & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2010).Start: '" & zone.GetDaylightChanges(2010).Start & "'" & vbCrLf s2 &= "zone.GetDaylightChanges(2010).End: '" & zone.GetDaylightChanges(2010).End & "'" & vbCrLf s2 &= "---------------" & vbCrLf dtDate = New PublicDomain.TzDateTime(zone.ToLocalTime(DateTime.UtcNow), zone) 'DST dtDate.DateTimeLocal = "2007-09-12 03:00" s2 &= "dtDate.DateTimeLocal = '2007-09-12 03:00'" & vbCrLf s2 &= "zone.GetUtcOffset(dtDate).TotalHours: '" & zone.GetUtcOffset(dtDate.DateTimeLocal).TotalHours & "'" & vbCrLf 'Non-DST dtDate.DateTimeLocal = "2007-12-12 03:00" s2 &= "dtDate.DateTimeLocal = '2007-12-12 03:00'" & vbCrLf s2 &= "zone.GetUtcOffset(dtDate).TotalHours: '" & zone.GetUtcOffset(dtDate.DateTimeLocal).TotalHours & "'" & vbCrLf 'IsDaylightSavingTime s2 &= "zone.IsDaylightSavingTime(Now): '" & zone.IsDaylightSavingTime(Now) & "'" & vbCrLf s2 &= "zone.IsDaylightSavingTime('2007-09-15'): '" & zone.IsDaylightSavingTime("2007-09-15") & "'" & vbCrLf s2 &= "zone.IsDaylightSavingTime('2007-12-15'): '" & zone.IsDaylightSavingTime("2007-12-15") & "'" & vbCrLf s2 &= "zone.IsDaylightSavingTime('2008-09-15'): '" & zone.IsDaylightSavingTime("2008-09-15") & "'" & vbCrLf s2 &= "zone.IsDaylightSavingTime('2008-12-15'): '" & zone.IsDaylightSavingTime("2008-12-15") & "'" & vbCrLf s2 &= "zone.IsDaylightSavingTime('2016-09-15'): '" & zone.IsDaylightSavingTime("2016-09-15") & "'" & vbCrLf s2 &= "zone.IsDaylightSavingTime('2016-12-15'): '" & zone.IsDaylightSavingTime("2016-12-15") & "'" & vbCrLf s2 &= "zone.IsDaylightSavingTime('1974-09-15'): '" & zone.IsDaylightSavingTime("1974-09-15") & "'" & vbCrLf s2 &= "zone.IsDaylightSavingTime('1974-12-15'): '" & zone.IsDaylightSavingTime("1974-12-15") & "'" & vbCrLf s2 &= "--------- Converting local time to UTC -------------" & vbCrLf 'ToUniversalTime around DST breaks s2 &= "zone.ToUniversalTime('2007-01-25 00:00'): '" & zone.ToUniversalTime("2007-01-25 00:00") & "'" & vbCrLf s2 &= "DST on rule for Europe/Paris: Mar lastSun 1:00u (2am (1:00 UTC) becomes 3am)" & vbCrLf s2 &= "zone.ToUniversalTime('2007-03-25 00:00'): '" & zone.ToUniversalTime("2007-03-25 00:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-03-25 01:00'): '" & zone.ToUniversalTime("2007-03-25 01:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-03-25 02:00'): '" & zone.ToUniversalTime("2007-03-25 02:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-03-25 02:30'): '" & zone.ToUniversalTime("2007-03-25 02:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-03-25 03:00'): '" & zone.ToUniversalTime("2007-03-25 03:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-03-25 03:30'): '" & zone.ToUniversalTime("2007-03-25 03:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-03-25 04:00'): '" & zone.ToUniversalTime("2007-03-25 04:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-03-25 04:30'): '" & zone.ToUniversalTime("2007-03-25 04:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-09-12 03:00'): '" & zone.ToUniversalTime("2007-09-12 03:00") & "'" & vbCrLf s2 &= "DST off rule for Europe/Paris: Oct lastSun 1:00u (3am (1:00 UTC) becomes 2am)" & vbCrLf s2 &= "zone.ToUniversalTime('2007-10-28 00:00'): '" & zone.ToUniversalTime("2007-10-28 00:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-10-28 01:00'): '" & zone.ToUniversalTime("2007-10-28 01:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-10-28 01:30'): '" & zone.ToUniversalTime("2007-10-28 01:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-10-28 02:00'): '" & zone.ToUniversalTime("2007-10-28 02:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-10-28 02:30'): '" & zone.ToUniversalTime("2007-10-28 02:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-10-28 03:00'): '" & zone.ToUniversalTime("2007-10-28 03:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-10-28 03:30'): '" & zone.ToUniversalTime("2007-10-28 03:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-10-28 04:00'): '" & zone.ToUniversalTime("2007-10-28 04:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2007-12-12 03:00'): '" & zone.ToUniversalTime("2007-12-12 03:00") & "'" & vbCrLf s2 &= "DST on rule for Europe/Paris: Mar lastSun 1:00u (2am (1:00 UTC) becomes 3am)" & vbCrLf s2 &= "zone.ToUniversalTime('2008-03-30 00:00'): '" & zone.ToUniversalTime("2008-03-30 00:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-03-30 01:00'): '" & zone.ToUniversalTime("2008-03-30 01:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-03-30 02:00'): '" & zone.ToUniversalTime("2008-03-30 02:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-03-30 02:30'): '" & zone.ToUniversalTime("2008-03-30 02:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-03-30 03:00'): '" & zone.ToUniversalTime("2008-03-30 03:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-03-30 03:30'): '" & zone.ToUniversalTime("2008-03-30 03:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-03-30 04:00'): '" & zone.ToUniversalTime("2008-03-30 04:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-03-30 04:30'): '" & zone.ToUniversalTime("2008-03-30 04:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-05-10 03:00'): '" & zone.ToUniversalTime("2008-05-10 03:00") & "'" & vbCrLf s2 &= "DST off rule for Europe/Paris: Oct lastSun 1:00u (3am (1:00 UTC) becomes 2am)" & vbCrLf s2 &= "zone.ToUniversalTime('2008-10-26 00:00'): '" & zone.ToUniversalTime("2008-10-26 00:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-10-26 01:00'): '" & zone.ToUniversalTime("2008-10-26 01:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-10-26 01:30'): '" & zone.ToUniversalTime("2008-10-26 01:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-10-26 02:00'): '" & zone.ToUniversalTime("2008-10-26 02:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-10-26 02:30'): '" & zone.ToUniversalTime("2008-10-26 02:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-10-26 03:00'): '" & zone.ToUniversalTime("2008-10-26 03:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-10-26 03:30'): '" & zone.ToUniversalTime("2008-10-26 03:30") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-10-26 04:00'): '" & zone.ToUniversalTime("2008-10-26 04:00") & "'" & vbCrLf s2 &= "zone.ToUniversalTime('2008-12-12 03:00'): '" & zone.ToUniversalTime("2008-12-12 03:00") & "'" & vbCrLf s2 &= "--------- Converting UTC to local time -------------" & vbCrLf s2 &= "zone.ToLocalTime('2007-01-25 00:00'): '" & zone.ToLocalTime("2007-01-25 00:00") & "'" & vbCrLf s2 &= "DST on rule for Europe/Paris: Mar lastSun 1:00u (2am (1:00 UTC) becomes 3am)" & vbCrLf s2 &= "zone.ToLocalTime('2007-03-25 00:00'): '" & zone.ToLocalTime("2007-03-25 00:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-03-25 00:30'): '" & zone.ToLocalTime("2007-03-25 00:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-03-25 01:00'): '" & zone.ToLocalTime("2007-03-25 01:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-03-25 01:30'): '" & zone.ToLocalTime("2007-03-25 01:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-03-25 02:00'): '" & zone.ToLocalTime("2007-03-25 02:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-03-25 02:30'): '" & zone.ToLocalTime("2007-03-25 02:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-03-25 03:00'): '" & zone.ToLocalTime("2007-03-25 03:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-03-25 04:00'): '" & zone.ToLocalTime("2007-03-25 04:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-09-12 03:00'): '" & zone.ToLocalTime("2007-09-12 03:00") & "'" & vbCrLf s2 &= "DST off rule for Europe/Paris: Oct lastSun 1:00u (3am (1:00 UTC) becomes 2am)" & vbCrLf s2 &= "zone.ToLocalTime('2007-10-28 00:00'): '" & zone.ToLocalTime("2007-10-28 00:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-10-28 00:30'): '" & zone.ToLocalTime("2007-10-28 00:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-10-28 01:00'): '" & zone.ToLocalTime("2007-10-28 01:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-10-28 01:30'): '" & zone.ToLocalTime("2007-10-28 01:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-10-28 02:00'): '" & zone.ToLocalTime("2007-10-28 02:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-10-28 02:30'): '" & zone.ToLocalTime("2007-10-28 02:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-10-28 03:00'): '" & zone.ToLocalTime("2007-10-28 03:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-10-28 04:00'): '" & zone.ToLocalTime("2007-10-28 04:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2007-12-12 03:00'): '" & zone.ToLocalTime("2007-12-12 03:00") & "'" & vbCrLf s2 &= "DST on rule for Europe/Paris: Mar lastSun 1:00u (2am (1:00 UTC) becomes 3am)" & vbCrLf s2 &= "zone.ToLocalTime('2008-03-30 00:00'): '" & zone.ToLocalTime("2008-03-30 00:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-03-30 00:30'): '" & zone.ToLocalTime("2008-03-30 00:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-03-30 01:00'): '" & zone.ToLocalTime("2008-03-30 01:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-03-30 01:30'): '" & zone.ToLocalTime("2008-03-30 01:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-03-30 02:00'): '" & zone.ToLocalTime("2008-03-30 02:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-03-30 02:30'): '" & zone.ToLocalTime("2008-03-30 02:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-03-30 03:00'): '" & zone.ToLocalTime("2008-03-30 03:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-03-30 04:00'): '" & zone.ToLocalTime("2008-03-30 04:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-05-10 03:00'): '" & zone.ToLocalTime("2008-05-10 03:00") & "'" & vbCrLf s2 &= "DST off rule for Europe/Paris: Oct lastSun 1:00u (3am (1:00 UTC) becomes 2am)" & vbCrLf s2 &= "zone.ToLocalTime('2008-10-26 00:00'): '" & zone.ToLocalTime("2008-10-26 00:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-10-26 00:30'): '" & zone.ToLocalTime("2008-10-26 00:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-10-26 01:00'): '" & zone.ToLocalTime("2008-10-26 01:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-10-26 01:30'): '" & zone.ToLocalTime("2008-10-26 01:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-10-26 02:00'): '" & zone.ToLocalTime("2008-10-26 02:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-10-26 02:30'): '" & zone.ToLocalTime("2008-10-26 02:30") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-10-26 03:00'): '" & zone.ToLocalTime("2008-10-26 03:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-10-26 04:00'): '" & zone.ToLocalTime("2008-10-26 04:00") & "'" & vbCrLf s2 &= "zone.ToLocalTime('2008-12-12 03:00'): '" & zone.ToLocalTime("2008-12-12 03:00") & "'" & vbCrLf

schizoidboy wrote Aug 13, 2007 at 7:22 PM

Bugs fixed in release 0.2.12.0

** Closed by schizoidboy 8/9/2007 10:14 PM

schizoidboy wrote Aug 13, 2007 at 7:22 PM

More bugs discovered

schizoidboy wrote Aug 18, 2007 at 8:49 PM

Thanks for the latest additional bugs. I have found a bug in code common to both ToUniversalTime and ToLocalTime. I'm currently working on the fix and some regression tests, but one thing I noticed is that when you are testing zone.ToLocalTime, you are using implicit DateTime creation which uses DateTime.Parse, and that creates a DateTime with a Kind of Unspecified.

In this case, ToLocalTime has no way to know what type of DateTime you passed it. There is a public property on TzDateTime called TreatUnspecifiedKindAsLocal which treats this case and assumes the kind is Local. This is much more common since users normally are dealing with local date/times (unless using things like DateTime.UtcNow [which has Kind specified correctly]).

I think this contract makes sense, so I think your tests are slightly flawed. I will make the comment in ToLocalTime more clear for the user to be careful, but it does say that a UTC DateTime is expected.

To fix your tests, the easiest way is to change from:

zone.ToLocalTime(DateTime.Parse("2008-12-12 03:00"))

to:

ToUniversalTime and ToLocalTime. I'm currently working on the fix and some regression tests, but one thing I noticed is that when you are testing zone.ToLocalTime, you are using implicit DateTime creation which uses DateTime.Parse, and that creates a DateTime with a Kind of Unspecified.

In this case, ToLocalTime has no way to know what type of DateTime you passed it. There is a public property on TzDateTime called TreatUnspecifiedKindAsLocal which treats this case and assumes the kind is Local. This is much more common since users normally are dealing with local date/times (unless using things like DateTime.UtcNow [which has Kind specified correctly]).

I think this contract makes sense, so I think your tests are slightly flawed. I will make the comment in ToLocalTime more clear for the user to be careful, but it does say that a UTC DateTime is expected.

To fix your tests, the easiest way is to change from:

zone.ToLocalTime(new DateTime(DateTime.Parse("2006-04-02 07:00").Ticks, DateTimeKind.Utc))

Whatever the equivalent in VB.Net is to that. Basically, you have to explicitly create a DateTime with the right UTC Kind.

schizoidboy wrote Aug 18, 2007 at 8:51 PM

CodePlex screwed up my last comment:

Thanks for the latest additional bugs. I have found a bug in code common to both ToUniversalTime and ToLocalTime. I'm currently working on the fix and some regression tests, but one thing I noticed is that when you are testing zone.ToLocalTime, you are using implicit DateTime creation which uses DateTime.Parse, and that creates a DateTime with a Kind of Unspecified.

In this case, ToLocalTime has no way to know what type of DateTime you passed it. There is a public property on TzDateTime called TreatUnspecifiedKindAsLocal which treats this case and assumes the kind is Local. This is much more common since users normally are dealing with local date/times (unless using things like DateTime.UtcNow [which has Kind specified correctly]).

I think this contract makes sense, so I think your tests are slightly flawed. I will make the comment in ToLocalTime more clear for the user to be careful, but it does say that a UTC DateTime is expected.

To fix your tests, the easiest way is to change from:

zone.ToLocalTime(DateTime.Parse("2008-12-12 03:00"))

to:

zone.ToLocalTime(new DateTime(DateTime.Parse("2006-04-02 07:00").Ticks, DateTimeKind.Utc))

Whatever the equivalent in VB.Net is to that. Basically, you have to explicitly create a DateTime with the right UTC Kind.

schizoidboy wrote Aug 18, 2007 at 9:30 PM

Also, I don't think the ToLocalTime tests are really valid on the boundary cases. For example, if the TimeZone is America/Chicago, the results of ToUniversalTime are:

zone.ToUniversalTime('2006-04-02 01:00'): '4/2/2006 7:00:00 AM'zone.ToUniversalTime('2006-04-02 02:00'): '4/2/2006 7:00:00 AM'zone.ToUniversalTime('2006-04-02 03:00'): '4/2/2006 8:00:00 AM'

Of course, as you can see the UTC time 4/2/2006 7:00:00 AM is completely ambiguous in terms of converting it back to local time. It could either be 2006-04-02 01:00 or 2006-04-02 02:00.

I have done some research on this, and a Microsoft BCL dev actually mentioned that the design of ToLocalTime is ambiguous.

Therefore, the best we shoot for is getting it pretty close :-).