Comment obtenir l'heure actuelle en millisecondes depuis C sous Linux?

86

Comment obtenir l'heure actuelle sous Linux en millisecondes?

JE VAIS
la source

Réponses:

100

Ceci peut être réalisé en utilisant la fonction POSIXclock_gettime .

Dans la version actuelle de POSIX, gettimeofdayest marqué comme obsolète . Cela signifie qu'il peut être supprimé d'une future version de la spécification. Les développeurs d'applications sont encouragés à utiliser la clock_gettimefonction à la place de gettimeofday.

Voici un exemple d'utilisation 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 votre objectif est de mesurer le temps écoulé et que votre système prend en charge l'option «horloge monotone», vous devriez envisager d'utiliser CLOCK_MONOTONICau lieu de CLOCK_REALTIME.

Moulage Dan
la source
7
+1 pour être POSIXly correct - mais votre réponse a les mauvaises unités. L'OP ne veut pas l'heure en millisecondes, mais l'heure en millisecondes.
pilcrow
5
Bonne solution mais n'oubliez pas le -lm dans votre gcccommande.
David Guyon
2
selon la page de manuel pour round, vous voulez utiliser lround lors de l'affectation du résultat à un entier (ou long)
hildred
2
Vous devez utiliser floor () au lieu de round () pour ne jamais arrondir à 1000 ms. Sinon, vous devrez incrémenter slorsque cela se produit. Probablement un événement rare, mais le chiffre supplémentaire peut causer des problèmes.
Mike
1
@Mike Belle prise. À un sur deux mille, ce n'est même pas si rare et devrait donc être résolu. Plutôt que d'utiliser le sol, je pense que je préfère conserver un peu plus de précision et continuer à arrondir, mais incrémenter le deuxième compteur s'il arrondit à 1000.
Dan Molding
58

Vous devez faire quelque chose comme ceci:

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
yadab
la source
33

Voici la fonction util pour obtenir l'horodatage actuel en millisecondes:

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

À propos du fuseau horaire :

gettimeofday () pour spécifier le fuseau horaire, j'utilise NULL , qui ignore le fuseau horaire, mais vous pouvez spécifier un fuseau horaire, si besoin.


@Update - fuseau horaire

Puisque la longreprésentation du temps n'est pas pertinente ou affectée par le fuseau horaire lui-même, il tzn'est pas nécessaire de définir le paramètre de gettimeofday (), car cela ne fera aucune différence.

Et, selon l' homme page gettimeofday(), l'utilisation de la timezonestructure est obsolète, donc l' tzargument doit normalement être NULL, pour plus de détails veuillez consulter la page man.

Eric Wang
la source
1
> gettimeofday () pour spécifier le fuseau horaire, j'utilise NULL, qui ignore le fuseau horaire, mais vous pouvez spécifier un fuseau horaire si besoin. Vous avez tort. Le fuseau horaire doit être introduit exclusivement via un appel à localtime ().
vitaly.v.ch
@ vitaly.v.ch J'ai fait un test, en passant le tzparamètre gettimeofday()as &(struct timezone tz = {480, 0})n'obtiendra aucun avertissement, et cela n'a aucun effet sur le résultat, cela a du sens, car la longreprésentation du temps n'est pas pertinente ni affectée par fuseau horaire lui-même, non?
Eric Wang
Il n'y avait aucune raison de faire un test. Le noyau Linux n'a pas les informations appropriées sur les fuseaux horaires, et en même temps n'a pas de moyen de les fournir. C'est une raison pour laquelle l'argument tz est traité de manière très spécifique. une longue représentation n'a pas d'importance.
vitaly.v.ch
@ vitaly.v.ch À un moment donné, la représentation longue ne varie pas en raison du fuseau horaire, c'est pourquoi c'est important, et pour cette raison, seule NULLla valeur raisonnable à passer. Et je pense que les tests sont toujours une bonne approche pour prouver les choses.
Eric Wang
13

Utilisez gettimeofday()pour obtenir l'heure en secondes et microsecondes. Combiner et arrondir en millisecondes reste un exercice.

Boursiers Donal
la source
7

C11 timespec_get

Il renvoie jusqu'à nanosecondes, arrondi à la résolution de l'implémentation.

Il est déjà implémenté dans Ubuntu 15.10. L'API ressemble au POSIX clock_gettime.

#include <time.h>
struct timespec ts;
timespec_get(&ts, TIME_UTC);
struct timespec {
    time_t   tv_sec;        /* seconds */
    long     tv_nsec;       /* nanoseconds */
};

Plus de détails ici: https://stackoverflow.com/a/36095407/895245

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
0

Dérivé de la réponse POSIX de Dan Moulding, cela devrait fonctionner:

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

Aussi comme le souligne David Guyon: compile avec -lm

Jirka Justra
la source