在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;

但这似乎很冗长。

最佳答案

您的第二个示例正是您将如何执行此操作。它是故意冗长的。参见Noda Time's design philosophy

分为三个部分来考虑:

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

  • 获取LocalDateTime的最后一步很简单,但是要意识到,这样做时,您将剥离所有时区信息。 NodaTime中的“本地”不表示“运行代码的计算机本地”。 (换句话说,它不像DateTimeKind.Local)

    需要考虑的其他事项:
  • 您可能更喜欢使用IClock接口(interface)来抽象时钟:
    IClock clock = SystemClock.Instance;
    // Instant now = clock.Now;               // NodaTime 1.x
    Instant now = clock.GetCurrentInstant();  // NodaTime 2.x
    

    然后,您可以将时钟作为方法参数传入,或将其与您喜欢的DI/IoC框架一起注入(inject)。 (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)时区。

  • 如果您对为什么Not Time如此冗长而DateTime.Now如此紧凑感到好奇,请尝试反编译DateTime.Now或查看MS引用源。您会发现它在后台执行了基本上相同的步骤。

    10-02 04:12