Отримайте DateTime.Now з точністю до мілісекунд


231

Як я можу точно побудувати часовий штамп фактичного часу з точністю до мілісекунд?

Мені потрібно щось на зразок 16.4.2013 9: 48: 00: 123. Чи можливо це? У мене є додаток, де я вибираю значення 10 разів на секунду, і мені потрібно показувати їх у графі.



Майте на увазі, що ряд відповідей використовується hhгодинами (стандартний час). У разі позначки часу (і в багатьох інших випадках) це, мабуть, повинно бути спарене з tt(am / pm) або замінено на HH(військовий час).
goz

Відповіді:


304

Як я можу точно побудувати часовий штамп фактичного часу з точністю до мілісекунд?

Я підозрюю, що ви маєте на увазі точність мілісекунд . DateTimeмає велику точність, але з точки зору точності є досить грубою. Взагалі кажучи, ви не можете. Зазвичай системний годинник (звідки DateTime.Nowотримує свої дані) має роздільну здатність близько 10-15 мс. Докладнішу інформацію див. У блозі Еріка Ліпперта про точність та точність .

Якщо вам потрібні більш точні терміни, ніж це, ви, можливо, захочете переглянути NTP-клієнт.

Однак незрозуміло, що вам тут справді потрібна точність мілісекунд. Якщо вас не хвилює точний термін - ви просто хочете показати зразки в потрібному порядку з "досить хорошою" точністю, тоді системний годинник повинен бути нормальним. Я б радив скористатися, DateTime.UtcNowа не DateTime.Nowхоч, щоб уникнути проблем із часовим поясом навколо переходів на літній час тощо.

Якщо ваше запитання насправді полягає лише в перетворенні a DateTimeна рядок з мілісекундною точністю, я б запропонував використовувати:

string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff",
                                            CultureInfo.InvariantCulture);

(Зауважте, що на відміну від вашої вибірки, це є сортуванням і менше шансів викликати плутанину навколо того, чи мається на увазі це "місяць / день / рік" або "день / місяць / рік".)


5
@antonio: Не маючи більше інформації, ніж "не працює", я не можу надати більше ніякої допомоги.
Джон Скіт

Так, я можу надати додаткову інформацію: "{0: yyyyMMdd HH: mm: ss.fff}", DateTime.UtcNow -> 20180502 11: 07: 20.000 Win32.GetSystemTime (refime) -> 2018,2,5,11 , 7,20,0 (ymdh mm ss ms) Я можу створити екземпляр часу дати з мілісекундами: var dt = new DateTime (2018, 5, 2, 19, 34, 55, 200); "{0: yyyyMMdd HH: mm: ss.fff}", dt -> 20180502 19: 34: 55.200. Чистий компактний каркас, Windows Embedded Compact 7, на ARM Cortex-A8
antonio

@antonio: Таким чином, це виглядає як версія .NET, яку ви використовуєте на апаратному забезпеченні, яке ви використовуєте, просто не забезпечує підсекундну точність - або вам трапилось зателефонувати на другу межу. (Якщо ви постійно DateTime.UtcNowповторюєте удари , чи збільшується це лише раз на секунду? Ви цього не показували.)
Джон Скіт

Коли я отримую Ticks з DateTime.Now, значення прирізається: Ticks 636534596580000000 DateTime from Ticks 20180205 20: 34: 18.000. я думаю, обмеження в жорсткому / програмному забезпеченні. Я замість цього використовую клас Секундомір Спасибі Йон
антоніо

@antonio: Напевно, варто створити нове запитання з усіма детальними відомостями про пристрій, що займається на даний момент.
Джон Скіт

117

Це має працювати:

DateTime.Now.ToString("hh.mm.ss.ffffff");

Якщо вам не потрібно, щоб він відображався і просто потрібно знати різницю в часі, добре не перетворюйте його на String. Просто залиште це якDateTime.Now();

І використовуйте, TimeSpanщоб знати різницю між часовими інтервалами:

Приклад

DateTime start;
TimeSpan time;

start = DateTime.Now;

//Do something here

