web-dev-qa-db-ja.com

Instant.Now for NodaTime

Jon Skeet(およびその他)による Noda Time フレームワークの使用を理解しようとしています。

現在を保存しようとしています(インスタント)。インスタントは長いティックから作成されますが、現在のティックの数はいくつですか?

それは...ですか:

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

そしてまたは?

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

それらは同等ですか、私もこれを正しく行っていますか?

PS、ジョンの答えがこれなら-Instant.Nowプロパティを提案したいと思います。

PS2タイトルにタグが含まれていることは知っていますが、短い「Instant.Now」タイトルを付けることはできません。

28
Chuck Savage

少し調べてみたところ、NodaTimeの方法は、 クロック に従ってnowモーメントを取得することのようです。

システムクロックを使用して現在の時刻を取得する場合は、SystemClock.Instance.GetCurrentInstant()を使用します。

ただし、コードで_SystemClock.Instance_を直接使用するのではなく、時間認識クラスにIClock依存関係を挿入することをお勧めします。

これにより、次のことが可能になります。

  • 実行時にクラスに_SystemClock.Instance_を提供して、コードが正しい時間を使用するようにします
  • ユニットテスト中にIClockの偽の実装を提供して、さまざまなシナリオ(時間の経過など)をテストするために必要に応じて時間を微調整できるようにします。 FakeClockと呼ばれるそのようなクラスを提供するNodaTime.Testingプロジェクトがあります。

これはとても便利だと思います。 new Instant()や_Instant.Now_のようなもので現在の時刻を返すと、SystemClockの使用法を隠蔽してハードコーディングしやすくなり、NodaTimeが提供するテストの利点が失われると思います。

NodaTimeを使用した単体テストの詳細については、 このリンク を参照してください。


あなたのコード例に関して:それらは同等ではありません。

  • Instant.FromDateTimeUtc(DateTime.Now.ToUniversalTime())は、実際にUTCで現在の瞬間を提供します。
  • new Instant(DateTime.Now.ToUniversalTime().Ticks)は、BCLの _DateTime.Ticks_ が_1/1/0001_以降のティック数を表すため、はるか先の間違った日付を示します。 NodaTimeの _Instant.Ticks_ は、_1/1/1970_以降のティック数を表します(備考 ここ を参照)。
34

SystemClock.Now 現在の時刻をInstant値として返します。

Instant now = SystemClock.Instance.Now;

ただし、 IClock インターフェイスのドキュメントの注意事項に注意することをお勧めします。

IClockは、現在の時刻にアクセスする必要がある場所で使用することを目的としています。 SystemClock.Instance.Nowを直接呼び出すことは厳密には誤りではありませんが、 tcNow を呼び出すのと同じ方法で、本番コードのスタイルの問題として強くお勧めしません。 IClockのインスタンスを必要なものに提供することをお勧めします。これにより、NodaTime.Testing Assembly(または独自の実装)。

簡単な例として、現在の時刻を必要とする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をインスタンス化するときは、SystemClock.Instanceを指定できます。ただし、Loggerクラスの単体テストでは、 FakeClock を指定できます。

14
Michael Liu