DateTime — Странное поведение при переходе на летнее время

Мой местный часовой пояс: (UTC+10:00) Канберра, Мельбурн, Сидней

Сб, 31 марта 2012 г., 15:59 UTC = Воскресенье, 01 апреля 2012 г., 02:59 +11:00
Сб, 31 марта 2012 г., 16:00 UTC = вс, 01 апреля 2012 г., 02:00 +10:00

Летнее время заканчивается в 3:00 первого воскресенья апреля, а часы переводятся на 1 час назад.

Учитывая следующий код....

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);

Я получаю следующий вывод

2012-Apr-01 02:59:00.0000 +11:00
2012-Apr-01 03:00:00.0000 +10:00 (Местный) = 2012-Apr-01 02:00:00.0000 +10:00 (Местный)
15 : 17 : 16

Добавление 1 минуты к исходной дате и времени делает местное время 3:00, но также устанавливает смещение на +10 часов. Добавление 1 минуты к дате UTC и правильный синтаксический анализ устанавливает местное время в 2 часа ночи со смещением +10 UTC.

Повторение с

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);

или

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); 

дает

2012-Mar-31 15:59:00.0000 Z
2012-март-31 16:00:00.0000 Z (UTC) = 2012-март-31 16:00:00.0000 Z (UTC)
15 : 16 : 16

как и ожидалось

Повторение снова с

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();

дает оригинал

2012-Apr-01 02:59:00.0000 +11:00
2012-Apr-01 03:00:00.0000 +10:00 (Местный) = 2012-Apr-01 02:00:00.0000 +10:00 (Местный)
15 : 17 : 16

Кто-нибудь может объяснить это?

Неприлично, если я использую TimeZoneInfo для преобразования из UTC в Восточное стандартное время Австралии, я получаю правильное время, но я теряю информацию о смещении в экземпляре DateTime как DateTime .Kind == DateTimeKind.Unspecified

== Дополнительный сценарий для выделения

Это просто добавление временного промежутка, начиная с недвусмысленной даты UTC, за 1 минуту до завершения перехода на летнее время.

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());  

дает

Оригинал в UTC: 2012-Mar-31 15:59:00.0000 Z
Оригинал на местном языке: 2012-Apr-01 02:59:00.0000 +11:00
+ 1 минута в местном режиме: 2012-Apr-01 02:00:00.0000 +10:00
+ 1 минута в UTC: 2012-март-31 16:00:00.0000 Z

======================== =============================

Оригинал в формате UTC: 31 марта 2012 г., 15:59:00.0000 Z
Оригинал на местном языке: 2012-Apr-01 02:59:00.0000 +11:00
+ 1 минута в местном режиме: 2012-Apr-01 03:00:00.0000 +10:00
+ 1 минута в UTC: 2012-март-31 17:00:00.0000 Z

18
задан Robert Slaney 2 March 2012 в 00:43
поделиться