Получите время в миллисекундах с помощью C #

134

Я делаю программу, в которой мне нужно получить время в миллисекундах. Под временем я имею в виду число, которое никогда не равно самому себе и всегда на 1000 чисел больше, чем было секунду назад. Я пробовал преобразовать DateTime.Nowв a TimeSpanи получить TotalMillisecondsот этого ... но слышал, что это не совсем точно.

Есть ли более простой способ сделать это?

сущность
источник
Ожидаете ли вы, что любые два вызова всегда будут приводить к увеличению значений? Как правило, вызовы с интервалом ближе, чем минимальный интервал, разрешенный разрешением таймера, будут давать такое же значение. Вам нужно будет добавить свой собственный инструмент разрешения конфликтов в виде сериализатора с фиктивной точностью.
Стивен Судит
16
«Число, которое никогда не равно самому себе». Звучит ... сложно. ;)
Mizipzor
1
На самом деле NaN соответствует этому требованию. Несмотря на то, что это «не число», это числовой тип, и он не равен самому себе.
Yay295 04

Ответы:

78

Воспользуйтесь Stopwatchклассом.

Предоставляет набор методов и свойств, которые можно использовать для точного измерения прошедшего времени.

Здесь есть полезная информация о его реализации:

Тесты производительности: точное измерение времени работы с помощью System.Diagnostics.Stopwatch

RedFilter
источник
8
секундомер является частью диагностики. Следует ли использовать его в реальном коде?
Андрей
5
@Andrey - stackoverflow.com/questions/2805362/…
Джон Раш,
Обычно это точность до ближайших 15 мсек или около того.
Стивен Судит
11
насколько это дорого? может нам стоит засечь секундомер :)
jb.
3
@ Стивен, это зависит от ОС и оборудования. Если возможно, используется таймер с высоким разрешением, что характерно для всех известных мне версий Windows x86 для настольных и серверных компьютеров. Для получения более подробной информации проверьте свойства Frequency и IsHighResolution. На уровне ОС QueryPerformanceCounter и QueryPerformanceFrequency - это низкоуровневые API, поддерживающие эту функциональность.
Крис Тейлор,
323
long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;

Именно так в DateTimeOffsetклассе реализованы различные методы преобразования Unix (.NET Framework 4.6+, .NET Standard 1.3+):

long milliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();
Эван Мулавски
источник
66
Заголовок - «получить время в миллисекундах». Этот ответ полезен.
Aerospace
33
Да, для тех из нас, кто ищет ответ на поставленный вопрос, это было очень полезно, спасибо.
user430788
1
Если вам нужны десятичные дроби (даже если они DateTime.Nowне обновляются очень часто), конечно, используйте decimal milliseconds = DateTime.Now.Ticks / (decimal)TimeSpan.TicksPerMillisecond;вместо них.
Jeppe Stig Nielsen
1
Это гораздо более полезно, чем выбранный ответ для результатов поиска и даже для того, что я понял из исходного вопроса.
bwoogie
1
Этот ответ спас мне жизнь. Есть аналогичный код, но он не работает. Не мог понять почему. Затем я увидел longтип данных перед миллисекундами. Использование intнаверняка переполнится.
FisNaN
13

DateTime.TicksСвойство получает количество тиков , которые представляют дату и время.

10 000 тиков - это миллисекунда (10 000 000 тиков в секунду).

Итай Каро
источник
4
Но разрешение Ticks намного меньше 1/10000 с, может быть
1/62
2
@codymanix - из MSDN:A single tick represents one hundred nanoseconds or one ten-millionth of a second. There are 10,000 ticks in a millisecond.
Итай Каро,
5
Конечно, это так, но в операционной системе нет такого точного разрешения.
codymanix
6
@codymanix правильный. По аналогии Ангстрем - это единица длины; десять миллиардов ангстрем составляют один метр. Вы можете написать функцию, которая сообщает ваш рост как 64-битное целое число в Ангстремах, но если все, что у вас есть, это метрическая шкала с точностью до сантиметра, то тот факт, что функция представляет субнанометровую точность, совершенно не имеет значения. Менее значимые цифры будут мусором.
Эрик Липперт,
4
@RedFilter: если бы вы действительно знали свой возраст с точностью до миллисекунды, вы могли бы сказать что-то вроде: «Когда я снова моргну, мой возраст будет x миллисекунд». Более глубокая проблема - это не общение, а измерение: вряд ли ваше рождение станет известно даже с точностью до секунды.
Стивен Судит,
11

Использую следующий класс. Однажды я нашел его в Интернете, и он был признан лучшим СЕЙЧАС () .

/// <summary>Class to get current timestamp with enough precision</summary>
static class CurrentMillis
{
    private static readonly DateTime Jan1St1970 = new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    /// <summary>Get extra long current timestamp</summary>
    public static long Millis { get { return (long)((DateTime.UtcNow - Jan1St1970).TotalMilliseconds); } }
}

Источник неизвестен.

schmijos
источник
5
FWIW, весь смысл этого часто используемого фрагмента, состоит в том, чтобы создать временную метку, совместимую со стандартом временных меток Unix. Для этого это жизненно важно. Если кто-то просто хочет рассчитать время, это неоправданно дорого.
ToolmakerSteve
8

Можете попробовать QueryPerformanceCounterродной метод. См. Http://www.pinvoke.net/default.aspx/kernel32/QueryPerformanceCounter.html для получения дополнительной информации. Это то, что Stopwatchиспользует класс.

См. Раздел Как получить метку времени точности тиков в .NET / C #? Чтобы получить больше информации.

Stopwatch.GetTimestamp() дает доступ к этому методу:

public static long GetTimestamp() {
     if(IsHighResolution) {
         long timestamp = 0;
         SafeNativeMethods.QueryPerformanceCounter(out timestamp);
         return timestamp;
     }
     else {
         return DateTime.UtcNow.Ticks;
     }
 }
Питер ван Гинкель
источник
1
AFAIK StopWatch использует QueryPerformanceCounter внутри, если он доступен
codymanix
Да, внутренняя реализация Stopwatch.GetTimestamp()фактически предоставляет доступ к этому методу.
Питер ван Гинкель
5

Я использовал DateTime.Now.TimeOfDay.TotalMilliseconds (на текущий день), надеюсь, это тоже поможет вам.

Sarvan
источник
1
который не будет возвращать возрастающие значения (как требовал исходный плакат), так как TimeOfDay сбрасывается на ноль каждый день в полночь. Кроме того, у него будут те же потенциальные проблемы, о которых упоминал плакат, при использовании DateTime.Теперь можно получить общее количество миллисекунд от этого.
Джим О'Нил
3
Джим О'Нил Я согласен с вами, поэтому я упомянул «(на текущий день)» в своем сообщении ... Кстати, мое решение сработало для моей проблемы, поскольку моя проблема не привязана к дате, мне просто нужно было получить часть миллисекунд, которая будет использоваться в качестве счетчика, поэтому я разместил ее здесь. Я здесь новенький, поэтому, если я разместил его не в том месте, извините :)
Сарван
2

Используйте System.DateTime.Now.ToUniversalTime(). Это переводит ваше чтение в известный справочный миллисекундный формат, который полностью исключает смену дня и т. Д.

Джон Тоблер
источник
Полезно знать, но не имеет отношения к задаваемому вопросу, который касается времени (измерение времени), а не точной передачи времени.
ToolmakerSteve,