Example of ambiguous DateTimeOffset

Thomas Zweifel

We have DateTimeOffsets in Database/Model. To display these values in Web, we convert the DateTimeOffsets into the current user's timezone.

According MSDN, DateTimeOffset can be ambiguous in a specific TimeZone:

TimeZoneInfo.IsAmbiguousTime Method (DateTimeOffset)

This doesn't make sense to me at all. Can someone please give me an example DateTimeOffset which is ambiguous?
We're in TimeZone "W. Europe Standard Time".

Matt Johnson-Pint

I think the confusion comes from the way that "ambiguous" is defined here.

To be clear, a DateTimeOffset is never ambiguous unto itself. It always represents a specific moment in absolute, instantaneous time. Given a date, time, and offset, I can tell you both the local wall-time, and the precise UTC time (by applying the offset).

However, the wall-time portion of the value can be ambiguous within a specific time zone. That is, the date and time only when you ignore the offset. That's what TimeZoneInfo.IsAmbiguousTime is telling you. That if it weren't for the offset, the value would be ambiguous. The wall-time may be one that a person in that time zone might find confusing.

Consider that there are two overloads of this method, one that takes a DateTime and one that takes a DateTimeOffset.

  • The DateTime one makes perfect sense when .Kind is 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
    
  • It makes a little less sense with the other kinds, because it does conversions to the given time zone first - but still it does the same thing:

    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
    
  • The DateTimeOffset overload is essentially doing the same thing as the previous example. Whatever the offset is, it gets applied to the date and time, then ambiguity is checked on the resulting date and time alone - just like in the first example.

    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
    
  • Even with an offset that is meaningless to that time zone, it still gets applied before comparing.

    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
    

It boils down to the implementation of the overload, which is essentially:

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

You can see this in the .net reference source here. They condense it to two lines, and preface it with a shortcut for better perf when DST is not applicable, but that's what it does.

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事