Ottieni DateTime.Now con precisione in millisecondi


231

Come posso costruire esattamente un timestamp di tempo reale con precisione in millisecondi?

Ho bisogno di qualcosa come il 16.4.2013 9: 48: 00: 123. È possibile? Ho un'applicazione, in cui campiono i valori 10 volte al secondo e devo mostrarli in un grafico.



Tieni presente che un numero di risposte utilizza hhper ore (ora solare). Nel caso di un timestamp (e in molti altri casi), questo dovrebbe probabilmente essere accoppiato con tt(am / pm) o sostituito da HH(tempo militare).
Goz

Risposte:


304

Come posso costruire esattamente un timestamp di tempo reale con precisione in millisecondi?

Ho il sospetto che intendi la precisione in millisecondi . DateTimeha molta precisione, ma è abbastanza grossolano in termini di accuratezza. In generale, non puoi. Di solito l'orologio di sistema (da dove DateTime.Nowottiene i suoi dati) ha una risoluzione di circa 10-15 ms. Vedi il post sul blog di Eric Lippert sulla precisione e accuratezza per maggiori dettagli.

Se hai bisogno di tempi più precisi di questo, potresti voler esaminare usando un client NTP.

Tuttavia, non è chiaro che qui hai davvero bisogno di una precisione di millisecondi. Se non ti interessa il momento esatto , vuoi solo mostrare i campioni nell'ordine giusto, con una precisione "abbastanza buona", quindi l'orologio di sistema dovrebbe andare bene. Ti consiglierei di usare DateTime.UtcNowpiuttosto che DateTime.Nowperò, per evitare problemi di fuso orario attorno alle transizioni di ora legale, ecc.

Se la tua domanda è in realtà proprio dietro la conversione di una DateTimead una stringa con precisione micrometrica, io suggerirei utilizzando:

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

(Nota che a differenza del tuo campione, questo è ordinabile e ha meno probabilità di creare confusione sul fatto che debba essere "mese / giorno / anno" o "giorno / mese / anno".)


5
@antonio: senza più informazioni di "non funziona" non posso fornire altro aiuto.
Jon Skeet,

Sì, posso fornire ulteriori informazioni: "{0: yyyyMMdd HH: mm: ss.fff}", DateTime.UtcNow -> 20180502 11: 07: 20.000 Win32.GetSystemTime (ref stime) -> 2018,2,5,11 , 7,20,0 (ymdh mm ss ms) Posso creare un'istanza di data e ora con millisecondi: var dt = new DateTime (2018, 5, 2, 19, 34, 55, 200); "{0: yyyyMMdd HH: mm: ss.fff}", dt -> 20180502 19: 34: 55.200. Framework compatto netto, Windows Embedded Compact 7, su ARM Cortex-A8
antonio

@antonio: Quindi sembra che la versione di .NET che stai usando sull'hardware che stai usando semplicemente non fornisca una precisione inferiore al secondo - o ti è capitato di chiamarla su un secondo limite. (Se continui a colpire DateTime.UtcNowripetutamente, aumenta sempre e solo una volta al secondo? Non l'hai dimostrato.)
Jon Skeet,

Quando recupero i tick da DateTime.Now, il valore viene troncato: tick 636534596580000000 DateTime da tick 20180205 20: 34: 18.000. la limitazione è nel disco rigido / software, penso. Ho usato la classe Cronometro, invece Grazie Jon
antonio il

@antonio: probabilmente vale la pena creare una nuova domanda con tutti i dettagli del dispositivo coinvolto a questo punto.
Jon Skeet,

117

Questo dovrebbe funzionare:

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

Se non ti serve che sia visualizzato e devi solo conoscere la differenza di tempo, non convertirlo in una stringa. Lascialo come,DateTime.Now();

E usa TimeSpanper conoscere la differenza tra gli intervalli di tempo:

Esempio

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'));

Ho bisogno di calcolarlo, quindi non posso convertirlo in stringa.
LuckyHK

25

Stavo cercando una soluzione simile, basandomi su ciò che è stato suggerito su questo thread, utilizzo quanto segue DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.fff") e funziona come un incantesimo. Nota: questi .fffsono i numeri di precisione che si desidera acquisire.


1
Se la data è nel pomeriggio (16:00) verrà visualizzato come al mattino. FIX: utilizzare HH(tempo militare) o aggiungere tt(PM o AM). Come mostrato in questo esempio: repl.it/KGr3/1
Jaider

22

Usa la struttura DateTime con millisecondi e formatta in questo modo:

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

16

La risposta di Pyromancer mi sembra abbastanza buona, ma forse volevi:

DateTime.Now.Millisecond

Ma se stai confrontando le date, TimeSpan è la strada da percorrere.


15
Nota: se si sta confrontando la differenza tra due DateTimes come TimeSpan, è necessario TotalMilliseconds. Millisecondi detiene l'attuale contatore Millisecondi, che non è mai maggiore di 1000, mentre TotalMillisecondi detiene i millisecondi totali trascorsi dall'epoca.
Contango,

4

Se desideri comunque una data anziché una stringa come le altre risposte, aggiungi questo metodo di estensione.

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

Per quanto ho capito la domanda, puoi scegliere:

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

Questo taglierà le zecche inferiori a 1 millisecondo.


Sì, ma la risoluzione effettiva di DateTime.Now potrebbe non essere superiore a circa 16 ms.
Peter Mortensen,

2

Il problema con DateTime.UtcNowed DateTime.Nowè che, a seconda del computer e sistema operativo, che può solo essere precisi tra 10 e 15 millisecondi. Tuttavia, sui computer Windows è possibile utilizzare la funzione di basso livello GetSystemTimePreciseAsFileTime per ottenere la precisione dei microsecondi, vedere la funzione di GetTimeStamp()seguito.

    [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;
    }

Grazie mille. Ho cercato così a lungo. Causa problemi di prestazioni ed è sicuro utilizzare il codice di produzione?
Muhammet Göktürk Ayan,


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

Se vuoi microsecondi, basta passare 10000a 10e se vuoi il decimo di micro, elimina / 10000.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.