Bug 795080 - Some dates reset to 01/01/1970

An odd corner case: BST apparently came off of DST at 23:00 26 Oct 2014,
so midnight that day was ambiguous about being DST or not; that causes
the local_date_time constructor to throw in spite of the tm.is_dst element
being 0 (meaning pick standard time).

Instead of just failing in that case, try constructing a local_date_time
three hours later then adjust it back three hours. If *that* doesn't work
then throw a std::invalid argument.
This commit is contained in:
John Ralls 2018-04-12 15:12:14 -07:00
parent b5ac8591fc
commit 16ba1e39b1

View File

@ -158,12 +158,12 @@ LDT_from_unix_local(const time64 time)
static LDT
LDT_from_struct_tm(const struct tm tm)
{
auto tdate = boost::gregorian::date_from_tm(tm);
auto tdur = boost::posix_time::time_duration(tm.tm_hour, tm.tm_min,
tm.tm_sec, 0);
auto tz = tzp.get(tdate.year());
try
{
auto tdate = boost::gregorian::date_from_tm(tm);
auto tdur = boost::posix_time::time_duration(tm.tm_hour, tm.tm_min,
tm.tm_sec, 0);
auto tz = tzp.get(tdate.year());
LDT ldt(tdate, tdur, tz, LDTBase::EXCEPTION_ON_ERROR);
return ldt;
}
@ -177,7 +177,18 @@ LDT_from_struct_tm(const struct tm tm)
}
catch(boost::local_time::ambiguous_result&)
{
throw(std::invalid_argument("Struct tm can resolve to more than one time."));
/* We plunked down in the middle of a DST change. Try constructing the
* LDT three hours later to get a valid result then back up those three
* hours to have the time we want.
*/
using boost::posix_time::hours;
auto hour = tm.tm_hour;
tdur += hours(3);
LDT ldt(tdate, tdur, tz, LDTBase::NOT_DATE_TIME_ON_ERROR);
if (ldt.is_special())
throw(std::invalid_argument("Couldn't create a valid datetime."));
ldt -= hours(3);
return ldt;
}
}