【问题标题】:WinAPI to format FILETIME as a localized string with date and/or timeWinAPI 将 FILETIME 格式化为带有日期和/或时间的本地化字符串
【发布时间】:2018-03-14 18:54:38
【问题描述】:

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

通过反转 MFC 的 COleDateTime,我能够找到“有点”有效的 VarBstrFromDate 函数。所以我试图看看是否有另一个更可靠的 API 可以实现这一点。

我可以看到VarBstrFromDate 有两个问题:

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

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

它返回"12/31/1899",不带时间部分。

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

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

它返回"12:00:00 PM",不带日期部分。

2) 此外,从FILETIMEDATE 的转换有些棘手,尤其是对于 1899 年 12 月 30 日之前的日期。同样,通过反转 MFC,我能够找到 @ 987654322@ 可以通过 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;
}

你知道他们为什么要检查 SystemTimeToVariantTime 返回的结果,然后以如此尴尬的方式将其传递给 VariantTimeToSystemTime 吗?这是否意味着SystemTimeToVariantTime 可能返回不正确的结果,还是什么?

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

【问题讨论】:

  • 如果您使用的是旧版 C++03 编译器,请使用标准库 chrono 或 boost chrono。见:stackoverflow.com/questions/16692400/…
  • 自动化日期必须与 Lotus 123 错误兼容。怪物只是在那里帮助你不落入陷阱。不要使用 1900 年 3 月 1 日之前的日期。

标签: c++ winapi localization mfc filetime


【解决方案1】:

您可以使用 kernel32 中的经典时间函数:首先调用FileTimeToSystemTime,然后调用GetTimeFormatGetDateFormatSHFormatDateTime 是这些函数的封装。

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

【讨论】:

  • 哇,很好的发现。我不知何故错过了SHFormatDateTime API。虽然我似乎无法弄清楚本地化将如何使用它。 SetThreadUILanguageSetThreadPreferredUILanguages 似乎都对它没有任何影响? StrFromTimeInterval 也一样
  • 不,同样的事情。虽然我刚刚意识到我可以简单地做GetDateFormat(lcid, DATE_SHORTDATE, &amp;st, NULL, bufferDate, _countof(bufferDate)); 然后GetTimeFormat(lcid, 0, &amp;st, NULL, bufferTime, _countof(bufferTime)); 然后将它连接为date + space + time,它会做我需要的。不过我很好奇(我似乎在任何地方都找不到)所以也许你知道——几乎所有文化都有date,然后是space,然后是time
  • 该实现已在某个时间点移至propsys.dll,短日期为:日期+“”+时间。长日期是:日期 + ", " + 时间,但逗号字符串来自 LoadString,并且可能在不同的语言环境中不是 ", ",因为涉及 MUI。
猜你喜欢
  • 2012-09-07
  • 1970-01-01
  • 2020-08-07
  • 2017-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
相关资源
最近更新 更多