【问题标题】:Getting the system's LocalDateTime in Noda Time在野田时间获取系统的 LocalDateTime
【发布时间】:2014-01-28 13:13:22
【问题描述】:

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

但这似乎很冗长。

【问题讨论】:

    标签: c# date datetime time nodatime


    【解决方案1】:

    您的第二个示例正是您将如何执行此操作。 故意冗长。见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);
      

    获得LocalDateTime 的最后一步很简单,但要认识到,当您这样做时,您会删除任何时区信息。 NodaTime 中的“本地”not 表示“运行代码的计算机的本地”。 (换句话说,它不像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 参考源。您会看到它在后台执行的步骤基本相同。

    【讨论】:

    • 感谢您提供如此深刻而翔实的回答!回复:附加点,我确实计划注入一个 IClock 代替。另外,我确实想在这里使用系统时间。该代码适用于应用技术人员将在现场使用的微控制器上设置时间,该微控制器“太愚蠢”而没有时区的概念。但是,我使用的是 Noda Time,因为我们的服务器上也将使用同一个库,以便在设置设备后与设备进行无线通信。
    • 不久前我做了类似的事情。在我的例子中,将每个设备与特定的命名时区相关联更有意义,而不是使用它们正在与之交谈的机器的时区。 YMMV。
    • 另外,您可能需要考虑如何在您的设备上处理 DST 更改。那是我在该项目中必须关注的另一个领域。
    • 该设备与服务器上的特定时区相关联,并且将在那里考虑时区,但设备本身太笨而无法知道它(因此使用LocalDateTime)。该设备处理 DST 有点简单 - 它保存 DST 开始的日期和时间以及结束时间的匹配对。不幸的是,该设备或其固件超出了我的控制范围。
    • @MarkusHütter - 根据these docs,如果您使用的是Noda Time 的.NET Standard 版本,则Bcl 提供程序不可用。请改用Tzdb 提供程序。结果将是相似的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-20
    • 2014-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多