time = DateTime.Now - start;
label1.Text = String.Format("{0}.{1}", time.Seconds, time.Milliseconds.ToString().PadLeft(3, '0'));

Мені потрібно обчислити його, тому я не можу перетворити його на рядок.
LuckyHK

25

Я шукав подібне рішення, базуючись на тому, що було запропоновано в цій темі, я використовую наступне DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.fff") , і воно працює як шарм. Примітка. .fffЦе точні цифри, які ви бажаєте зафіксувати.


1
Якщо дата вдень (4:00), буде показано, як і вранці. Виправлення: Використовуйте HH(військовий час) або додайте tt(PM або AM). Як показано в цьому прикладі: repl.it/KGr3/1
Jaider

22

Використовуйте структуру DateTime з мілісекундами та таким форматом:

string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", 
CultureInfo.InvariantCulture);
timestamp = timestamp.Replace("-", ".");

16

Відповідь Піроманса здається мені досить хорошою, але, можливо, ви хотіли:

DateTime.Now.Millisecond

Але якщо ви порівнюєте дати, TimeSpan - це шлях.


15
Примітка. Якщо ви порівнюєте різницю між двома DateTimes як TimeSpan, вам потрібно TotalMilliseconds. Мільсекунд утримує поточний лічильник мілісекунд, який ніколи не перевищує 1000, тоді як TotalMillise секунди містить загальний мілісекунд, що минув з епохи.
Контанго

4

Якщо ви все ще хочете дати замість рядка, як інші відповіді, просто додайте цей метод розширення.

public static DateTime ToMillisecondPrecision(this DateTime d) {
    return new DateTime(d.Year, d.Month, d.Day, d.Hour, d.Minute,
                        d.Second, d.Millisecond, d.Kind);
}

3

Наскільки я розумію питання, ви можете піти на:

DateTime dateTime = DateTime.Now;
DateTime dateTimeInMilliseconds = dateTime.AddTicks(-1 * dateTime.Ticks % 10000); 

Це дозволить відрізати кліщів менше 1 мілісекунди.


Так, але фактична роздільна здатність DateTime.Now може бути не більше ніж 16 мс.
Пітер Мортенсен

2

Проблема DateTime.UtcNowі в DateTime.Nowтому , що, в залежності від комп'ютера і операційної системи, це може бути тільки з точністю до від 10 до 15 мілісекунд. Однак на комп'ютерах Windows можна використовувати функцію низького рівня GetSystemTimePreciseAsFileTime для отримання мікросекундної точності, див. Функцію GetTimeStamp()нижче.

    [System.Security.SuppressUnmanagedCodeSecurity, System.Runtime.InteropServices.DllImport("kernel32.dll")]
    static extern void GetSystemTimePreciseAsFileTime(out FileTime pFileTime);

    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
    public struct FileTime  {
        public const long FILETIME_TO_DATETIMETICKS = 504911232000000000;   // 146097 = days in 400 year Gregorian calendar cycle. 504911232000000000 = 4 * 146097 * 86400 * 1E7
        public uint TimeLow;    // least significant digits
        public uint TimeHigh;   // most sifnificant digits
        public long TimeStamp_FileTimeTicks { get { return TimeHigh * 4294967296 + TimeLow; } }     // ticks since 1-Jan-1601 (1 tick = 100 nanosecs). 4294967296 = 2^32
        public DateTime dateTime { get { return new DateTime(TimeStamp_FileTimeTicks + FILETIME_TO_DATETIMETICKS); } }
    }

    public static DateTime GetTimeStamp() { 
        FileTime ft; GetSystemTimePreciseAsFileTime(out ft);
        return ft.dateTime;
    }

Дуже дякую. Я так довго шукав це. Чи це викликає якісь проблеми щодо продуктивності та чи безпечно використовувати виробничий код?
Muhammet Göktürk Ayan


-2
public long millis() {
  return (long.MaxValue + DateTime.Now.ToBinary()) / 10000;
}

Якщо вам потрібні мікросекунди, просто перейдіть 10000на 10, а якщо ви хочете 10-ту мікросекцію, видаліть / 10000.


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