不明确的DateTimeOffset示例

4
我们的数据库/模型中有DateTimeOffsets。为了在Web中显示这些值,我们将DateTimeOffsets转换为当前用户的时区。
根据MSDN的说法,DateTimeOffset在特定时区可能是不明确的:
TimeZoneInfo.IsAmbiguousTime方法(DateTimeOffset)
对我来说这一点毫无意义。请问有人可以举一个不明确的DateTimeOffset的例子吗?我们在“W.欧洲标准时间”时区。

请注意,DateTimeOffset 是时区感知的。它只有日期、时间和 UTC 偏移值。 - Soner Gönül
3个回答

3
我认为混淆的原因在于此处“ambiguous”的定义方式。
明确一点,DateTimeOffset本身永远不会有二义性。它始终代表一个特定瞬间的绝对时间。给定日期、时间和偏移量,我可以告诉你本地墙上时间和精确的UTC时间(通过应用偏移量)。
然而,在特定时区内,该值的墙上时间部分可能存在二义性。也就是说,当你忽略偏移量时,仅仅关注日期和时间。这就是TimeZoneInfo.IsAmbiguousTime所告诉你的内容。如果没有偏移量,那么该值会有歧义。这个时间可能会让该时区的人感到困惑。
请注意,此方法有两个重载版本,一个使用DateTime,另一个使用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
    

这主要涉及到重载的实现,其本质是:

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

您可以在.net参考源代码中查看此内容。他们将其压缩为两行,并在夏令时不适用时使用快捷方式以提高性能,但这就是它的作用。


非常好的答案!您对壁钟时间部分的解释以及忽略时区值的说明帮助了很多!我不知道框架只使用DateTimeOffset的DateTime部分。 - Thomas Zweifel
1
这只是关于这个函数的问题。还有很多其他地方确实考虑了偏移量。 - Matt Johnson-Pint

3
文档的说明并不清晰吗?
通常,时间不明确是由于时钟从夏令时返回标准时间造成的。例如,如果在凌晨2点你退出夏令时并将时钟调回1点,那么如果有人谈论1点半,你就不知道是30分钟后还是30分钟前发生的。
存在一组数值(通常为1小时),它们映射到UTC时间中的两个不同的时刻。

1
除了DateTimeOffset指的是时间(时间+偏移量)的绝对点之外,这种情况下没有歧义。在特定的DateTimeOffset中,一个时区只能有一个偏移量。 - Sellorio

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

Ambiguous 时间相反的是 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");

1
即使您自己的示例强调无效时间仅对DateTime(没有提供偏移量)有效。OP和我想知道当绝对时间(DateTimeOffset-日期,时间和偏移量)指向确切时间点时如何产生歧义。 - Sellorio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接