C # DateTime.Now точность - PullRequest
       55

C # DateTime.Now точность

90 голосов
/ 27 января 2010

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

Я знаю, что есть класс Секундомер, который лучше подходит для выполнения точных измерений времени, но мне было любопытно, если кто-то может объяснить это поведение в DateTime? Есть ли официальная точность, документированная для DateTime.Now (например, с точностью до 50 мс?)? Почему DateTime.Now должен быть менее точным, чем то, с чем может справиться большинство процессорных часов? Может, он просто предназначен для процессора с наименьшим общим знаменателем?

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

Ответы [ 7 ]

170 голосов
/ 27 января 2010

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

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

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

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

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

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

18 голосов
/ 27 января 2010

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

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

13 голосов
/ 21 февраля 2013

Я бы хотел точный 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); } }
}
5 голосов
/ 27 января 2010

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

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

5 голосов
/ 27 января 2010

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

3 голосов
/ 27 января 2010

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

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

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

1 голос
/ 04 февраля 2019

Разрешение этого свойства зависит от системного таймера, который зависит от базовой операционной системы. Это имеет тенденцию быть между 0,5 и 15 миллисекунд.

В результате повторные вызовы свойства Now за короткий промежуток времени, например в цикле, могут возвращать одно и то же значение.

MSDN Link

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...