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) 此外,从 FILETIME
到 DATE
的转换有些棘手,尤其是对于 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
。
我正在寻找一个低级别的 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) 此外,从 FILETIME
到 DATE
的转换有些棘手,尤其是对于 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
。