Вопрос

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

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

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();
}
Это было полезно?

Решение

Почему 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); } }
}

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

Фактическая точность зависит от аппаратного обеспечения.Более высокая точность может быть получена с помощью QueryPerformanceCounter.

Как бы то ни было, если не считать фактической проверки .СЕТЕВОЙ источник, Эрик Липперт предоставил комментарий к это ТАКОЙ вопрос говоря, что дата-время имеет точность только приблизительно до 30 мс.Причина того, что точность не достигает наносекунды, по его словам, заключается в том, что в этом "нет необходимости".

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

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

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

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

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

Ссылка на MSDN

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top