【问题标题】:Getting the current time (in milliseconds) from the system clock in Windows?从 Windows 中的系统时钟获取当前时间(以毫秒为单位)?
【发布时间】:2009-11-08 03:32:13
【问题描述】:

如何在 C++ 中获取系统时钟的当前时间(以毫秒为单位)?这是一个特定于 Windows 的应用程序。

【问题讨论】:

    标签: c++ windows


    【解决方案1】:

    最简单(也是最直接)的方法是调用 GetSystemTimeAsFileTime(),它会返回一个 FILETIME,这是一个存储自 1601 年 1 月 1 日午夜以来 100 纳秒间隔的 64 位数的结构。

    至少在 Windows NT 3.1、3.51 和 4.01 中,GetSystemTimeAsFileTime() API 是能够检索当前时间的最快的用户模式 ​​API。它还提供了作为单个 API 调用的优势(与 GetSystemTime() -> SystemTimeToFileTime() 相比),在正常情况下不会失败。

    要将 FILETIME ft_now; 转换为名为 ll_now 的 64 位整数,请使用以下命令:
    ll_now = (LONGLONG)ft_now.dwLowDateTime + ((LONGLONG)(ft_now.dwHighDateTime) << 32LL);

    然后您可以除以每毫秒的 100 纳秒间隔数(其中 10,000 个),您有自 Win32 纪元以来的毫秒数。

    要转换为 Unix 纪元,请减去 116444736000000000LL 以达到 1970 年 1 月 1 日。

    您提到希望找到当天的毫秒数。因为 Win32 纪元从午夜开始,所以今天到目前为止经过的毫秒数可以通过取模运算从文件时间中计算出来。具体来说,因为有24 hours/day * 60 minutes/hour * 60 seconds/minute * 1000 milliseconds/second = 86,400,000 milliseconds/day,你可以使用系统时间的模数,单位为毫秒模数86400000LL

    对于不同的应用程序,可能不想使用模数。尤其是在计算经过的时间时,可能会因为半夜的折返而遇到困难。这些困难是可以解决的,我所知道的最好的例子是 Linux 内核中的 Linus Torvald 的线,它处理计数器回绕。

    请记住,系统时间作为 UTC 时间返回(在 GetSystemTimeAsFileTime() 和简单的 GetSystemTime() 的情况下)。如果您需要管理员配置的本地时间,则可以使用GetLocalTime()

    【讨论】:

    • +1 用于深入细分。请注意为 NT5.1+ 添加有关“至少在 Windows NT 3.1、3.51 和 4.01.. 最快的用户 API 时”的位。这是否意味着不再是这种情况?
    • 您也可以使用 FILETIME 的布局就像 long long 一样,然后直接转换它。看看 LARGE_INTEGER 是如何与 union 一起工作的,想法是一样的。 *reinterpret_cast<long long*>(&ft_now)
    • 互联网上的最佳答案
    • 应该是“要将文件时间(以 100 纳秒为单位)转换为 Unix 纪元,减去 116444736000000000LL 以达到 1970 年 1 月 1 日。”虽然
    • @MattPrice:你不能只转换,请参阅msdn.microsoft.com/en-gb/library/windows/desktop/…:“不要将指向 FILETIME 结构的指针转换为 ULARGE_INTEGER* 或 __int64* 值,因为它可能导致 64 位对齐错误-位窗口”
    【解决方案2】:

    要获取以 UTC 表示的时间,请在 Win32 API 中使用 GetSystemTime

    SYSTEMTIME st;
    GetSystemTime(&st);
    

    SYSTEMTIME 被记录为具有以下相关成员:

    WORD wYear;
    WORD wMonth;
    WORD wDayOfWeek;
    WORD wDay;
    WORD wHour;
    WORD wMinute;
    WORD wSecond;
    WORD wMilliseconds;
    

    正如 shf301 在下面有用地指出的那样,GetLocalTime(使用相同的原型)将产生一个更正为用户当前时区的时间。

    这里有几个不错的答案,具体取决于您所追求的。如果您正在寻找只是一天中的时间,我的答案是最好的方法——如果您需要可靠的算术日期,请考虑 Alex 的。 Windows 上有a lot of ways to skin the time cat,其中一些比其他更准确(目前还没有人提到QueryPerformanceCounter)。

    【讨论】:

    • 使用 GetLocalTime 获取用户将看到的时间和日期。 msdn.microsoft.com/en-us/library/ms724338%28VS.85%29.aspx
    • QueryPerformanceCounter... 我想你可能是在开玩笑,因为它有很多缺点,这会使其成为一个糟糕的选择。
    • 再一次,人们必须搜索正确的对应包含...pffff
    【解决方案3】:

    上面杰德回答的一个切入点的例子:

    const std::string currentDateTime() {
    
    SYSTEMTIME st, lt;
    
    GetSystemTime(&st);
    
    char currentTime[84] = "";
    
    sprintf(currentTime,"%d/%d/%d  %d:%d:%d %d",st.wDay,st.wMonth,st.wYear, st.wHour, st.wMinute, st.wSecond , st.wMilliseconds);
    
    return string(currentTime); }
    

    【讨论】:

    • sprintf(currentTime,"%.4d%.2d%.2d%.2d%.2d%.2d%.4d",st.wYear,st.wMonth,st.wDay, st.wHour, st.wMinute, st.wSecond , st.wMilliseconds); 用于固定长度的字符串
    • 获取UTC时间; GetLocalTime() 工作方式类似,但提供本地时区时间
    【解决方案4】:

    首先使用GetSystemTime;然后,如果您需要,您可以在前者为您填充的SYSTEMTIME 结构上调用SystemTimeToFileTimeFILETIME 是一个 epoch 以来 100 纳秒间隔的 64 位计数,因此更适合算术; SYSTEMTIME 是一个包含所有预期字段(年、月、日、小时等,精确到毫秒)的结构。如果您想知道“自午夜以来经过了多少毫秒”,例如,减去两个 FILETIME 结构(一个为当前时间,一个通过将相同的 SYSTEMTIME 归零后将相应的字段进行转换获得)并除以十的适当幂可能是最简单的可用方法。

    【讨论】:

    • 杰德,对,凭记忆写,我以为有一个下划线——现在编辑来修复,tx。
    【解决方案5】:

    根据您的应用程序的需要,有六个常用选项。这个Dr Dobbs Journal article 将为您提供选择最佳信息所需的所有信息(以及更多信息)。

    在您的具体情况下,来自这篇文章:

    GetSystemTime() 检索当前 系统时间并实例化一个 SYSTEMTIME结构,即 由若干独立的 字段包括年、月、日、 小时、分钟、秒和 毫秒。

    【讨论】:

    • 如果我错了,请纠正我,但 GetTickCount 没有给出自 oyur 应用程序启动以来经过的毫秒数?
    • 是的,没错,我添加了错误的报价。对不起。我现在已经修好了。
    • @Mark:系统启动后。 GetTickCount64,从 Windows Vista 开始,将其扩展到 64 位;前者限制为 32 个。
    • 其实,我相信是从系统启动开始的,但你说的还是对的,因为它是 weong 函数。
    【解决方案6】:

    以下是我在 Open Watcom C 项目中使用的一些适用于 Windows 的代码。它应该在 C++ 中工作 它使用 _dos_gettime 或 gettime 返回秒(不是毫秒)

      double seconds(void)
      {
      #ifdef __WATCOMC__
      struct dostime_t t;
      _dos_gettime(&t);
      return ((double)t.hour * 3600 + (double)t.minute * 60 + (double)t.second + (double)t.hsecond * 0.01);
      #else
      struct time t;
      gettime(&t);
      return ((double)t.ti_hour * 3600 + (double)t.ti_min * 60 + (double)t.ti_sec + (double)t.ti_hund * 0.01);
      #endif
    }
    

    【讨论】:

      【解决方案7】:

      虽然这不是问题所要问的,但值得考虑您为什么需要此信息。

      如果您只想跟踪计算某项所需的时间或自上次用户交互以来过去的时间,请考虑使用正常运行时间(自启动以来的毫秒数),这更容易获得:GetTickCount() 或GetTickCount64()。这就是我想做的,但我首先进入了时代兔子洞,因为这就是你在 unix 下的做法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-10-25
        • 2017-02-20
        • 2013-09-21
        • 1970-01-01
        • 2017-04-25
        • 1970-01-01
        相关资源
        最近更新 更多