C# DateTime.Теперь точность

Я просто столкнулся с неожиданным поведением с DateTime.UtcNow во время выполнения некоторых модульных тестов. Похоже, что при вызове DateTime.Теперь / UtcNow в быстрой последовательности, похоже, дает вам одно и то же значение в течение более длительного, чем ожидалось, интервала времени, а не захватывает более точные миллисекундные приращения.

Я знаю, что есть класс секундомеров, который лучше подходит для точных измерений времени, но мне было любопытно, может ли кто-нибудь объяснить это поведение в Датавремя? Есть ли официальная точность, документированная для DateTime.Теперь (например, с точностью до 50 мс?)? Почему DateTime.Теперь сделать менее точным, чем то, что большинство часов 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();
}

6 ответов


почему DateTime.Теперь сделать менее точным, чем то, что большинство часов CPU может обрабатывать?

хорошие часы должны быть как точный и точный; это разные вещи. Как говорится в старой шутке, остановленные часы точно точны дважды в день, часы, которые отстают на минуту, никогда не бывают точными в любое время. Но часы на минуту медленнее всегда точны до ближайшей минуты, в то время как остановленные часы не имеют полезной точности на все.

почему DateTime должно быть точный чтобы, скажем, микросекунду, когда это невозможно точный в микросекунду? Большинство людей не имеют никакого источника для официальных сигналов времени, которые точны до микросекунды. Поэтому, давая шесть цифр после десятичного знака точность, последние пять из которых являются мусор будет врет.

помните, что целью DateTime является представляют дату и время. Высокоточные тайминги вовсе не являются целью DateTime; как вы заметили, это цель секундомера. Цель DateTime-представить дату и время для таких целей, как отображение текущего времени пользователю, вычисление количества дней до следующего вторника и т. д.

короче говоря, " который час? и сколько времени это заняло?"совершенно разные вопросы; не используйте инструмент, предназначенный для ответа на один вопрос, чтобы ответить другой.

Спасибо за вопрос; это сделает хорошую статью в блоге! :-)


точность DateTime несколько специфична для системы, в которой она запускается. Точность связана со скоростью контекстного переключателя, которая, как правило, составляет около 15 или 16 мс. (В моей системе это на самом деле около 14 мс от моего тестирования, но я видел некоторые ноутбуки, где он ближе к точности 35-40 МС.)

Питер Бромберг написал статья о высокой точности синхронизации кода в C#, который обсуждает это.


Я хотел бы получить точное время.Теперь :), поэтому я приготовил это:

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); } }
}

для чего это стоит, не проверяя источник .NET, Эрик Липперт предоставил комментарий к это так вопрос говоря, что DateTime является точным только приблизительно до 30 мс. По его словам, причина не быть наносекундной точностью заключается в том, что это "не должно быть"."


С MSDN вы найдете, что DateTime.Now есть примерное разрешение 10 миллисекунд на всех операционных системах NT.

фактическая точность зависит от аппаратного обеспечения. Лучшую точность можно получить, используя QueryPerformanceCounter.


из документации MSDN:

разрешение этого имущества зависит от системного таймера.

Они также утверждают, что приблизительное разрешение на Windows NT 3.5 и более поздних версий составляет 10 мс:)