104

単体テストを行っているときに、DateTime.UtcNow で予期しない動作に遭遇しました。DateTime.Now/UtcNow を立て続けに呼び出すと、より正確なミリ秒の増分を取得するのではなく、予想よりも長い時間間隔で同じ値を返すように見えます。

正確な時間測定に適した Stopwatch クラスがあることは知っていますが、誰かが DateTime でこの動作を説明できるかどうか興味がありましたか? DateTime.Now について文書化された公式の精度はありますか (たとえば、50 ミリ秒以内の精度ですか?)。DateTime.Now の精度が、ほとんどの CPU クロックで処理できる精度よりも低くなるのはなぜですか? たぶん、最小公分母のCPU用に設計されているのでしょうか?

public static void Main(string[] args)
{
    var stopwatch = new Stopwatch();
    stopwatch.Start();
    for (int i=0; i<1000; i++)
    {
        var now = DateTime.Now;
        Console.WriteLine(string.Format(
            "Ticks: {0}\tMilliseconds: {1}", now.Ticks, now.Millisecond));
    }

    stopwatch.Stop();
    Console.WriteLine("Stopwatch.ElapsedMilliseconds: {0}",
        stopwatch.ElapsedMilliseconds);

    Console.ReadLine();
}
4

7 に答える 7

203

DateTime.Now の精度が、ほとんどの CPU クロックで処理できる精度よりも低くなるのはなぜですか?

優れた時計は正確正確でなければなりません。それらは異なります。古い冗談が言うように、停止した時計は 1 日に 2 回正確に正確であり、1 分遅れた時計はいつでも正確ではありません。しかし、1 分遅い時計は常に最も近い分まで正確ですが、停止している時計には有用な精度がまったくありません。

マイクロ秒まで正確にできない可能性があるのに、なぜDateTimeをマイクロ秒まで正確にする必要があるのでしょうか? ほとんどの人は、マイクロ秒まで正確な公式の時報の情報源を持っていません。したがって、精度の小数点以下 6 桁を指定すると、最後の 5 桁がゴミになります

DateTime の目的は、日付と時刻を表すことです。高精度のタイミングは、DateTime の目的ではありません。お気づきのように、それがストップウォッチの目的です。DateTime の目的は、現在の時刻をユーザーに表示したり、次の火曜日までの日数を計算したりするなどの目的で、日付と時刻を表すことです。

要するに「今何時?」と「それはどのくらいかかりましたか?」完全に異なる質問です。ある質問に答えるために設計されたツールを使用して、他の質問に答えないでください。

ご質問ありがとうございます。これは良いブログ記事になります!:-)

于 2010-01-27T00:36:30.623 に答える
18

DateTime の精度は、それが実行されているシステムに多少固有です。精度は、コンテキスト スイッチの速度に関連しており、約 15 または 16 ミリ秒になる傾向があります。(私のシステムでは、テストから実際には約 14 ミリ秒ですが、35 ~ 40 ミリ秒の精度に近いラップトップを見たことがあります。)

Peter Bromberg は、C#の高精度コード タイミングに関する記事を書き、これについて説明しています。

于 2010-01-26T22:28:33.600 に答える
12

私は正確なDatetime.Nowが欲しいです:)、それで私はこれを調理しました:

public class PreciseDatetime
{
    // using DateTime.Now resulted in many many log events with the same timestamp.
    // use static variables in case there are many instances of this class in use in the same program
    // (that way they will all be in sync)
    private static readonly Stopwatch myStopwatch = new Stopwatch();
    private static System.DateTime myStopwatchStartTime;

    static PreciseDatetime()
    {
        Reset();

        try
        {
            // In case the system clock gets updated
            SystemEvents.TimeChanged += SystemEvents_TimeChanged;
        }
        catch (Exception)
        {                
        }
    }

    static void SystemEvents_TimeChanged(object sender, EventArgs e)
    {
        Reset();
    }

    // SystemEvents.TimeChanged can be slow to fire (3 secs), so allow forcing of reset
    static public void Reset()
    {
        myStopwatchStartTime = System.DateTime.Now;
        myStopwatch.Restart();
    }

    public System.DateTime Now { get { return myStopwatchStartTime.Add(myStopwatch.Elapsed); } }
}
于 2013-02-21T17:42:51.217 に答える
6

.NET ソースを実際にチェックすることを除けば、Eric Lippert は、この SO の質問に対して、DateTime の精度は約 30 ミリ秒までしか正確ではないというコメントを提供しました。彼の言葉によると、ナノ秒の精度ではない理由は、「そうである必要はない」ということです。

于 2010-01-26T22:28:09.530 に答える
6

MSDNから、すべての NT オペレーティング システムでDateTime.Now10 ミリ秒の分解能があることがわかります。

実際の精度はハードウェアに依存します。を使用すると、より高い精度が得られQueryPerformanceCounterます。

于 2010-01-26T22:28:50.257 に答える
3

MSDN ドキュメントから:

このプロパティの解決は、システム タイマーによって異なります。

彼らはまた、Windows NT 3.5 以降でのおおよその解像度は 10 ミリ秒であると主張しています :)

于 2010-01-26T22:28:09.837 に答える