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


134

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

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


Ожидаете ли вы, что любые два вызова всегда будут приводить к увеличению значений? Как правило, вызовы с интервалом ближе, чем минимальный интервал, разрешенный разрешением таймера, будут давать такое же значение. Вам нужно будет добавить свой собственный инструмент разрешения конфликтов в виде сериализатора с фиктивной точностью.
Стивен Судит

16
«Число, которое никогда не равно самому себе». Звучит ... сложно. ;)
Mizipzor

1
На самом деле NaN соответствует этому требованию. Несмотря на то, что это «не число», это числовой тип, и он не равен самому себе.
Yay295 04

Ответы:


78

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

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

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

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


8
секундомер является частью диагностики. Следует ли использовать его в реальном коде?
Андрей


Обычно это точность до ближайших 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); } }
}

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


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 (на текущий день), надеюсь, это тоже поможет вам.


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

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

2

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


Полезно знать, но не имеет отношения к задаваемому вопросу, который касается времени (измерение времени), а не точной передачи времени.
ToolmakerSteve,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.