Как получить текущее время в миллисекундах с C в 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 за POSIX-правильность, но в вашем ответе неправильные единицы измерения. ОП не хочет время с миллисекундах, но время в миллисекундах.
pilcrow
5
Хорошее решение, но не забывайте -lm в своей gccкоманде.
Дэвид Гайон
2
согласно man-странице для round, вы хотите использовать lround при присвоении результата целому (или длинному)
hildred
2
Вам нужно использовать floor () вместо round (), чтобы он никогда не округлялся до 1000 мс. В противном случае вам нужно будет увеличить, sкогда это произойдет. Наверное, редкое событие, но лишняя цифра может вызвать проблемы.
Майк
1
@ Майк Хороший улов. Один из двух тысяч, это даже не так уж и редко, поэтому обязательно нужно исправить. Вместо того, чтобы использовать пол, я бы предпочел сохранить немного больше точности и продолжить округление, но увеличивать второй счетчик, если он округляется до 1000.
Дэн Молдинг
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часовому поясу и не зависит от него , установка param для gettimeofday () не требуется, поскольку это не будет иметь никакого значения.

И, по словам мужчины странице gettimeofday(), использование timezoneструктуры является устаревшим, поэтому tzаргумент должен нормально быть указан как NULL, для информации , пожалуйста , смотрите страницы.

Эрик Ван
источник
1
> gettimeofday () поддерживает указание часового пояса, я использую NULL, который игнорирует часовой пояс, но вы можете указать часовой пояс, если необходимо. Вы неправы. Часовой пояс следует вводить исключительно через вызов localtime ().
vitaly.v.ch 04
@ vitaly.v.ch Я провел тест, передав tzпараметр gettimeofday()as &(struct timezone tz = {480, 0})не будет получать никаких предупреждений, и это не повлияет на результат, что имеет смысл, поскольку longпредставление времени не имеет отношения к по самому часовому поясу, верно?
Эрик Ван
Не было причин делать никаких тестов. Ядро Linux не имеет надлежащей информации о часовых поясах, и в то же время не имеет возможности предоставить ее. Это причина того, что аргумент tz обрабатывается очень специфическим образом. длинное представление значения не имеет.
vitaly.v.ch 05
@ vitaly.v.ch В определенный момент времени длинное представление не меняется в зависимости от часового пояса, поэтому оно имеет значение, и обычно это NULLявляется разумным значением для передачи. И я считаю, что тестирование - всегда хороший способ доказать что-то.
Эрик Ван
13

Используйте, gettimeofday()чтобы получить время в секундах и микросекундах. Объединение и округление до миллисекунд оставлено как упражнение.

Donal Fellows
источник
7

C11 timespec_get

Он возвращается с точностью до наносекунд, округленной до разрешения реализации.

Это уже реализовано в Ubuntu 15.10. API выглядит так же, как 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 */
};

Подробнее здесь: https://stackoverflow.com/a/36095407/895245

Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
источник
0

Полученный из ответа Дэна Молдинга 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);
}

Также, как указал Дэвид Гайон: скомпилировать с -lm

Ирка Юстра
источник