Отримайте час у мілісекундах, використовуючи C #


131

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

Чи є простіший спосіб зробити це?


Чи очікуєте, що будь-які два дзвінки завжди приведуть до зростання цін? Загалом, дзвінки, менші за мінімальний інтервал, який дозволяє роздільна здатність таймера, отримають те саме значення. Вам потрібно буде додати свій власний розрив у формі фальшивого точного серіалізатора.
Стівен Судіт

16
"Число, яке ніколи не дорівнює собі". Це звучить ... складно. ;)
Мізіпзор

1
NaN фактично відповідав би цій вимозі. Незважаючи на те, що він "не число", він є числовим типом, і він не дорівнює собі.
Yay295

Відповіді:


78

Використовуйте Stopwatchклас.

Надає набір методів і властивостей, які можна використовувати для точного вимірювання минулого часу.

Тут є хороша інформація про її реалізацію:

Тести продуктивності: точні вимірювання часу запуску за допомогою System.Diagnostics.Stopwatch


8
секундомір є частиною діагностики. Чи слід його використовувати в реальному коді?
Андрій


Зазвичай це точне лише до найближчих 15 мс.
Стівен Судіт

11
наскільки це дорого? можливо, нам слід зупинити секундомір :)
jb.

3
@Steven, це залежить від ОС та базового обладнання. Якщо є, використовується таймер високої роздільної здатності, що стосується всіх поточних настільних і серверних версій x86 Windows, про які я знаю. Перевірте властивості частоти та IsHighResolution для отримання більш детальної інформації. На рівні ОС QueryPerformanceCounter та QueryPerformanceFrequency - це API низького рівня, які підтримують цю функціональність.
Кріс Тейлор

320
long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;

Це власне те, як різні методи перетворення Unix реалізуються в DateTimeOffsetкласі (.NET Framework 4.6+, .NET Standard 1.3+):

long milliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();

65
Заголовок - "отримати час у мілісекундах". Ця відповідь корисна.
Аерокосмічний

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
Але дозвіл Тікса дуже менше 1/10000, можливо, 1 /
62s

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.
Itay Karo

5
Звичайно, але операційна система не має такої чіткості.
codymanix

6
@codymanix правильний. За аналогією, ангстрем - це одиниця довжини; десять мільярдів ангстрем складають один метр. Ви можете написати функцію, яка повідомляє про ваш зріст як 64-бітове ціле число в Angstroms, але якщо у вас є метрика з точністю до сантиметра, то той факт, що функція представляє точність субнометру, абсолютно не має значення. Менш значущі цифри будуть сміттям.
Ерік Ліпперт

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.Серед отримуючи від цього загальні мілісекунди.
Jim O'Neil

3
Jim O'Neil Я згоден з u, тому я згадав "(для поточного дня)" у своєму дописі ... До речі, моє рішення працювало на мою проблему, оскільки моя проблема не залежить від дати, мені просто потрібно було отримати частина мілісекунд, яка буде використана як лічильник, тому я розмістив її тут. Я тут новий, тому якщо я розмістив його в
іншому

2

Використовуйте System.DateTime.Now.ToUniversalTime(). Це ставить ваше читання у відомий опорний мілісекундний формат, який повністю виключає зміну дня тощо.


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