如何在Metro(C++/CX)应用程序中解析日期?

17

我有一个处理文件数据的C++/CX应用程序,其中有一个表示用于保存日期的文化的字符串,以及一些日期。我需要将它们从字符串转换为Platform::DateTime。我听说Windows::Globalization::DateTimeFormatting是要使用的类,但我不知道如何用它来实现转换。有人有示例吗?


我对winrt不是很熟悉,但看起来DateTimeFormatter类是反过来的,将DateTime-> string。你需要解析它。我认为DateTimeOffset::Parse()DateTimeOffset::ParseExact()是你要找的(或者是winrt/C++的等效物)。 - Jeff Mercado
仅从名称来看,我并不反对,但是DateTimeFormatting类的文档(完整的)中说:“格式化和解析日期和时间。”Platform::DateTime只是一个没有方法的结构体。 - Kate Gregory
1
文档中的措辞误导/错误并不让我感到惊讶。该类中只有一个方法(Format()),没有明确的解析方法/构造函数。它可能只是用于格式化。至少有一个案例中,文档根本没有意义。 - Jeff Mercado
3个回答

14

C++/CX对WinRT的投影与托管投影(C#/VB)在许多方面都有所不同,其中最主要的一个区别就是基本类型(如PointSizeStringDateTime)的投影。

托管投影将这些类型作为.NET类型进行投影(具有BCL的所有底层支持),而C++投影通常只是最小化地将这些类型投影出来以实现相互操作,期望用户依靠C++库的支持来获得更高级的功能。

因此,在.NET中,有符号的32位整数变成了System.Int32(带有其相关的.Parse功能),而在C++中,您得到了一个普通的C++ int,需要使用CRT功能(_wtoi)来完成类似的任务。这种差异通常会导致不同投影之间存在“功能差距”,其中一种更痛苦的是处理DateTime结构体(在BCL中具有非常丰富的支持)。

我找到的解决方案是从COleDateTime类(包含ATLComTime.h)开始,然后通过COleDateTime->SYSTEMTIME->FILETIME->_ULARGE_INTEGER->Windows::Foundation::DateTime的方式进行转换。虽然这是一种相当复杂的方法,但COleDateTime类具有您需要的语言特定解析功能。

LCID lcid = LocaleNameToLCID(L"es-es", LOCALE_ALLOW_NEUTRAL_NAMES); //parse language tag to get locale ID

COleDateTime dt;
dt.ParseDateTime(L"12 enero, 2012 10:00:01", 0, lcid); //parse date string based on language

//get system time struct
SYSTEMTIME st;
dt.GetAsSystemTime(st);

//COleDateTime is in local timezone, DateTime is in UTC, so we need to convert
SYSTEMTIME st_utc;
TzSpecificLocalTimeToSystemTime(nullptr, &st, &st_utc);

//get filetime struct to get a time format compatible with DateTime
FILETIME ft;
SystemTimeToFileTime(&st_utc, &ft);

//use _ULARGE_INTEGER to get a uint64 to set the DateTime struct to
_ULARGE_INTEGER ulint = {ft.dwLowDateTime, ft.dwHighDateTime};

Windows::Foundation::DateTime wfdt;
wfdt.UniversalTime = ulint.QuadPart;

我询问了关于DateTimeFormatter类的问题,文档是错误的;它不支持解析并且也不打算支持(仅支持格式化)。


1
我不得不稍微修改这段代码,因为与夏令时和从 UTC 四舍五入的问题有关,但只要你考虑到了这一点,就可以使用这个解决方案——而且这确实不是我能想到的。谢谢! - Kate Gregory

4
您是否可以尝试使用std::get_time来解决问题呢?页面底部的示例表明,您可以使用区域设置将日期字符串解析为tm结构。我想您可以将tm结构转换为正确的WinRT DateTime。请注意保留HTML标记。

1
我相信这也可以工作,但与COleDateTime::ParseDateTime相比似乎不太灵活。但是当您接收格式良好的日期时,我认为这将是一个更简单的解决方案。 - Andy Rich

0
我使用以下代码: auto cal = ref new Windows::Globalization::Calendar(); cal->AddSeconds(additionalSeconds); return cal->GetDateTime(); 使用Windows::Globalization::Calendar,您可以获得所有所需的时间函数:https://msdn.microsoft.com/library/windows/apps/br206724

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接