39

我正在尝试使用 Jon Skeet(和其他人)的Noda Time框架。

我正在尝试存储当前(即时)。Instant 是从长滴答声中创建的,但是当前滴答声的计数是多少?

是吗:

Instant now = new Instant(DateTime.Now.ToUniversalTime().Ticks);

或者?

Instant now = Instant.FromDateTimeUtc(DateTime.Now.ToUniversalTime());

他们是等价的吗,我这样做对吗?

PS,如果乔恩回答是这个 - 我想提出一个 Instant.Now 属性。

PS2 我知道标题包含一个标签,但它不会让我有一个简短的“Instant.Now”标题。

4

2 回答 2

52

我做了一些研究,似乎 NodaTime 的方式是根据时钟获取现在的时刻。

如果您想使用系统时钟获取当前时间,只需使用SystemClock.Instance.GetCurrentInstant().

但是,SystemClock.Instance与其直接在代码中使用,不如IClock在时间感知类中注入依赖项。

这将允许您:

  • 在运行时为类提供SystemClock.Instance,因此代码将使用正确的时间
  • 在单元测试期间提供一个虚假的实现,IClock以允许您根据需要调整时间以测试各种场景(如时间的流逝)。有一个 NodaTime.Testing 项目提供了这样一个类,称为FakeClock.

我觉得这非常有用。我认为拥有类似new Instant()Instant.Now返回当前时间的东西会更容易硬编码幕后的用法SystemClock,因此错过了 NodaTime 提供的测试优势。

有关使用 NodaTime 进行单元测试的更多信息,请参阅此链接


关于您的代码示例:它们不等效。

  • Instant.FromDateTimeUtc(DateTime.Now.ToUniversalTime())确实会为您提供 UTC 的当前时刻。
  • new Instant(DateTime.Now.ToUniversalTime().Ticks)会在很远的将来给你一个错误的日期,因为 BCLDateTime.Ticks代表自 以来的滴答数1/1/0001,而 NodaTimeInstant.Ticks代表自以来的滴答数(请参阅此处1/1/1970的注释)。
于 2013-01-25T23:24:12.707 回答
18

SystemClock.Now将当前时间作为Instant值返回:

Instant now = SystemClock.Instance.Now;

但是您可能需要注意IClock接口文档中的注释:

IClock旨在用于您需要访问当前时间的任何地方。尽管直接调用并非完全不正确SystemClock.Instance.Now,但与调用UtcNow的方式相同,但出于生产代码的风格问题,强烈建议不要这样做。我们建议为任何需要它的对象提供一个IClock实例,它允许您使用 NodaTime.Testing 程序集(或您自己的实现)中的存根时钟编写测试。

作为一个简单的示例,假设您有一个Logger需要当前时间的类。SystemClock不要直接访问,而是使用IClock通过其构造函数提供的实例:

public class Logger
{
    private readonly IClock clock;

    public Logger(IClock clock)
    {
        this.clock = clock;
    }

    public void Log(string message)
    {
        Instant timestamp = this.clock.Now;
        // Now log the message with the timestamp... 
    }
}

当你Logger在生产代码中实例化 a 时,你可以给它SystemClock.Instance. 但是在Logger类的单元测试中,你可以给它一个FakeClock.

于 2013-01-25T23:23:29.073 回答