【问题标题】:Example of ambiguous DateTimeOffset模棱两可的 DateTimeOffset 示例
【发布时间】:2016-04-18 13:50:35
【问题描述】:

我们在数据库/模型中有 DateTimeOffsets。为了在 Web 中显示这些值,我们将 DateTimeOffsets 转换为当前用户的时区。

根据 MSDN,DateTimeOffset 在特定的 TimeZone 中可能是不明确的:

TimeZoneInfo.IsAmbiguousTime Method (DateTimeOffset)

这对我来说根本没有意义。谁能给我一个模棱两可的示例 DateTimeOffset
我们在时区“西欧标准时间”。

【问题讨论】:

  • 注意,DateTimeOffset 是时区 awareness。它只有日期、时间和 Utc 偏移值。

标签: c# dst timezone-offset datetimeoffset


【解决方案1】:

文档中所说的内容是否不清楚?

通常,当时钟设置为从夏令时返回标准时间时,会产生不明确的时间

即如果您在凌晨 2 点离开 DST 并将时钟重置为凌晨 1 点,那么如果有人开始谈论凌晨 1.30,您不知道那是从现在开始的 30 分钟还是过去 30 分钟发生的事情。

有一组值(通常为一小时长)映射到 UTC 时间中的两组不同时刻。

【讨论】:

    【解决方案2】:

    示例是(去年 10 月的星期日 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");
    

    不明确时间相反的是无效时间(去年三月的星期日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");
    

    【讨论】:

      【解决方案3】:

      我认为混淆来自这里定义“模棱两可”的方式。

      需要明确的是,DateTimeOffset 本身永远不会模棱两可。它总是代表绝对瞬时时间中的特定时刻。给定日期、时间和偏移量,我可以告诉你当地的挂钟时间和精确的 UTC 时间(通过应用偏移量)。

      但是,值的挂起时间部分在特定时区内可能不明确。也就是说,日期和时间只有您忽略偏移量时。这就是TimeZoneInfo.IsAmbiguousTime 告诉你的。那如果不是偏移量,这个值就会是模棱两可的。墙上时间可能是那个时区的人可能会感到困惑的时间。

      考虑这个方法有两种重载,一种采用DateTime,另一种采用DateTimeOffset

      • .KindDateTimeKind.Unspecified 时,DateTime 非常有意义。

        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 时使用快捷方式作为开头以获得更好的性能,但这就是它的作用。

      【讨论】:

      • 很好的答案!您对墙上时间部分的解释和对时区值的无知有很大帮助!我不知道框架只使用 DateTimeOffset 的 DateTime 部分。
      • 这只是关于 this 功能。还有很多其他地方确实考虑了偏移量。
      猜你喜欢
      • 1970-01-01
      • 2018-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-10
      • 2014-08-12
      • 2011-04-20
      相关资源
      最近更新 更多