LinuxのCから現在の時刻をミリ秒単位で取得するにはどうすればよいですか?


86

Linuxの現在時刻をミリ秒単位で取得するにはどうすればよいですか?

回答:


100

これは、POSIXclock_gettime関数を使用して実現できます。

POSIXの現在のバージョンでは、廃止gettimeofdayマークされています。これは、仕様の将来のバージョンから削除される可能性があることを意味します。アプリケーション作成者は、のclock_gettime代わりに関数を使用することをお勧めしますgettimeofday

使用方法の例を次に示します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);
}

経過時間を測定することが目標であり、システムが「単調クロック」オプションをサポートしている場合は、のCLOCK_MONOTONIC代わりにを使用することを検討する必要がありCLOCK_REALTIMEます。


7
正解は+1ですが、答えの単位が間違っています。OPはミリ秒単位の時間必要としませんが、ミリ秒単位の時間を必要とます。
段落記号2013年

5
良い解決策ですが、コマンドの-lmを忘れないでくださいgcc
David Guyon 2014年

2
roundのマンページによると、結果を整数(またはlong)に割り当てるときにlroundを使用する必要があります
2016年

2
1000ミリ秒に切り上げられないように、round()の代わりにfloor()を使用する必要があります。そうしないとs、これが発生したときにインクリメントする必要があります。おそらくまれなイベントですが、余分な数字が問題を引き起こす可能性があります。
マイク

1
@マイクニースキャッチ。2000分の1で、それはそれほど珍しいことではないので、間違いなく修正する必要があります。むしろ使用の床よりも、私はもう少し精度を維持してラウンドに継続することを好むが、それは1000に切り上げる場合は、2番目のカウンタをインクリメントと思う
ダン成形

58

あなたはこのようなことをしなければなりません:

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

以下は、現在のタイムスタンプをミリ秒単位で取得するutil関数です。

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

タイムゾーンについて

タイムゾーンを指定するためのgettimeofday()サポート。タイムゾーンを無視するNULLを使用しますが、必要に応じてタイムゾーンを指定できます。


@ Update-タイムゾーン

long時間の表現はタイムゾーン自体とは関係がないか、影響を受けtzないため、gettimeofday()のparamを設定する必要はありません。違いはありません。

また、のmanページによるとgettimeofday()timezone構造体の使用は廃止tzされているため、引数は通常NULLとして指定する必要があります。詳細については、manページを確認してください。


1
> gettimeofday()サポートによるタイムゾーンの指定。NULLを使用します。これはタイムゾーンを無視しますが、必要に応じてタイムゾーンを指定できます。あなたは間違っている。タイムゾーンは、localtime()の呼び出しによってのみ導入する必要があります。
Vitaly.v.ch 2017年

@ vitaly.v.ch私が渡し、テストをしたtzのPARAMgettimeofday()として&(struct timezone tz = {480, 0})警告を取得することはありませんが、して以来、それは、理にかなって結果に影響しません。long時間の表現はに関連するか、行われませんタイムゾーン自体でね?
Eric Wang

テストを行う理由はありませんでした。Linuxカーネルには、タイムゾーンに関する適切な情報がなく、同時にそれを提供する方法もありません。これが、tz引数が非常に特殊な方法で処理される理由です。長い表現は重要ではありません。
Vitaly.v.ch 2017年

@ vitaly.v.ch特定の時点で、長い表現はタイムゾーンによって変化しません。それが重要である理由NULLです。そのため、通常は通過する妥当な値のみです。そして、私はテストが物事を証明するための良いアプローチであると常に信じています。
Eric Wang



0

Dan MouldingのPOSIX回答から派生した、これは機能するはずです:

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

また、David Guyonが指摘したように:-lmでコンパイルする

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.