以毫秒为单位获取本地时间

时间:2017-03-14 17:24:28

标签: c datetime time

我需要以最快的方式来获取本地时间(因此考虑当前时区)至少以毫秒为单位的精度,如果可以在十分之一毫秒内获得更好的效果。

我想避免使用gettimeofday(),因为它现在是一个过时的功能。

所以,似乎我需要使用clock_gettime(CLOCK_REALTIME, ...)并将小时调整到当前时区,但是如何?最好的点在哪里?在使用clock_gettime存储时间戳之前,或者之前在当前时区的格里高利历中转换它?

编辑:我的原始样本加入了get_clock和localtime - 有更好的方法可以达到这个目标吗?

#include <time.h>
#include <stdio.h>

int main() {
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);

    struct tm* ptm;
    ptm = localtime(&(ts.tv_sec));

    // Tenths of milliseconds (4 decimal digits)
    int tenths_ms = ts.tv_nsec / (100000L);

    printf("%04d-%02d-%02d %02d:%02d:%02d.%04d\n", 
        1900 + ptm->tm_year, ptm->tm_mon + 1, ptm->tm_mday, 
        ptm->tm_hour, ptm->tm_min, ptm->tm_sec, tenths_ms);
}

2 个答案:

答案 0 :(得分:3)

我认为没有比clock_gettime()localtime()更好的方法了。但是,您需要正确舍入返回的纳秒,并考虑将时间舍入到下一秒的情况。要格式化时间,您可以使用strftime()而不是手动格式化tm结构:

#include <time.h>
#include <stdio.h>

int main(void) {
    struct timespec ts;
    long msec;
    int err = clock_gettime(CLOCK_REALTIME, &ts);
    if (err) {
        perror("clock_gettime");
        return 1;
    }

    // round nanoseconds to milliseconds
    if (ts.tv_nsec >= 999500000) {
        ts.tv_sec++;
        msec = 0;
    } else {
        msec = (ts.tv_nsec + 500000) / 1000000;
    }

    struct tm* ptm = localtime(&ts.tv_sec);
    if (ptm == NULL) {
        perror("localtime");
        return 1;
    }

    char time_str[sizeof("1900-01-01 23:59:59")];
    time_str[strftime(time_str, sizeof(time_str),
            "%Y-%m-%d %H:%M:%S", ptm)] = '\0';

    printf("%s.%03li\n", time_str, msec);
}

答案 1 :(得分:2)

是的,这可以使用clock_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_in_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

    printf("Current time: %"PRIdMAX".%03ld seconds since the Epoch\n",
           (intmax_t)s, ms);
}

如果您的目标是测量经过的时间,并且您的系统支持&#34;单调时钟&#34;选项,那么您应该考虑使用CLOCK_MONOTONIC而不是CLOCK_REALTIME

还有一点,记得在尝试编译代码时包含-lm标志。

要获取时区,请执行以下操作:

#define _GNU_SOURCE /* for tm_gmtoff and tm_zone */

#include <stdio.h>
#include <time.h>

int main(void)
{
  time_t t = time(NULL);
  struct tm lt = {0};

  localtime_r(&t, &lt);

  printf("Offset to GMT is %lds.\n", lt.tm_gmtoff);
  printf("The time zone is '%s'.\n", lt.tm_zone);

  return 0;
}

注意: time()返回的纪元以来的秒数就像在GMT(格林威治标准时间)中一样进行衡量。