在Noda Time中获取系统的LocalDateTime

25
什么是在Noda Time中获取系统时间作为LocalDateTime的惯用方法?我能想到的最直接的方法是:
var dt = DateTime.Now
LocalDateTime systemTime = new LocalDateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute);

但是鉴于Noda Time的整个目的是用更好的语义来替换DateTime, 我认为有一种比上述方法更好的首选方法。我能想到的最好方法是使用Noda的功能:

var zone = NodaTime.TimeZones.BclDateTimeZone.ForSystemDefault();
LocalDateTime systemTime = SystemClock.Instance.Now.InZone(zone).LocalDateTime;

但这似乎有点冗长。
1个回答

54

你的第二个示例恰好是实现这一点的方法。它被有意地编写得冗长。请参见Noda Time设计哲学

将其分为三个部分:

  1. 获取当前时刻:

  2. // Instant now = SystemClock.Instance.Now;               // NodaTime 1.x
    Instant now = SystemClock.Instance.GetCurrentInstant();  // NodaTime 2.x
    
    获取系统的时区。(这是首选语法)
    DateTimeZone tz = DateTimeZoneProviders.Bcl.GetSystemDefault();
    
  3. 将时区应用于时刻:

  4. ZonedDateTime zdt = now.InZone(tz);
    
    你获取 LocalDateTime 的最后一步很简单,但请注意当你这样做时,会去除任何时区信息。在 NodaTime 中,“本地”并不意味着“本地到代码运行的计算机”。(换句话说,它不像 DateTimeKind.Local

    需要考虑的其他事项:

    • 您可能希望使用 IClock 接口来抽象时钟:

    • IClock clock = SystemClock.Instance;
      // Instant now = clock.Now;               // NodaTime 1.x
      Instant now = clock.GetCurrentInstant();  // NodaTime 2.x
      

      你可以将时钟作为方法参数传递,或使用你喜欢的 DI/IoC 框架进行注入(例如:Autofac、Ninject、StructureMap 等等)。这样做的好处是在单元测试中可以使用 NodaTime.Testing.FakeClock。有关详细信息,请参见Noda Time 的单元测试

    • 如果您希望在任何地方运行您的代码而不受系统时区的限制,则可能更喜欢传入 DateTimeZone。对于服务器应用程序来说,这一点很重要,但对于桌面 / 移动应用程序来说则不那么重要。

    • 如果您有其他使用 IANA 时区的工作,或者正在使用 Noda Time 的 .NET Standard 构建,则请更改第二步以使用 Tzdb 提供程序:

      DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
      

      TZDB时区比BCL时区更准确。在此初始调用中,Noda Time将映射您系统的Windows(BCL)时区到IANA(TZDB)时区。

      如果您好奇为什么DateTime.Now如此紧凑而Noda Time则非常冗长,请尝试反编译DateTime.Now或查看MS参考源代码。您会发现它在幕后执行基本相同的步骤。


感谢您提供如此深入和详细的答案!关于额外的要点,我计划注入一个IClock。此外,我确实想在这里使用系统时间。该代码是为应用技术人员在现场设置微控制器时间而设计的,因为该微控制器“太笨了”,无法理解时区的概念。我正在使用Noda Time,因为同一库也将用于我们的服务器上,以便在设备设置完成后通过无线方式与其通信。 - Matt Kline
我不久前也做了类似的事情。在我的情况下,将每个设备与特定命名的时区关联起来比使用它们所连接的机器的时区更有意义。你的情况可能会有所不同。 - Matt Johnson-Pint
此外,您可能需要考虑如何处理设备上的夏令时更改。那是我在该项目中不得不关注的另一个领域。 - Matt Johnson-Pint
该设备与服务器关联,并且将考虑使用的时区,但是该设备本身并不知道它(这就是使用LocalDateTime的原因)。该设备在处理夏令时方面有点简单化,它保存了夏令时开始和结束的日期和时间。不幸的是,该设备或其固件超出了我的控制范围。 - Matt Kline
2
根据这些文档,如果您正在使用Noda Time的.NET Standard版本,则无法使用“Bcl”提供程序。请改用“Tzdb”提供程序,结果将类似。 - Matt Johnson-Pint
显示剩余2条评论

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