【发布时间】:2009-11-08 03:32:13
【问题描述】:
如何在 C++ 中获取系统时钟的当前时间(以毫秒为单位)?这是一个特定于 Windows 的应用程序。
【问题讨论】:
如何在 C++ 中获取系统时钟的当前时间(以毫秒为单位)?这是一个特定于 Windows 的应用程序。
【问题讨论】:
最简单(也是最直接)的方法是调用 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()。
【讨论】:
*reinterpret_cast<long long*>(&ft_now)
要获取以 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)。
【讨论】:
上面杰德回答的一个切入点的例子:
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); 用于固定长度的字符串
GetLocalTime() 工作方式类似,但提供本地时区时间
首先使用GetSystemTime;然后,如果您需要,您可以在前者为您填充的SYSTEMTIME 结构上调用SystemTimeToFileTime。 FILETIME 是一个 epoch 以来 100 纳秒间隔的 64 位计数,因此更适合算术; SYSTEMTIME 是一个包含所有预期字段(年、月、日、小时等,精确到毫秒)的结构。如果您想知道“自午夜以来经过了多少毫秒”,例如,减去两个 FILETIME 结构(一个为当前时间,一个通过将相同的 SYSTEMTIME 归零后将相应的字段进行转换获得)并除以十的适当幂可能是最简单的可用方法。
【讨论】:
根据您的应用程序的需要,有六个常用选项。这个Dr Dobbs Journal article 将为您提供选择最佳信息所需的所有信息(以及更多信息)。
在您的具体情况下,来自这篇文章:
GetSystemTime() 检索当前 系统时间并实例化一个 SYSTEMTIME结构,即 由若干独立的 字段包括年、月、日、 小时、分钟、秒和 毫秒。
【讨论】:
GetTickCount64,从 Windows Vista 开始,将其扩展到 64 位;前者限制为 32 个。
以下是我在 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
}
【讨论】:
虽然这不是问题所要问的,但值得考虑您为什么需要此信息。
如果您只想跟踪计算某项所需的时间或自上次用户交互以来过去的时间,请考虑使用正常运行时间(自启动以来的毫秒数),这更容易获得:GetTickCount() 或GetTickCount64()。这就是我想做的,但我首先进入了时代兔子洞,因为这就是你在 unix 下的做法。
【讨论】: