My local timezone is (UTC+10:00) Canberra, Melbourne, Sydney
Sat 31-Mar-2012 15:59 UTC = Sun 01-Apr-2012 02:59 +11:00
Sat 31-Mar-2012 16:00 UTC = Sun 01-Apr-2012 02:00 +10:00
Daylight savings finishes at 3 AM first Sunday in April and the clock wind back 1 hour.
Given the following code ....
DateTime dt1 = DateTime.Parse("31-Mar-2012 15:59", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal);
DateTime dt2 = DateTime.Parse("31-Mar-2012 15:59", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal).AddMinutes(1);
DateTime dt3 = DateTime.Parse("31-Mar-2012 16:00", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal);
Console.WriteLine("{0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt1);
Console.WriteLine("{0:yyyy-MMM-dd HH:mm:ss.ffff K} ({1}) = {2:yyyy-MMM-dd HH:mm:ss.ffff K} ({3})", dt2, dt2.Kind, dt3, dt3.Kind);
Console.WriteLine("{0} : {1} : {2}", dt1.ToUniversalTime().Hour, dt2.ToUniversalTime().Hour, dt3.ToUniversalTime().Hour);
I get the following output
2012-Apr-01 02:59:00.0000 +11:00
2012-Apr-01 03:00:00.0000 +10:00 (Local) = 2012-Apr-01 02:00:00.0000 +10:00 (Local)
15 : 17 : 16
Adding 1 minute to the original datetime makes the local time 3AM but also set the offset to +10 hours. Adding 1 minute to the UTC date and parsing correctly sets the local time to 2 AM with a +10 UTC offset.
Repeating with
DateTime dt1 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc);
DateTime dt2 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc).AddMinutes(1);
DateTime dt3 = new DateTime(2012, 03, 31, 16, 0, 0, DateTimeKind.Utc);
or
DateTime dt1 = DateTime.Parse("31-Mar-2012 15:59", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
DateTime dt2 = DateTime.Parse("31-Mar-2012 15:59", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal).AddMinutes(1);
DateTime dt3 = DateTime.Parse("31-Mar-2012 16:00", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
gives
2012-Mar-31 15:59:00.0000 Z
2012-Mar-31 16:00:00.0000 Z (Utc) = 2012-Mar-31 16:00:00.0000 Z (Utc)
15 : 16 : 16
as expected
Repeating again with
DateTime dt1 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc).ToLocalTime();
DateTime dt2 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc).ToLocalTime().AddMinutes(1);
DateTime dt3 = new DateTime(2012, 03, 31, 16, 0, 0, DateTimeKind.Utc).ToLocalTime();
gives the original
2012-Apr-01 02:59:00.0000 +11:00
2012-Apr-01 03:00:00.0000 +10:00 (Local) = 2012-Apr-01 02:00:00.0000 +10:00 (Local)
15 : 17 : 16
Can anyone explain this ?
Indecently if I use the TimeZoneInfo to convert from UTC to AUS Eastern Standard Time I get the correct time, but I lose the offset information in the DateTime instance as the DateTime.Kind == DateTimeKind.Unspecified
== Additional scenario to highlight
This is just simple timespan adding, starting with an NON-ambiguous UTC date, 1 minute before Daylight savings finishes.
DateTime dt1 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc);
DateTime dt2 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc).ToLocalTime();
Console.WriteLine("Original in UTC : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt1);
Console.WriteLine("Original in Local : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt1.ToLocalTime());
Console.WriteLine("+ 1 Minute in Local : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt1.AddMinutes(1).ToLocalTime());
Console.WriteLine("+ 1 Minute in UTC : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt1.AddMinutes(1));
Console.WriteLine("=====================================================");
Console.WriteLine("Original in UTC : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt2.ToUniversalTime());
Console.WriteLine("Original in Local : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt2);
Console.WriteLine("+ 1 Minute in Local : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt2.AddMinutes(1));
Console.WriteLine("+ 1 Minute in UTC : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt2.AddMinutes(1).ToUniversalTime());
gives
Original in UTC : 2012-Mar-31 15:59:00.0000 Z
Original in Local : 2012-Apr-01 02:59:00.0000 +11:00
+ 1 Minute in Local : 2012-Apr-01 02:00:00.0000 +10:00
+ 1 Minute in UTC : 2012-Mar-31 16:00:00.0000 Z
=====================================================
Original in UTC : 2012-Mar-31 15:59:00.0000 Z
Original in Local : 2012-Apr-01 02:59:00.0000 +11:00
+ 1 Minute in Local : 2012-Apr-01 03:00:00.0000 +10:00
+ 1 Minute in UTC : 2012-Mar-31 17:00:00.0000 Z