WinAPI 将 FILETIME 格式化为具有日期 and/or 时间的本地化字符串

WinAPI to format FILETIME as a localized string with date and/or time

我正在寻找一个低级别的 WinAPI 来将日期时间从 FILETIME 格式化为本地化的字符串,同时输出日期、时间或日期和时间。

通过反转 MFC 的 COleDateTime,我能够找到 "kinda" 有效的 VarBstrFromDate 函数。所以我想看看是否有另一个更可靠的 API 可以做到这一点。

我发现 VarBstrFromDate 有两个问题:

1) 它不能可靠地报告日期或时间部分。例如,如果我这样称呼 midnight Dec. 31, 1899:

BSTR bstr = NULL;
HRESULT hr = ::VarBstrFromDate(1.0, LANG_USER_DEFAULT, VAR_FOURDIGITYEARS, &bstr);
::SysFreeString(bstr);

it returns "12/31/1899" 没有时间部分。

或者,如果我调用它,比如说,noon Dec. 30, 1899:

BSTR bstr = NULL;
HRESULT hr = ::VarBstrFromDate(0.5, LANG_USER_DEFAULT, VAR_FOURDIGITYEARS, &bstr);
::SysFreeString(bstr);

it returns "12:00:00 PM" 没有日期部分。

2) 此外,从 FILETIMEDATE 的转换有些棘手,尤其是对于 1899 年 12 月 30 日之前的日期。同样,通过逆向 MFC 我发现 SystemTimeToVariantTime 可以通过 SYSTEMTIME 结构来完成。有点倒退,但没关系。但后来我在 atlcore.h:

看到了这个怪物
inline BOOL AtlConvertSystemTimeToVariantTime(
    _In_ const SYSTEMTIME& systimeSrc,
    _Out_ double* pVarDtTm)
{
    ATLENSURE(pVarDtTm!=NULL);
    //Convert using ::SystemTimeToVariantTime and store the result in pVarDtTm then
    //convert variant time back to system time and compare to original system time.
    BOOL ok = ::SystemTimeToVariantTime(const_cast<SYSTEMTIME*>(&systimeSrc), pVarDtTm);
    SYSTEMTIME sysTime;
    ::ZeroMemory(&sysTime, sizeof(SYSTEMTIME));

    ok = ok && ::VariantTimeToSystemTime(*pVarDtTm, &sysTime);
    ok = ok && (systimeSrc.wYear == sysTime.wYear &&
            systimeSrc.wMonth == sysTime.wMonth &&
            systimeSrc.wDay == sysTime.wDay &&
            systimeSrc.wHour == sysTime.wHour &&
            systimeSrc.wMinute == sysTime.wMinute &&
            systimeSrc.wSecond == sysTime.wSecond);

    return ok;
}

您知道他们为什么要检查 return 由 SystemTimeToVariantTime 编辑的结果,然后以如此笨拙的方式将其传递给 VariantTimeToSystemTime 吗?这是否意味着 SystemTimeToVariantTime 可能 return 一个不正确的结果,或者什么?

无论如何,我想找另一个 API 不依赖于转换为浮点数 DATE

您可以使用 kernel32 中的经典时间函数:第一次调用 FileTimeToSystemTime and then call GetTimeFormat and GetDateFormat. SHFormatDateTime 是对这些函数的包装。

如果您需要持续时间的友好文本,shell 也有 StrFromTimeInterval