【问题标题】:How can I create a SYSTEMTIME struct from ULONGLONG milliseconds?如何从 ULONGLONG 毫秒创建 SYSTEMTIME 结构?
【发布时间】:2012-06-20 15:15:01
【问题描述】:

我想使用::GetSystemTime()::GetTickCount64 来计算它,而不是使用WMI 来获取上次启动时间。但是一旦达到毫秒,我不知道如何返回 FILETIME 对象。

我试过了:

static ULONGLONG FileTimeToMillis(const FILETIME &ft)
{
    ULARGE_INTEGER uli;
    uli.LowPart = ft.dwLowDateTime; // could use memcpy here!
    uli.HighPart = ft.dwHighDateTime;

    return uli.QuadPart/10000;
}

static void MillisToSystemTime(ULONGLONG millis, SYSTEMTIME *st)
{
   UINT64 t = static_cast<UINT64>(-10000) * static_cast<UINT64>(millis);

   FILETIME ft;
   ft.dwLowDateTime = static_cast<DWORD(t & 0xFFFFFFFF);
   ft.dwHighDateTime = static_cast<DWORD>(t >> 32);

   ::FileTimeToSystemTime(&ft, st);
}

void main()
{
    SYSTEMTIME st, lt, st2, lt2;

    ::GetSystemTime(&st);
    ::GetLocalTime(&lt);

    cout << "The system time is: " << st.wHour << ":" << st.wMinute << ":" << st.wSecond << endl;
    cout << "The local time is: "  << lt.wHour << ":" << lt.wMinute << ":" << lt.wSecond << endl;

    FILETIME sft, lft;
    ::SystemTimeToFileTime(&st, &sft);
    ::SystemTimeToFileTime(&lt, &lft);  

    cout << "The system time in millis is: " << FileTimeToMillis(sft) << endl;
    cout << "The local time in millis is: "  << FileTimeToMillis(lft) << endl;

    MillisToSystemTime(FileTimeToMillis(sft), &st2);
    MillisToSystemTime(FileTimeToMillis(sft), &lt2);

    cout << "The system time (post conversion) is: " << st2.wHour << ":" << st2.wMinute << ":" << st2.wSecond << endl;
    cout << "The local time (post conversion) is: "  << lt2.wHour << ":" << lt2.wMinute << ":" << lt2.wSecond << endl;
}

但我当然没有得到预期的结果。相反,我得到:

The system time is: 15:5:2
The local time is: 10:5:2
The system time in millis is: 12984678302935
The local time in millis is: 12984660302935
The system time (post conversion) is: 52428:52428:52428
The local time (post conversion) is: 52428:52428:52428

有什么想法吗?请不要告诉我使用 Boost 或因为它对我不可用。

【问题讨论】:

  • 你想要的伪代码FileTimeToSystemTime(GetSystemTimeAsFileTime - (10000 * GetTickCount64))
  • @arx MSDN 建议不要对 FILETIME 结构本身执行算术运算。

标签: c++ windows visual-c++ datetime


【解决方案1】:

系统时间(转换后)为:52428:52428:52428

当你得到奇怪的值时,总是先转换为十六进制。 52428 == 0xcccc。这是调试构建生成的代码用于初始化变量的值。所以你正在查看未初始化的内存。

下一个防御策略是从不忽略Windows api函数的返回值。使用 VERIFY() 宏,如 MFC 中可用的宏。然后您会很容易看到 FileTimeToSystemTime() 失败。

错误是-10000。

【讨论】:

  • 哦!将负数粘贴到无符号中是菜鸟错误!我使用的是通过 Google 找到的代码,他们使用的是 __int64,我没有将 -10000 更改为 10000。很好!
【解决方案2】:

原来我做错了算术。一旦我阅读了ULARGE_INTEGERFILETIME,我发现我可以直接使用ULARGE_INTEGERQuadPart,然后正确地拉出高低部分,同时避免位移和铸造混乱。

static UINT64 FileTimeToMillis(const FILETIME &ft)
{
    ULARGE_INTEGER uli;
    uli.LowPart = ft.dwLowDateTime; // could use memcpy here!
    uli.HighPart = ft.dwHighDateTime;

    return static_cast<UINT64>(uli.QuadPart/10000);
}

static void MillisToSystemTime(UINT64 millis, SYSTEMTIME *st)
{
    UINT64 multiplier = 10000;
    UINT64 t = multiplier * millis;

    ULARGE_INTEGER li;
    li.QuadPart = t;
    // NOTE, DON'T have to do this any longer because we're putting
    // in the 64bit UINT directly
    //li.LowPart = static_cast<DWORD>(t & 0xFFFFFFFF);
    //li.HighPart = static_cast<DWORD>(t >> 32);

    FILETIME ft;
    ft.dwLowDateTime = li.LowPart;
    ft.dwHighDateTime = li.HighPart;

    ::FileTimeToSystemTime(&ft, st);
}

Key 正在从MSDN 读取以下内容:

不建议您从 FILETIME 结构获取相对时间。相反,您应该复制 文件时间的低位和高位部分到 ULARGE_INTEGER 结构,对 QuadPart 成员执行 64 位运算,然后复制 将 LowPart 和 HighPart 成员放入 FILETIME 结构中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-08
    • 1970-01-01
    • 2013-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    • 2017-11-06
    相关资源
    最近更新 更多