在Noda Time中获取系统的LocalDateTime

Mat*_*ine 19 c# time datetime date nodatime

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

var dt = DateTime.Now
LocalDateTime systemTime = new LocalDateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute);
Run Code Online (Sandbox Code Playgroud)

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

var zone = NodaTime.TimeZones.BclDateTimeZone.ForSystemDefault();
LocalDateTime systemTime = SystemClock.Instance.Now.InZone(zone).LocalDateTime;
Run Code Online (Sandbox Code Playgroud)

但这似乎很冗长.

Mat*_*int 40

你的第二个例子就是你如何做到这一点.这是故意冗长的.请参阅Noda Time的设计理念.

可以分三个部分来考虑:

  1. 获取当前时刻:

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

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

    ZonedDateTime zdt = now.InZone(tz);
    
    Run Code Online (Sandbox Code Playgroud)

获得a的最后一步LocalDateTime是微不足道的,但要认识到当你这样做时,你正在剥离任何时区信息.NodaTime中的"Local" 并不意味着"代码运行的计算机的本地".(换句话说,它不像DateTimeKind.Local)

需要考虑的其他事项:

  • 您可能更喜欢使用IClock界面抽象时钟:

    IClock clock = SystemClock.Instance;
    // Instant now = clock.Now;               // NodaTime 1.x
    Instant now = clock.GetCurrentInstant();  // NodaTime 2.x
    
    Run Code Online (Sandbox Code Playgroud)

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

  • 您可能还希望传入,DateTimeZone以便可以在任何地方运行代码,而不必依赖于系统时区.这对于服务器应用程序很重要,但对桌面/移动应用程序则不那么重要.

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

    DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
    
    Run Code Online (Sandbox Code Playgroud)

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

如果您对DateTime.NowNoda Time如此简洁有如此紧凑的好奇心,请尝试反编译DateTime.Now或查看MS参考源.你会发现它在幕后做了基本相同的步骤.

  • @MarkusHütter - Per [这些文档](https://nodatime.org/2.2.x/api/NodaTime.DateTimeZoneProviders.html#NodaTime_DateTimeZoneProviders_Bcl),如果您使用的是.NET标准版,则无法使用`Bcl`提供程序野田时间 请改用`Tzdb`提供程序.结果将类似. (2认同)