如何在C++中获取系统时钟的当前时间(以毫秒为单位)? 这是一个Windows特定的应用程序。
最简单(也是最直接)的方法是调用GetSystemTimeAsFileTime()
函数,它返回一个FILETIME
结构,该结构存储了自1601年1月1日午夜以来的100纳秒间隔的64位值。
至少在Windows NT 3.1、3.51和4.01时期,GetSystemTimeAsFileTime()
API是检索当前时间的最快用户模式API。与GetSystemTime() -> SystemTimeToFileTime()
相比,它还具有以下优点:是单个API调用,在正常情况下不会失败。
要将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小时/天 * 60分钟/小时 * 60秒/分钟 * 1000毫秒/秒 = 86,400,000毫秒/天
,您可以使用系统时间的毫秒数模 86400000LL
。
对于不同的应用程序,可能不希望使用模数。特别是如果要计算流逝的时间,可能会因午夜时分的回绕而遇到困难。这些困难是可以解决的,我所知道的最好的例子是Linus Torvald在Linux内核中处理计数器回绕的那行代码。
请注意,系统时间是以协调世界时(UTC)返回的(无论是在 GetSystemTimeAsFileTime()
还是简单的 GetSystemTime()
的情况下)。如果您需要管理员配置的本地时间,则可以使用 GetLocalTime()
。
要将时间表示为协调世界时(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上有很多处理时间的方式,其中一些比其他方法更准确(还没有人提到QueryPerformanceCounter
)。
Jed 上面的回答提供了一个简明扼要的例子:
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);
用于生成固定长度的字符串。 - AntonioGetLocalTime()
的工作方式类似,但会给出本地时区时间。 - M.M首先使用GetSystemTime函数,然后如果需要,可以在前者填充的SYSTEMTIME
结构上调用SystemTimeToFileTime函数。一个FILETIME
是一个64位计数器,表示自纪元以来的100纳秒间隔,因此更适合进行算术运算;一个SYSTEMTIME
是一个带有所有预期字段(年、月、日、小时等,直到毫秒)的结构体。例如,如果您想知道“从午夜以来经过了多少毫秒”,那么减去两个FILETIME
结构(一个是当前时间,另一个是将相同的SYSTEMTIME
转换后置零适当字段所得到的)并除以适当的10的幂可能是最简单的方法。
GetTickCount64
自 Windows Vista 开始扩展到 64 位;前者仅限于 32 位。 - Jed Smith虽然这不是问题所问的,但考虑一下为什么你需要这些信息是值得的。
如果你只是想跟踪计算所需的时间或自上次用户交互以来经过的时间,请考虑使用系统启动后的运行时间(毫秒):GetTickCount()或GetTickCount64()。这要简单得多。但我之前陷入了时代漩涡,因为在Unix下你需要这样做。
这里有一些在Windows中可用的代码,我在Open Watcom C项目中使用过。它应该在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
}
*reinterpret_cast<long long*>(&ft_now)
- Matt Price