C # DateTime.Теперь точность
-
22-09-2019 - |
Вопрос
Я только что столкнулся с некоторым неожиданным поведением с 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 мс.Причина того, что точность не достигает наносекунды, по его словам, заключается в том, что в этом "нет необходимости".
Разрешение этого свойства зависит от системного таймера.
Они также утверждают, что приблизительное разрешение в Windows NT 3.5 и более поздних версиях составляет 10 мс :)
Разрешение этого свойства зависит от системного таймера, который зависит от базовой операционной системы.Это имеет тенденцию быть от 0,5 до 15 миллисекунд.
В результате повторные вызовы свойства Now за короткий промежуток времени, например, в цикле, могут возвращать одно и то же значение.