Come ottenere l'ora corrente in millisecondi da C in Linux?


86

Come ottengo l'ora corrente su Linux in millisecondi?

Risposte:


100

Ciò può essere ottenuto utilizzando la funzione POSIXclock_gettime .

Nella versione corrente di POSIX, gettimeofdayè contrassegnato come obsoleto . Ciò significa che potrebbe essere rimosso da una versione futura della specifica. Gli autori di applicazioni sono incoraggiati a utilizzare la clock_gettimefunzione invece di gettimeofday.

Ecco un esempio di come utilizzare 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);
}

Se il tuo obiettivo è misurare il tempo trascorso e il tuo sistema supporta l'opzione "orologio monotonico", dovresti considerare di usare CLOCK_MONOTONICinvece di CLOCK_REALTIME.


7
+1 per essere POSIXly corretto, ma la tua risposta ha le unità sbagliate. L'OP non vuole il tempo con millisecondi, ma il tempo in millisecondi.
pilcrow

5
Buona soluzione ma non dimenticare il -lm nel tuo gcccomando.
David Guyon

2
secondo la manpage di round, si desidera utilizzare lround quando si assegna il risultato a un numero intero (o lungo)
hildred

2
Devi usare floor () invece di round () in modo che non arrivi mai a 1000 ms. Altrimenti dovresti incrementare squando questo accade. Probabilmente un evento raro, ma la cifra in più può causare problemi.
Mike

1
@Mike Bella cattura. A uno su duemila, non è nemmeno così raro, quindi dovrebbe assolutamente essere risolto. Piuttosto che usare floor, penso che preferirei mantenere un po 'più di precisione e continuare ad arrotondare, ma incrementare il secondo contatore se arrotonda fino a 1000.
Dan Molding

58

Devi fare qualcosa del genere:

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

Di seguito è riportata la funzione util per ottenere il timestamp corrente in millisecondi:

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

Informazioni sul fuso orario :

supporto gettimeofday () per specificare il fuso orario, io uso NULL , che ignora il fuso orario, ma puoi specificare un fuso orario, se necessario.


@Update - fuso orario

Poiché la longrappresentazione del tempo non è rilevante o influenzata dal fuso orario stesso, l'impostazione del tzparametro gettimeofday () non è necessaria, poiché non farà alcuna differenza.

E, secondo la pagina man di gettimeofday(), l'uso della timezonestruttura è obsoleto, quindi l' tzargomento dovrebbe normalmente essere specificato come NULL, per i dettagli si prega di controllare la pagina man.


1
> supporto gettimeofday () per specificare il fuso orario, io uso NULL, che ignora il fuso orario, ma puoi specificare un fuso orario, se necessario. Tui hai torto. Il fuso orario dovrebbe essere introdotto esclusivamente tramite la chiamata a localtime ().
vitaly.v.ch

@ vitaly.v.ch Ho fatto un test, superando il tzparametro gettimeofday()as &(struct timezone tz = {480, 0})non avrò nessun avviso, e non ha alcun effetto sul risultato, questo ha senso, dato che la longrappresentazione del tempo non è rilevante o effettuata dal fuso orario stesso, giusto?
Eric Wang

Non c'era motivo di fare alcun test. Il kernel Linux non ha informazioni adeguate sui fusi orari e allo stesso tempo non ha un modo per fornirle. È un motivo per cui l'argomento tz viene elaborato in modo molto specifico. la lunga rappresentazione non ha importanza.
vitaly.v.ch

@ vitaly.v.ch In un momento specifico, la rappresentazione lunga non varia a causa del fuso orario, ecco perché è importante, e per questo normalmente NULLè solo il valore ragionevole da passare. E credo che il test sia sempre un buon approccio per dimostrare le cose.
Eric Wang

13

Utilizzare gettimeofday()per ottenere il tempo in secondi e microsecondi. La combinazione e l'arrotondamento a millisecondi vengono lasciati come esercizio.



0

Derivato dalla risposta POSIX di Dan Moulding, dovrebbe funzionare:

#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);
}

Inoltre, come sottolineato da David Guyon: compilare con -lm

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.