Wie kann ich die aktuelle Zeit in Millisekunden von C unter Linux abrufen?


85

Wie erhalte ich die aktuelle Zeit unter Linux in Millisekunden?

Antworten:


98

Dies kann mit der POSIX-clock_gettime Funktion erreicht werden.

In der aktuellen Version von POSIX gettimeofdayist dies als veraltet markiert . Dies bedeutet, dass es möglicherweise aus einer zukünftigen Version der Spezifikation entfernt wird. Anwendungsschreiber werden aufgefordert, die clock_gettimeFunktion anstelle von zu verwenden gettimeofday.

Hier ist ein Beispiel für die Verwendung 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);
}

Wenn Sie die verstrichene Zeit messen möchten und Ihr System die Option "monotone Uhr" unterstützt, sollten Sie die Verwendung von CLOCK_MONOTONICanstelle von in Betracht ziehen CLOCK_REALTIME.


6
+1 für POSIXly korrekt - aber Ihre Antwort hat die falschen Einheiten. Das OP möchte nicht die Zeit in Millisekunden, sondern die Zeit in Millisekunden.
Pilcrow

5
Gute Lösung, aber vergessen Sie nicht das -lm in Ihrem gccBefehl.
David Guyon

1
Laut der Manpage für Runde möchten Sie lround verwenden, wenn Sie das Ergebnis einer ganzen Zahl (oder langen)
zuweisen

2
Sie müssen floor () anstelle von round () verwenden, damit es niemals auf 1000 ms aufrundet. Andernfalls müssten Sie sin diesem Fall inkrementieren . Wahrscheinlich ein seltenes Ereignis, aber die zusätzliche Ziffer kann Probleme verursachen.
Mike

1
@ Mike Schöner Fang. Bei einem von zweitausend ist es nicht einmal so selten, sollte also definitiv behoben werden. Anstatt Boden zu verwenden, würde ich es vorziehen, etwas mehr Genauigkeit beizubehalten und weiter zu runden, aber den zweiten Zähler zu erhöhen, wenn er auf 1000 aufrundet.
Dan Moulding

58

Sie müssen so etwas tun:

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

Im Folgenden finden Sie die Util-Funktion zum Abrufen des aktuellen Zeitstempels in Millisekunden:

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

Über die Zeitzone :

gettimeofday () Unterstützung zur Angabe der Zeitzone, ich verwende NULL , die die Zeitzone ignorieren, aber Sie können bei Bedarf eine Zeitzone angeben.


@ Update - Zeitzone

Da die longDarstellung der Zeit für die Zeitzone selbst nicht relevant ist oder von tzdieser beeinflusst wird, ist es nicht erforderlich, den Parameter gettimeofday () festzulegen, da dies keinen Unterschied macht.

Und nach Mann Seite gettimeofday(), die Verwendung der timezoneist Struktur obsolet, so die tzArgumentation sollte normalerweise als NULL angegeben werden, für Details überprüfen Sie bitte die Manpage.


1
> gettimeofday () Unterstützung zur Angabe der Zeitzone, ich verwende NULL, die die Zeitzone ignorieren, aber Sie können bei Bedarf eine Zeitzone angeben. Sie liegen falsch. Die Zeitzone sollte ausschließlich per Aufruf von localtime () eingeführt werden.
vitaly.v.ch

@ vitaly.v.ch Ich habe einen Test durchgeführt, bei dem der tzParameter von gettimeofday()as &(struct timezone tz = {480, 0})nicht gewarnt wurde, und es hat keine Auswirkung auf das Ergebnis, was sinnvoll ist, da die longDarstellung der Zeit für oder beeinflusst nicht relevant ist nach Zeitzone selbst, richtig?
Eric Wang

Es gab keinen Grund, einen Test durchzuführen. Der Linux-Kernel verfügt nicht über die richtigen Informationen zu Zeitzonen und kann diese auch nicht bereitstellen. Dies ist ein Grund, warum das Argument tz sehr spezifisch verarbeitet wird. lange Darstellung spielt keine Rolle.
vitaly.v.ch

@ vitaly.v.ch Zu einem bestimmten Zeitpunkt variiert die lange Darstellung nicht aufgrund der Zeitzone, deshalb ist es wichtig, und aus diesem Grund ist normalerweise nur NULLder angemessene Wert zu übergeben. Und ich glaube, Testen ist immer ein guter Ansatz, um Dinge zu beweisen.
Eric Wang

12

Verwenden Sie gettimeofday()diese Option , um die Zeit in Sekunden und Mikrosekunden abzurufen. Das Kombinieren und Runden auf Millisekunden bleibt als Übung übrig.


7

C11 timespec_get

Es gibt bis zu Nanosekunden zurück, gerundet auf die Auflösung der Implementierung.

Es ist bereits in Ubuntu 15.10 implementiert. Die API sieht genauso aus wie die 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 */
};

Weitere Details finden Sie hier: https://stackoverflow.com/a/36095407/895245

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.