2016-01-13 10 views
2

У нас есть DateTimeOffsets в базе данных/модели. Чтобы отобразить эти значения в Интернете, мы преобразуем DateTimeOffsets в часовой пояс текущего пользователя.Пример неоднозначности DateTimeOffset

Согласно MSDN, DateTimeOffset может быть неоднозначной в определенном TimeZone:

TimeZoneInfo.IsAmbiguousTime Method (DateTimeOffset)

Это не имеет смысла для меня вообще. Может кто-нибудь, пожалуйста, дайте мне пример DateTimeOffset, который неоднозначен?
Мы находимся в TimeZone «W. Europe Standard Time».

+0

Знайте, что 'DateTimeOffset' является часовым поясом _ознания_. Он просто имеет дату, время и значение смещения Utc. –

ответ

1

Я думаю, что путаница происходит из-за того, что здесь определен «двусмысленный».

Чтобы быть ясным, DateTimeOffset никогда не является двусмысленным для себя. Он всегда представляет собой конкретный момент в абсолютном, мгновенном времени. Учитывая дату, время и смещение, я могу рассказать вам как локальное настенное время, так и точное время UTC (путем применения смещения).

Однако часть времени на стене может быть неоднозначной в течение определенного часового пояса. То есть, дата и время только , когда вы игнорируете смещение. Вот что говорит вам TimeZoneInfo.IsAmbiguousTime. То, что , если бы не смещение, значение было бы неоднозначным. Время стены может быть тем, что человек в этом часовом поясе может сбить с толку.

Учтите, что существует два перегрузки этого метода: один принимает DateTime и тот, который принимает DateTimeOffset.

  • The DateTime один имеет смысл, когда .Kind является DateTimeKind.Unspecified.

    DateTime dt = new DateTime(2016, 10, 30, 2, 0, 0); 
    TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time"); 
    bool ambiguous = tz.IsAmbiguousTime(dt); // true 
    
  • Это делает немного меньше смысла с другими видами, потому что он делает преобразования в данной временной зоне первого - но все же он делает то же самое:

    DateTime dt = new DateTime(2016, 10, 30, 1, 0, 0, DateTimeKind.Utc); 
    TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time"); 
    bool ambiguous = tz.IsAmbiguousTime(dt); // true 
    
  • Перегрузка DateTimeOffset является по существу делая то же, что и в предыдущем примере. Независимо от смещения, он применяется к дате и времени, тогда двусмысленность проверяется на итоговую дату и время в одиночку - точно так же, как в первом примере.

    DateTimeOffset dto = new DateTimeOffset(2016, 10, 30, 2, 0, 0, TimeSpan.FromHours(1)); 
    TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time"); 
    bool ambiguous = tz.IsAmbiguousTime(dto); // true 
    
  • Даже со смещением, что не имеет смысла для этой временной зоны, она по-прежнему будет применяться перед сравнением.

    DateTimeOffset dto = new DateTimeOffset(2016, 10, 29, 19, 0, 0, TimeSpan.FromHours(-5)); 
    TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time"); 
    bool ambiguous = tz.IsAmbiguousTime(dto); // true 
    

Она сводится к реализации перегрузки, которая является по существу:

// Make sure the dto is adjusted to the tz. This could be a no-op if it already is. 
DateTimeOffset adjusted = TimeZoneInfo.ConvertTime(dto, tz); 

// Then just get the wall time, stripping away the offset. 
// The resulting datetime has unspecified kind. 
DateTime dt = adjusted.DateTime; 

// Finally, call the datetime version of the function 
bool ambiguous = tz.IsAmbiguousTime(dt); 

Вы можете увидеть это in the .net reference source here. Они конденсируют его до двух строк и предируют с помощью ярлыка для лучшего перфоманса, когда DST не применим, но это то, что он делает.

+0

Отличный ответ! Ваше объяснение части времени на стене и незнание ценности часового пояса помогает много! Я не знал, что Framework использует только часть DateTime для DateTimeOffset. –

+0

Это только в отношении * этой функции *. Есть много других мест, где смещение действительно считается. –

3

Означает ли документация, что это не ясно?

Как правило, неоднозначные раз возникают, когда часы установлены, чтобы вернуться к стандартному времени летнее время

Т.е. если в 2 часа вы отделитесь от летнего времени и сбросите часы до 1 часа ночи, тогда, если кто-то начнет говорить о 1.30am, вы не знаете, прошло ли это через 30 минут или случилось за 30 минут в прошлом.

Существует набор значений (обычно час), которые отображают два разных момента времени в UTC.

2

Ну образец (в в октябре прошлого года в воскресенье 2: 00-3: 00)

DateTimeOffset example = new DateTimeOffset(2015, 10, 25, 2, 30, 0, 
    new TimeSpan(0, 2, 0, 0)); 

TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time"); 

if (tst.IsAmbiguousTime(example)) 
    Console.Write("Ambiguous time"); 

Напротив неоднозначных время Invalid время (в марте прошлого года, в воскресенье 2: 00- 3:00):

TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time"); 

if (tst.IsInvalidTime(new DateTime(2016, 03, 27, 2, 30, 0))) 
    Console.Write("Invalid time");