rmeador
rmeador

Reputation: 25696

Parse failure using Boost datetime library with time zone string

I'm trying to parse a date/time string in a custom format using Boost's date time library. The format I'm trying to use is rather unusual because it includes the Posix time zone description string. The docs for the library clearly state that there is a flag (%ZP) usable for both input and output that handles the Posix time zone string. The value I'm trying to parse is coming from a web browser, and rather than write JS to perform the transformation specified in the zone string and then send to the server in UTC, I'd rather just do it server-side (since Boost should do this really easily). Obviously I wouldn't be posting here if it worked. This code throws a boost::bad_lexical_cast with a value of "source type value could not be interpreted as target".

using namespace boost::posix_time;
using namespace boost::local_time;
using namespace boost::gregorian;

std::istringstream ss("1989-11-09T15:30:42.005;PST-8PDT,M3.2.0,M11.1.0");
ss.exceptions(std::ios_base::failbit);
local_time_input_facet* facet = new local_time_input_facet("%Y-%m-%dT%H:%M:%S%F;%ZP");
ss.imbue(std::locale(ss.getloc(), facet));

local_date_time ldt(not_a_date_time);

ss >> ldt; // do the parse

std::cout << ldt.to_string();

However, if you replace the format string with "%Y-%m-%dT%H:%M:%S%F;", the parse succeeds just fine (of course it outputs a value in the wrong time zone).

Any idea what I'm doing wrong? The docs for the %ZP flag don't have an example, so I'm not sure how it's supposed to be used.

Upvotes: 1

Views: 1315

Answers (1)

Nim
Nim

Reputation: 33655

I think your format string should look like this: %Y-%m-%dT%H:%M:%s *;%ZP the %s * will match seconds and fractional seconds. With this change, the above code runs, bizarely though, the output I get is:

1989-Nov-09 15:30:42.005000 ST

Not sure why it says ST rather than PST, however the timezone information does get parsed correctly, if you change the date for example to Nov-01, then it will report PDT.

EDIT: the description of the time zone object is here.


Okay, from messing around with this, it appears that the parsing error is caused by the presence of the ;, removing it from the original string such that it becomes:

std::istringstream ss("1989-10-16T15:30:42.005 PST-8PDT,M3.2.0,M10.2.0");

And changing the format string to:

local_time_input_facet* facet = new local_time_input_facet("%Y-%m-%d %H:%M:%s %ZP");

correctly reports:

1989-Oct-16 15:30:42.005000 PST

If you change the input string again to:

std::istringstream ss("1989-10-16T15:30:42.005 PST-8PDT,M3.2.0,M11.1.0");

the output is again correct:

1989-Oct-16 15:30:42.005000 PDT

This tells me that is is indeed honouring the timezone information embedded in the string... so the interesting question is why is it barfing if there is a ;?

Further update, it appears that the input string can only contain alphanumerics, characters from the set .:-, and spaces - after the fractional bits - i.e. you cannot separate the timezone information stuff with any character other than what I've listed above (it's not exhaustive, don't have the time to test for all of them!)

Upvotes: 1

Related Questions