¿Cómo obtener la hora actual en milisegundos de C en Linux?


86

¿Cómo obtengo la hora actual en Linux en milisegundos?

Respuestas:


100

Esto se puede lograr utilizando la función POSIXclock_gettime .

En la versión actual de POSIX, gettimeofdayestá marcado como obsoleto . Esto significa que puede eliminarse de una versión futura de la especificación. Se anima a los escritores de aplicaciones a utilizar la clock_gettimefunción en lugar de gettimeofday.

A continuación, se muestra un ejemplo de cómo utilizarlo clock_gettime:

#define _POSIX_C_SOURCE 200809L

#include <inttypes.h>
#include <math.h>
#include <stdio.h>
#include <time.h>

void print_current_time_with_ms (void)
{
    long            ms; // Milliseconds
    time_t          s;  // Seconds
    struct timespec spec;

    clock_gettime(CLOCK_REALTIME, &spec);

    s  = spec.tv_sec;
    ms = round(spec.tv_nsec / 1.0e6); // Convert nanoseconds to milliseconds
    if (ms > 999) {
        s++;
        ms = 0;
    }

    printf("Current time: %"PRIdMAX".%03ld seconds since the Epoch\n",
           (intmax_t)s, ms);
}

Si su objetivo es medir el tiempo transcurrido y su sistema admite la opción "reloj monótono", debería considerar usar en CLOCK_MONOTONIClugar de CLOCK_REALTIME.


7
+1 por ser POSIX correctamente correcto, pero su respuesta tiene las unidades incorrectas. El OP no quiere el tiempo en milisegundos, sino el tiempo en milisegundos.
Pilcrow

5
Buena solución, pero no olvide el -lm en su gcccomando.
David Guyon

2
de acuerdo con la página de manual de round, desea usar lround al asignar el resultado a un entero (o largo)
hildred

2
Necesita usar floor () en lugar de round () para que nunca se redondea a 1000 ms. De lo contrario, necesitaría incrementar scuando esto ocurra. Probablemente sea un evento poco común, pero el dígito extra puede causar problemas.
Mike

1
@ Mike Niza captura. En uno de cada dos mil, ni siquiera es tan raro, por lo que definitivamente debería arreglarse. En lugar de usar el piso, creo que preferiría mantener un poco más de precisión y continuar redondeando, pero incrementar el segundo contador si se redondea a 1000.
Dan Molding

58

Tienes que hacer algo como esto:

struct timeval  tv;
gettimeofday(&tv, NULL);

double time_in_mill = 
         (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000 ; // convert tv_sec & tv_usec to millisecond

33

A continuación se muestra la función util para obtener la marca de tiempo actual en milisegundos:

#include <sys/time.h>

long long current_timestamp() {
    struct timeval te; 
    gettimeofday(&te, NULL); // get current time
    long long milliseconds = te.tv_sec*1000LL + te.tv_usec/1000; // calculate milliseconds
    // printf("milliseconds: %lld\n", milliseconds);
    return milliseconds;
}

Acerca de la zona horaria :

Soporte de gettimeofday () para especificar la zona horaria, yo uso NULL , que ignora la zona horaria, pero puede especificar una zona horaria, si es necesario.


@Update - zona horaria

Dado que la longrepresentación del tiempo no es relevante ni se ve afectada por la zona horaria en sí, tzno es necesario establecer el parámetro de gettimeofday (), ya que no hará ninguna diferencia.

Y, de acuerdo con la página de manual de gettimeofday(), el uso de la timezoneestructura es obsoleto, por lo que el tzargumento normalmente debe especificarse como NULL; para obtener más detalles, consulte la página de manual.


1
> Soporte para gettimeofday () para especificar la zona horaria, yo uso NULL, que ignora la zona horaria, pero puede especificar una zona horaria, si es necesario. Está usted equivocado. La zona horaria debe introducirse exclusivamente mediante una llamada a localtime ().
vitaly.v.ch

@ vitaly.v.ch Hice una prueba, pasando el tzparámetro de gettimeofday()as &(struct timezone tz = {480, 0})no recibirá ninguna advertencia, y no tiene ningún efecto en el resultado, eso tiene sentido, ya que la longrepresentación del tiempo no es relevante ni se efectúa por zona horaria en sí, ¿verdad?
Eric Wang

No había razón para hacer ninguna prueba. El kernel de Linux no tiene la información adecuada sobre las zonas horarias y, al mismo tiempo, no tiene una forma de proporcionarla. Es una razón por la que el argumento tz se procesa de una manera muy específica. la representación larga no importa.
vitaly.v.ch

@ vitaly.v.ch En un punto de tiempo específico, la representación larga no varía debido a la zona horaria, por eso es importante, y debido a eso, normalmente solo se NULLpasa el valor razonable. Y creo que las pruebas siempre son un buen enfoque para probar las cosas.
Eric Wang



0

Derivado de la respuesta POSIX de Dan Moulding, esto debería funcionar:

#include <time.h>
#include <math.h>

long millis(){
    struct timespec _t;
    clock_gettime(CLOCK_REALTIME, &_t);
    return _t.tv_sec*1000 + lround(_t.tv_nsec/1.0e6);
}

También como lo señaló David Guyon: compile con -lm

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.