C# DateTime.Now の精度
-
22-09-2019 - |
質問
いくつかの単体テストを実行中に、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();
}
解決
なぜ、ほとんどのCPUクロックが扱うことができるものよりも精度の低いなされるDateTime.Nowがでしょうか?
良い時計は、両方のの正確なと正確のでなければなりません。それらは異なっています。古いジョークが進むにつれ、停止クロックを1日2回、正確に正確である、クロック分遅い、いつでも正確なことはありません。停止したクロックは全く便利な精度を持っていないのに対し、しかし、クロック分遅い、常に最も近い分に正確です。
なぜDateTimeのあるべきの正確なの、それはおそらく、のことができないとき、マイクロ秒を避ける正確のマイクロ秒に?ほとんどの人は、マイクロ秒に正確である公式時間信号のための任意のソースを持っていません。したがって、の精度の小数点以下の場所の後に6桁の数字を与えて、のごみのであるの最後の5は、を横たわっのでしょう。
のDateTimeの目的は、の日付と時刻を表すのにある、覚えておいてください。高精度タイミングがすべてのDateTimeの目的ではありません。あなたが注意として、それはストップウォッチの目的です。日時の目的は、ユーザに現在の時刻を表示次火曜日までの日数を計算する、等々のような目的のための日付と時刻を表すことである。
要するに、「それは何時ですか?」そして、「どのくらいそのテイクをしました?」完全に別の質問があります。他に答えるために一つの質問に答えるために設計されたツールを使用しないでください。
ご質問をお寄せいただきありがとうございます。これは良いブログ記事を行います! : - )
他のヒント
日時の精度はややそれが上で実行されているのシステムに固有のものです。精度は、15または16ミリ秒の周りになる傾向があるコンテキストスイッチの速度に関連しています。 (私のシステムでは、それは私のテストから14ミリ秒程度実際に、私はそれが近い35〜40ミリ秒の精度です一部のラップトップを見てきました。)
ピーターBromberg、これを説明C#で高精度のコードタイミングの上記事を書います。
私は、正確な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); } }
}
MSDN のから、あなたはそのDateTime.Now
を見つけることができますすべてのNTオペレーティングシステムで10ミリ秒ののおおよそのの解像度を持っています。
は、実際の精度は、ハードウェアに依存します。より良好な精度は QueryPerformanceCounter
するを使用して得ることができます。
実際に .NET ソースをチェックする以外の価値があることについては、Eric Lippert が次のコメントを提供しました。 この質問 DateTime は約 30 ミリ秒までしか正確ではないと言っています。彼の言葉によれば、ナノ秒の精度がない理由は「その必要はない」ということだ。
このプロパティの解像度は、基礎となるオペレーティングシステムに依存するシステムタイマーに依存します。そうなる傾向があります 0.5〜15ミリ秒。
その結果、ループなどで短期間に Now プロパティを繰り返し呼び出すと、同じ値が返される場合があります。