c - Windows API:在毫秒之间获取微秒
问题描述
GetSystemTimePreciseAsFileTime:以尽可能高的精度(<1us)检索当前系统日期和时间。
这给了我们一个文件时间
然后我们将它传递给: FileTimeToSystemTime 这给了我们一个 SYSTEMTIME
但是 SYSTEMTIME 只向我们展示了毫秒精度。
typedef struct _SYSTEMTIME {
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
那么我如何到达 (<1us) 部分?我希望能够打印类似的东西
printf( "milli:[%u] micro:[%u] nano:[%u]\n",
st.wMilliseconds, st.wMicro, st.Nano );
谢谢
我尝试了以下方法:
int main()
{
FILETIME ft = { 0 };
SYSTEMTIME st = { 0 };
UINT32 nsT = 0;
UINT32 us = 0;
UINT32 ns = 0;
for (int i = 0; i < 32; i++)
{
GetSystemTimePreciseAsFileTime(&ft);
FileTimeToSystemTime(&ft, &st);
nsT = (ft.dwLowDateTime & 0x0FFFFFFFFLL) | (ft.dwHighDateTime << 32LL);
us = (nsT % 10000LL) / 10LL;
ns = (nsT % 10LL);
wprintf(L"DT:[%u%02u%02u %02u:%02u:%02u:%03u:%03u:%u]\n",
st.wYear, st.wMonth, st.wDay,
st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, us, ns);
}
}
但是,它会产生不正常的时间
DT:[20190921 12:48:51:152:735:4]
DT:[20190921 12:48:51:164:561:4]
DT:[20190921 12:48:51:169:126:3]
DT:[20190921 12:48:51:172:595:0]
DT:[20190921 12:48:51:173:428:7]
DT:[20190921 12:48:51:173:415:9]
DT:[20190921 12:48:51:177:446:2]
DT:[20190921 12:48:51:181:309:8]
DT:[20190921 12:48:51:182:386:7]
DT:[20190921 12:48:51:184:650:6]
DT:[20190921 12:48:51:184:740:6]
DT:[20190921 12:48:51:189:271:8]
DT:[20190921 12:48:51:190:471:4]
DT:[20190921 12:48:51:194:746:6]
DT:[20190921 12:48:51:197:049:5]
DT:[20190921 12:48:51:198:793:4]
DT:[20190921 12:48:51:200:823:4]
DT:[20190921 12:48:51:200:529:1]
DT:[20190921 12:48:51:202:606:3]
DT:[20190921 12:48:51:210:913:4]
DT:[20190921 12:48:51:214:764:6]
DT:[20190921 12:48:51:214:815:4]
DT:[20190921 12:48:51:219:079:4]
DT:[20190921 12:48:51:222:580:2]
DT:[20190921 12:48:51:223:959:5]
DT:[20190921 12:48:51:224:933:8]
DT:[20190921 12:48:51:225:844:7]
DT:[20190921 12:48:51:226:810:7]
DT:[20190921 12:48:51:228:811:1]
DT:[20190921 12:48:51:230:139:1]
DT:[20190921 12:48:51:253:539:1]
DT:[20190921 12:48:51:253:653:9]
请注意以下对于给定的毫(173),我们有递减的微(428 到 415) 415 应该大于 428。
DT:[20190921 12:48:51:173:428:7]
DT:[20190921 12:48:51:173:415:9]
DT:[20190921 12:48:51:200:823:4]
DT:[20190921 12:48:51:200:529:1]
然后我将字符串冲刺到一个全局数组并在随后的循环中打印它以确保没有标准输出竞争条件,但它仍然在更精细的范围内失序:
DT:[20190921 13:05:01:228:534:1]
DT:[20190921 13:05:01:228:534:3]
DT:[20190921 13:05:01:228:534:3]
DT:[20190921 13:05:01:228:534:1]
DT:[20190921 13:05:01:228:534:3]
DT:[20190921 13:05:01:228:534:1]
DT:[20190921 13:05:01:228:534:3]
如果我添加一些代码来比较计算出的毫秒与 ST.wMilliseconds,我们会看到不一致:
ms:[140][0x8C] != st.wMilliseconds:[177][0xB1]
ms:[284][0x11C] != st.wMilliseconds:[184][0xB8]
ms:[337][0x151] != st.wMilliseconds:[236][0xEC]
感谢 Adrian,以下代码似乎可以完美运行:
int main()
{
WCHAR b[MAX][256] = { 0 };
FILETIME ft = { 0 };
SYSTEMTIME st = { 0 };
UINT64 ftLo = 0;
UINT64 ftHi = 0;
UINT64 myTime = 0;
UINT64 ms = 0;
UINT64 us = 0;
UINT64 ns = 0;
for (int i = 0; i < MAX; i++)
{
GetSystemTimePreciseAsFileTime(&ft);
FileTimeToSystemTime(&ft, &st);
ftLo = ft.dwLowDateTime;
ftHi = ft.dwHighDateTime;
myTime = ftLo | (ftHi << 32uLL);
ms = (myTime % 10000000uLL) / 10000uLL;
us = (myTime % 10000uLL) / 10uLL;
ns = (myTime % 10uLL);
if (ms != st.wMilliseconds)
wprintf(L"ms:[%llu][0x%llX] != st.wMilliseconds:[%u][0x%X]\n",
ms, ms, st.wMilliseconds, st.wMilliseconds);
wprintf(L"%u%02u%02u %02u:%02u:%02u:%03llu:%03llu:%llu\n",
st.wYear, st.wMonth, st.wDay,
st.wHour, st.wMinute, st.wSecond,
ms, us, ns);
}
return 0;
}
结果:
20190922 10:51:20:625:917:4
20190922 10:51:20:626:065:5
20190922 10:51:20:628:774:2
20190922 10:51:20:631:084:5
20190922 10:51:20:631:628:4
20190922 10:51:20:632:223:0
20190922 10:51:20:635:252:7
20190922 10:51:20:637:841:8
20190922 10:51:20:641:058:9
20190922 10:51:20:649:869:0
20190922 10:51:20:651:283:0
20190922 10:51:20:652:677:9
20190922 10:51:20:652:749:7
20190922 10:51:20:652:808:6
20190922 10:51:20:654:621:0
20190922 10:51:20:656:662:3
20190922 10:51:20:659:048:9
20190922 10:51:20:660:926:0
20190922 10:51:20:664:202:1
20190922 10:51:20:666:506:9
20190922 10:51:20:666:592:6
20190922 10:51:20:666:712:8
20190922 10:51:20:670:800:7
20190922 10:51:20:680:442:7
20190922 10:51:20:680:522:0
20190922 10:51:20:681:207:1
20190922 10:51:20:682:988:3
20190922 10:51:20:684:476:8
20190922 10:51:20:685:727:1
20190922 10:51:20:685:777:0
20190922 10:51:20:686:526:3
20190922 10:51:20:686:919:9
解决方案
SYSTEMTIME
正如您所注意到的,您不能通过使用结构来做到这一点。您需要从返回的FILETIME
结构中提取数据并将其处理为 64 位整数:
FILETIME fTime;
GetSystemTimePreciseAsFileTime(&fTime);
uint64_t ftLo = uint64_t(fTime.dwLowDateTime);
uint64_t ftHi = uint64_t(fTime.dwHighDateTime);
uint64_t myTime = ftLo | (ftHi << 32uLL);
然后,该myTime
变量将保存自 01-JAN-1601 以来 100 纳秒间隔的数量。
要从这个 'epoch' 值到 'missing' us 和 ns 字段,SYSTEMTIME
您可以简单地使用下面的代码。您还应该获得自己的毫秒值,以防转换为SYSTEMTIME
“四舍五入”该dwMilliseconds
值(不知道是否发生这种情况):
uint64_t millis = (myTime % 10000000uLL) / 10000uLL;
uint64_t micros = (myTime % 10000uLL) / 10uLL;
uint64_t nanos = (myTime % 10uLL) * 100uLL; // Will have a resolution of only 100ns
(这是假设自 1601 年 1 月 1 日以来的所有日子都有整数毫秒,我认为这是一个合理的假设!)
注意:另一种选择是将结构复制(或强制转换)FILETIME
到 aULARGE_INTEGER
然后将该QuadPart
联合的元素分配给myTime
. 这也将起作用,但在标准 C++ 中,写入联合的一部分然后从另一部分读取是正式的未定义行为。
推荐阅读
- rest - 在具有上下文路径的 Spring Boot 应用程序中使用 API 网关时,HATEOAS 路径无效
- css - Angular2禁用CSS捆绑
- docker - 如何识别哪个容器拥有哪个覆盖目录?
- ios - 在登录屏幕上实现了 AWS cognito 身份验证,API 在 UWP 和 android 平台上被击中,但在 IOS 上没有
- java - Java - 无法访问特定的 Windows 注册表文件夹/值
- angular - Angular 6 - Sidenav 与 ngx-translate 重叠内容
- angular5 - 在 Angular 5 中,通过 http 发送数据
- png - zlib 标头如何存储在 png 中的多个 IDAT 块中
- git - 文件在合并期间被替换
- node.js - Node js模块返回未定义