做时间戳的最佳方法是什么?

时间:2010-10-06 21:12:27

标签: c++ c time timestamp

好的,所以我想给你留点时间......我也可以这样做......但是在研究这个问题时,我想在做时间戳时最好的做法是什么?我在这种情况下的假设是使用C / C ++代码。我知道内部时钟有各种各样的分辨率等...但我对需要注意的事情感兴趣......这些答案对我可能不知道的事情有帮助。

好时间格式应该是什么样的? 您对Posix时间函数有何看法? 我想要一个纹理表示和内部表示? 最简单的方法是什么,这样可以轻松添加和减少时间?

5 个答案:

答案 0 :(得分:1)

在我看来,最好的方法是将基于纪元的表示保持为整数。最标准的是自1970年以来保持秒数。由于你想保持更高的分辨率,你可以扩展它并保持自1970年以来的微秒或毫秒。为了实现这一点,你需要使用至少64位整数(很长)。

posix gettimeofday()将为您提供高达微秒的分辨率,您可以将其与gmtime_r()函数结合使用以获得剩余的标记。对于Windows,我使用GetSystemTime()函数来获得分辨率高达毫秒的时间(实际上,我认为它是几十毫秒)。以下代码片段显示了这种方法(而不是我的时间单位是纳秒)。

  LgrDate rtn;
#ifdef _WIN32
  SYSTEMTIME sys;
  GetSystemTime(&sys);
  rtn.setDate(
     sys.wYear,
     sys.wMonth,
     sys.wDay);
  rtn.setTime(
     sys.wHour,
     sys.wMinute,
     sys.wSecond,
     sys.wMilliseconds*uint4(nsecPerMSec));
#else
  struct timeval time_of_day;
  struct tm broken_down;
  gettimeofday(&time_of_day,0);
  gmtime_r(
     &time_of_day.tv_sec,
     &broken_down);
  rtn.setDate(
     broken_down.tm_year + 1900,
     broken_down.tm_mon + 1,
     broken_down.tm_mday);
  rtn.setTime(
     broken_down.tm_hour,
     broken_down.tm_min,
     broken_down.tm_sec,
     time_of_day.tv_usec * nsecPerUSec);
#endif
  return rtn;

答案 1 :(得分:1)

要注意的事项?

通过NTP保持系统同步,这样就可以关联来自多个系统的日志。

如果您在内部存储时间戳,请将其存储为自UTC 1970年以来的秒数(可能包含mS或uS的小数)。这是非常标准的,在表示上你可以轻松地在任何时区将它转换为本地时间(如果你必须处理几个时区,这很有用)。此外,UTC没有夏令时,这避免了一些歧义(但不是其他人,仍有闰秒)。

如果您只想要日志文件的时间戳,可以将已经转换为某种人类可读格式的时间戳写入。在处理多个时区和避免夏令时模糊时,UTC仍然有其优势。

如果您需要更精确的内容,请考虑DJB的libtai,或者根据您的需要,使用CLOCK_MONOTONIC的POSIX clock_gettime()就足够了。

答案 2 :(得分:0)

请参阅gettimeofday的手册页

int gettimeofday(struct timeval *tp, void *);

long    tv_sec;    /* seconds since Jan. 1, 1970 */
     long    tv_usec;   /* and microseconds */

你可以将时间存储为struct timeval,还有用于添加的宏和&使用struct timeval值减法。您可以使用ctime(tv_sec)来获取ascii字符串。 如果你需要用usec创建一个字符串,请尝试这样的事情:

char *now(void)  /* time to /1000ths of a second */
{
    struct timeval tv={0,0};
    int i=gettimeofday(&tv, NULL);
    static char retval[64]={0x0};
    char tmp[16]={0x0};

    if(i<0)
        return NULL;
    sprintf(tmp, "%.3f", (double)tv.tv_usec / (double)1000000);
    strftime(retval, sizeof(retval),
             "%Y-%m-%d %H:%M:%S.",
             localtime(&tv.tv_sec));
    strcat(retval, &tmp[2]);

    return retval;
}

答案 3 :(得分:0)

没有便携式时间功能可靠地为您提供超过10毫秒的分辨率。其他响应者引用的函数gettimeofday()具有依赖于系统的分辨率,我相信通常为1或10 ms。此外,即使90%的非便携时间功能也会涉及到0环(数千个时钟信号),这意味着只需执行功能调用就可以使用1-2美元!

唯一适用于所有英特尔平台的方法,为您提供亚微秒分辨率,每次调用的成本低于10纳秒是汇编指令'rdtsc'(或内在的__rdtsc())。

答案 4 :(得分:0)

新的C++0x,在其各种改进中,最终带来了一个成熟的time库。

它主要是为thread支持(表达各种try_lock和al)的持续时间/时间限制而开发的,但它是一颗真正闪亮的珍珠。您可以找到原始提案here和Bjarne关于它的条目here

显然,如果您希望将此时间与外部源进行比较,它依赖于您的系统正确同步:使用NTP。我还建议使用UTC时间,在没有夏令时的情况下,更容易在常见的时区中表达所有时间。

至于表现本身,我会选择人类可读的。对于一台机器来说,解析这两种格式都很容易,但对于一个人来说却不是这样,而且谁正在调查?

[1] 2010/10/07 06:54:36.123456
[2] 2010 OCT 07 06:54:36.123456
[3] 86456156456.123456          // garbage I made up ;)

第二种格式允许从一天中消除歧义,而不会产生任何混淆。这是我最喜欢的,但我经常看到第一个。