From 16ba1e39b13f90beb9f17afd32474e766480ff2d Mon Sep 17 00:00:00 2001 From: John Ralls Date: Thu, 12 Apr 2018 15:12:14 -0700 Subject: [PATCH] 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. --- libgnucash/engine/gnc-datetime.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/libgnucash/engine/gnc-datetime.cpp b/libgnucash/engine/gnc-datetime.cpp index 0c4337296b..d0958de356 100644 --- a/libgnucash/engine/gnc-datetime.cpp +++ b/libgnucash/engine/gnc-datetime.cpp @@ -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; } }