在Noda Time中获取系统的LocalDateTime

时间:2014-01-09 19:35:00

标签: c# date datetime time nodatime

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

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

但鉴于Noda Time的entire purpose is to replace DateTime with something that has nicer semantics,我认为有一种首选方法,而不是以上述方式使用DateTime。我能想出使用Noda的设施是最好的

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

但这似乎很冗长。

1 个答案:

答案 0 :(得分:38)

你的第二个例子就是你将如何做到这一点。这是故意详细。请参阅Noda Time's design philosophy

分三个部分来考虑:

  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);
    
  4. 获取LocalDateTime的最后一步是微不足道的,但要认识到当你这样做时,你正在剥离任何时区信息。 NodaTime中的“Local”表示“代码运行的计算机的本地”。 (换句话说,它不像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。有关详细信息,请参阅Unit Testing with 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参考源。你会发现它在幕后做了基本相同的步骤。