【问题标题】:How to get milliseconds passed since unix epoch in C without multiplying seconds by 1000?如何在不将秒数乘以 1000 的情况下获得自 C 中的 unix 纪元以来经过的毫秒数?
【发布时间】:2020-07-27 10:36:01
【问题描述】:

我唯一知道的是time(NULL),但它返回自 1970 年以来的秒数。 如果 C 没有需要的函数,我可以使用 WinApi 函数。

我什至找到了GetLocalTime WinApi 函数,但它以结构体形式返回当前日期时间...

我不想将秒数乘以 1000 的原因是因为我将代码注入到某个程序中,而我的代码用于从两个源捕获某些事件,我需要知道它们的确切时间,因为如果这两个事件自 1970 年以来发生的秒数相同,但毫秒数不同,那么对我来说,它们似乎发生在同一时间,而且很难确定首先发生了什么(我稍后对事件进行排序......)

【问题讨论】:

  • 存在 RtlTimeToSecondsSince1970RtlTimeToSecondsSince1980 用于将时间(从 1601)转换为秒
  • @RbMm - 抱歉,但我不明白它如何帮助我获得自 1970 年以来的毫秒数。
  • 如果想要更准确的时间 - GetSystemTimeAsFileTime - 它实际上返回 8 字节整数。或者可以使用相对(启动)时间 - GetTickCount64 - 毫秒,但自上次启动后
  • 可以使用时钟,程序启动时从0开始。
  • @stark - 谢谢,但我更喜欢稍后可以变成实时的东西,这样我就可以在人类友好的时间内测量某些事件之间经过的时间。

标签: c winapi time unix-timestamp


【解决方案1】:

在 Unix 中,你有(可能你会得到一些这些 API 也可以在 Windows 中工作)gettimeofday(2),这是 BSD 的时间实现,它基于 struct timeval,这是一个 struct,它有两个字段,tv_sec(自纪元以来的时间,以秒为单位,由time(2) 给出)和tv_usec(以微秒为单位的时间,作为整数,在0999999 之间)

这足以满足您的要求,但是今天,通常使用 Posix 的调用clock_gettime(2),它允许您选择要获取的时间类型(挂钟时间、cpu 时间等)@ 987654330@ 使用了类似的struct timespec (这次它有tv_sectv_nsec ---纳秒--- 分辨率)

没有时钟可以保证获得纳秒级的分辨率(但有人这样做),但至少你可以达到微秒级别,这比你想要的要多)

为了能够以毫秒为单位,您只需将tv_sec 乘以1000,然后加上tv_usec(如果使用gettimeofday())值除以1000。或者,如果您更喜欢使用clock_gettime(),您将添加tv_sec 字段乘以1000,然后添加tv_nsec 字段除以1000000

如果你只需要比较哪个时间戳早于另一个,你可以只比较两个tv_sec字段,如果它们恰好相等,然后比较tv_usec字段。我所知道的每一个 unix(除了 SCO UNIX)都实现了gettimeofday() 到微秒的分辨率。

【讨论】:

    【解决方案2】:

    这是确定自 1970 年以来经过的毫秒数的 WinApi 方法。 我做到了,因为没有人用原生 C 方式提供答案(也许根本没有原生方式)......

        SYSTEMTIME unix_epoch;
        unix_epoch.wYear = 1970;
        unix_epoch.wMonth = 1;
        unix_epoch.wDay = 1;
        unix_epoch.wDayOfWeek = 4;
        unix_epoch.wHour = 0;
        unix_epoch.wMilliseconds = 0;
        unix_epoch.wMinute = 0;
        unix_epoch.wSecond = 0;
    
        FILETIME curr_time_as_filetime;
        GetSystemTimeAsFileTime(&curr_time_as_filetime);
    
        FILETIME unix_epoch_as_filetime;
        SystemTimeToFileTime(&unix_epoch, &unix_epoch_as_filetime);
    
        ULARGE_INTEGER curr_time_as_uint64;
        ULARGE_INTEGER unix_epoch_as_uint64;
    
        curr_time_as_uint64.HighPart = curr_time_as_filetime.dwHighDateTime;
        curr_time_as_uint64.LowPart = curr_time_as_filetime.dwLowDateTime;
    
        unix_epoch_as_uint64.HighPart = unix_epoch_as_filetime.dwHighDateTime;
        unix_epoch_as_uint64.LowPart = unix_epoch_as_filetime.dwLowDateTime;
    
        ULARGE_INTEGER milliseconds_since_1970;
        milliseconds_since_1970.QuadPart = (curr_time_as_uint64.QuadPart - unix_epoch_as_uint64.QuadPart) / 10000;
    

    【讨论】:

    • 很高兴您得到了解决方案,感谢您的分享,如果您将它们标记为答案,我将不胜感激,这将对其他社区有益。
    【解决方案3】:

    另一种方法是在程序开始时结合使用clock()和time(NULL)

    start_time = time(NULL)
    
    ....
    
    clock() + start_time * CLOCKS_PER_SEC
    

    这会给您一个更好的估计,并且可能对您的需求足够准确?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-04
      • 2014-09-02
      • 1970-01-01
      • 2018-07-22
      • 2021-06-11
      • 2020-02-11
      • 2019-08-03
      • 2010-11-07
      相关资源
      最近更新 更多