24

LocalDateTime在 Noda Time中获取系统时间的惯用方法是什么?我能想到的最直接的方法是

var dt = DateTime.Now
LocalDateTime systemTime = new LocalDateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute);

但鉴于 Noda Time 的全部目的是用语义更好的东西替换 DateTime,我认为有一种比以DateTime上述方式使用的首选方法。使用 Noda 的设施我能想到的最好的方法是

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

但这似乎很冗长。

4

1 回答 1

52

您的第二个示例正是您将如何执行此操作。它是故意冗长的。请参阅Noda Time 的设计理念

分三个部分来考虑:

  1. 获取当前时刻:

    // Instant now = SystemClock.Instance.Now;               // NodaTime 1.x
    Instant now = SystemClock.Instance.GetCurrentInstant();  // NodaTime 2.x
    
  2. 获取系统的时区。(这是首选语法)

    DateTimeZone tz = DateTimeZoneProviders.Bcl.GetSystemDefault();
    
  3. 将时区应用于瞬间:

    ZonedDateTime zdt = now.InZone(tz);
    

您获得 a 的最后一步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在单元测试期间使用 a 。有关更多详细信息,请参阅使用 Noda Time进行单元测试。

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

  • 如果您有其他使用 IANA 时区的工作,或者您使用的是 Noda Time 的 .NET Standard 版本,请更改步骤 2 以使用Tzdb提供程序:

    DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
    

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

如果您对为什么DateTime.Now在 Noda Time 如此冗长的情况下如此紧凑感到好奇,请尝试反编译DateTime.Now或查看 MS 参考源。您会看到它在后台执行了基本相同的步骤。

于 2014-01-09T21:27:09.493 回答