How do I parse a date in a Metro (C++/CX) app?
Asked Answered
D

3

17

I have a C++/CX app that is processing some data from a file. It has a string in there representing the culture that was used to save the dates, and it has some dates. I need to convert them from strings to Platform::DateTime. I have heard that Windows::Globalization::DateTimeFormatting is the class to use, but I don't see how to use it for that. Does anyone have an example?

Daisey answered 23/7, 2012 at 15:50 Comment(3)
I'm not too familiar with winrt but it looks like the DateTimeFormatter class goes the other way taking DateTime -> string. You would need to parse it. I believe DateTimeOffset::Parse() or DateTimeOffset::ParseExact() is what you're looking for (or whatever the winrt/C++ equivalent is).Oppression
Based on the names alone, I don't disagree, but the doc for the DateTimeFormatting class says (in its entirety) "Formats and parses dates and times." Platform::DateTime is just a struct with no methods.Daisey
It wouldn't be a surprise to me that the wording in the documentation would be misleading/wrong. There's only one method in that class (Format()) and there's no clear method/constructor that does the parsing. It's probably just meant for the formatting. There's at least one case where the documentation made little sense at all.Oppression
W
14

The C++/CX projection of WinRT differs from the Managed (C#/VB) projection in a number of ways, and one of the most major is in the projection of fundamental types (such as Point, Size, String, and DateTime).

The managed projection projects these types as .NET types (with all the underlying support of the BCL) while the C++ projection generally minimally projects these types for interop, expecting the user to rely on C++ library support for more advanced functionality.

So, where in .NET a signed 32-bit integer becomes a System.Int32 (with its relevant .Parse functionality) in C++ you get a regular C++ int and are expected to use CRT functionality (_wtoi) to accomplish a similar task. This difference often results in a 'feature gap' between the different projections, one of the more painful of which is in dealing with the DateTime structure (which has very rich support in the BCL).

The solution I've managed to get was to start with the COleDateTime class (found by including ATLComTime.h) and going COleDateTime->SYSTEMTIME->FILETIME->_ULARGE_INTEGER->Windows::Foundation::DateTime. It's serious gymnastics, but the COleDateTime class has the language-specific parsing capability that you require.

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;

I've asked around about the DateTimeFormatter class, and the documentation is incorrect; it does not support parsing and is not intended to (only formatting).

Windswept answered 23/7, 2012 at 22:5 Comment(1)
I had to tweak this code slightly in my case because of issues related to Daylight Saving Time and roundtripping to and from UTC, but as long as you take that into account, you can use this solution -- and it sure wasn't something that would have occurred to me. Thanks!Daisey
R
4

Would std::get_time do the trick? The example at the bottom of the page suggests you can parse a date string using a locale into a tm struct. I imagine you could then convert the tm struct into the correct WinRT DateTime.

Roadblock answered 26/7, 2012 at 11:53 Comment(1)
I believe this would also work, but it seems to be less flexible when compared with COleDateTime::ParseDateTime. But I think it would be a simpler solution when you are receiving well-formatted dates.Windswept
B
0

I use this code:

auto cal = ref new Windows::Globalization::Calendar(); cal->AddSeconds(additionalSeconds); return cal->GetDateTime();

With Windows::Globalization::Calendar, you have all the nice time functions you need: https://msdn.microsoft.com/library/windows/apps/br206724

Bridesmaid answered 15/3, 2016 at 7:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.