Obtenga DateTime.Ahora con precisión de milisegundos


231

¿Cómo puedo construir exactamente una marca de tiempo del tiempo real con precisión de milisegundos?

Necesito algo como 16.4.2013 9: 48: 00: 123. es posible? Tengo una aplicación, donde muestro valores 10 veces por segundo, y necesito mostrarlos en un gráfico.



Tenga en cuenta que varias de las respuestas se utilizan hhdurante horas (hora estándar). En el caso de una marca de tiempo (y en muchos otros casos), esto probablemente debería emparejarse con tt(am / pm) o reemplazarse por HH(hora militar).
wentz

Respuestas:


304

¿Cómo puedo construir exactamente una marca de tiempo del tiempo real con precisión de milisegundos?

Sospecho que te refieres a la precisión de milisegundos . DateTimetiene mucha precisión, pero es bastante tosco en términos de precisión. En general, no puedes. Por lo general, el reloj del sistema (que es de donde DateTime.Nowobtiene sus datos) tiene una resolución de alrededor de 10-15 ms. Consulte la publicación del blog de Eric Lippert sobre precisión y exactitud para obtener más detalles.

Si necesita una sincronización más precisa que esta, es posible que desee considerar el uso de un cliente NTP.

Sin embargo, no está claro que realmente necesites una precisión de milisegundos aquí. Si no le importa el momento exacto , solo desea mostrar las muestras en el orden correcto, con una precisión "bastante buena", entonces el reloj del sistema debería estar bien. Le aconsejaría que use en DateTime.UtcNowlugar de hacerlo DateTime.Now, para evitar problemas de zona horaria alrededor de las transiciones de horario de verano, etc.

Si su pregunta es en realidad acerca de convertir un DateTimea una cadena con precisión de milisegundos, sugiero usar:

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

(Tenga en cuenta que, a diferencia de su muestra, esto es ordenable y es menos probable que cause confusión sobre si debe ser "mes / día / año" o "día / mes / año").


55
@antonio: Sin más información que "no funciona", no puedo proporcionar más ayuda.
Jon Skeet

Sí, puedo proporcionar más información: "{0: aaaaMMdd 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) Puedo crear una instancia de fecha y hora con milisegundos: var dt = new DateTime (2018, 5, 2, 19, 34, 55, 200); "{0: aaaaMMdd HH: mm: ss.fff}", dt -> 20180502 19: 34: 55.200 .Net compact framework, Windows Embedded Compact 7, en ARM Cortex-A8
antonio

@antonio: Parece que la versión de .NET que está utilizando en el hardware que está utilizando simplemente no proporciona una precisión de un segundo, o resultó que la llamó en un segundo límite. (Si sigues golpeando DateTime.UtcNowrepetidamente, ¿solo aumenta una vez por segundo? No lo has demostrado.)
Jon Skeet

Cuando recupero Ticks de DateTime. Ahora, el valor viene truncado: Ticks 636534596580000000 DateTime de Ticks 20180205 20: 34: 18.000. La limitación está en el hardware / software, creo. He usado la clase de cronómetro, en cambio, gracias Jon
antonio

@antonio: Probablemente valga la pena crear una nueva pregunta con todos los detalles del dispositivo involucrado en este punto.
Jon Skeet

117

Esto debería funcionar:

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

Si no necesita que se muestre y solo necesita saber la diferencia horaria, no lo convierta en una cadena. Solo déjalo como,DateTime.Now();

Y usa TimeSpanpara saber la diferencia entre los intervalos de tiempo:

Ejemplo

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

Necesito calcular con él, así que no puedo convertirlo en cadena.
LuckyHK

25

Estaba buscando una solución similar, basada en lo sugerido en este hilo, utilizo lo siguiente DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.fff") y funciona a la perfección. Nota: esos .fffson los números de precisión que desea capturar.


1
Si la fecha es en la tarde (4PM) se mostrará como en la mañana. REVISIÓN: Use HH(tiempo militar) o agregue tt(PM o AM). Como se muestra en este ejemplo: repl.it/KGr3/1
Jaider

22

Use la estructura DateTime con milisegundos y un formato como este:

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

16

La respuesta de Pyromancer me parece bastante buena, pero tal vez querías:

DateTime.Now.Millisecond

Pero si está comparando fechas, TimeSpan es el camino a seguir.


15
Nota: Si está comparando la diferencia entre dos DateTimes como TimeSpan, necesita TotalMilliseconds. Milisegundos contiene el contador actual de Milisegundos, que nunca es mayor que 1000, mientras que TotalMilliseconds contiene el total de milisegundos transcurridos desde la época.
Contango

4

Si aún desea una fecha en lugar de una cadena como las otras respuestas, simplemente agregue este método de extensión.

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

Hasta donde entiendo la pregunta, puedes ir por:

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

Esto cortará las garrapatas de menos de 1 milisegundo.


Sí, pero la resolución real de DateTime.Now no puede superar los 16 ms.
Peter Mortensen

2

El problema con DateTime.UtcNowy DateTime.Nowes que, dependiendo de la computadora y el sistema operativo, puede ser preciso entre 10 y 15 milisegundos. Sin embargo, en las computadoras con Windows se puede usar la función de bajo nivel GetSystemTimePreciseAsFileTime para obtener una precisión de microsegundos, consulte la función a GetTimeStamp()continuación.

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

Muchas gracias. He estado buscando esto por mucho tiempo. ¿Causa algún problema de rendimiento y es seguro usar el código de producción?
Muhammet Göktürk Ayan


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

Si desea microsegundos, simplemente cambie 10000a 10, y si desea el décimo de micro, elimine / 10000.


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.