gnucash unstable: Multiple changes pushed
John Ralls
jralls at code.gnucash.org
Tue Jan 9 20:34:07 EST 2018
Updated via https://github.com/Gnucash/gnucash/commit/ebbcd30f (commit)
via https://github.com/Gnucash/gnucash/commit/fcf88262 (commit)
from https://github.com/Gnucash/gnucash/commit/e798df07 (commit)
commit ebbcd30f398e589abbaf1efbeb99d74cb04ba951
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Jan 9 14:58:43 2018 -0800
Save Changes Bug 792106 - Wrong dates displayed
The first attempt to fix this, a17bc85a, doesn't work because the
boost::date_time constructor gets enough information in most cases to
generate a date, just not the one we expect. This change looks for '-' in
the fourth position and if it's there assumes iso-extended format, otherwise
it assumes delimiter-less ISO without the 'T', i.e. %Y%m%d%H%M%S.
diff --git a/libgnucash/engine/gnc-datetime.cpp b/libgnucash/engine/gnc-datetime.cpp
index 795ae5c..2ddc9dd 100644
--- a/libgnucash/engine/gnc-datetime.cpp
+++ b/libgnucash/engine/gnc-datetime.cpp
@@ -294,16 +294,12 @@ GncDateTimeImpl::GncDateTimeImpl(const std::string str) :
auto input_facet(new Facet());
std::istringstream ss(str.substr(0, tzpos));
ss.imbue(std::locale(std::locale(), input_facet));
- input_facet->set_iso_extended_format();
+ if (str.find("-") == 4)
+ input_facet->set_iso_extended_format();
+ else /* Not in iso format, try squashed format. */
+ input_facet->format("%Y%m%d%H%M%S");
PTime pdt(not_a_date_time);
ss >> pdt;
- if (pdt.is_special())
- {
- input_facet->format("%Y%m%d%H%M%S");
- ss.clear(); //Reset to the beginning.
- ss.seekg(0);
- ss >> pdt;
- }
m_time = LDT(pdt.date(), pdt.time_of_day(), tzptr,
LDTBase::NOT_DATE_TIME_ON_ERROR);
}
@@ -450,7 +446,7 @@ GncDateTime::GncDateTime(const time64 time) :
m_impl(new GncDateTimeImpl(time)) {}
GncDateTime::GncDateTime(const struct tm tm) :
m_impl(new GncDateTimeImpl(tm)) {}
-GncDateTime::GncDateTime(const std::string str, std::string fmt) :
+GncDateTime::GncDateTime(const std::string str) :
m_impl(new GncDateTimeImpl(str)) {}
GncDateTime::~GncDateTime() = default;
diff --git a/libgnucash/engine/test/gtest-gnc-datetime.cpp b/libgnucash/engine/test/gtest-gnc-datetime.cpp
index 245562b..65989bf 100644
--- a/libgnucash/engine/test/gtest-gnc-datetime.cpp
+++ b/libgnucash/engine/test/gtest-gnc-datetime.cpp
@@ -293,6 +293,16 @@ TEST(gnc_datetime_constructors, test_string_constructor)
EXPECT_EQ(tm.tm_hour, 15);
EXPECT_EQ(tm.tm_min, 8);
EXPECT_EQ(tm.tm_sec, 19);
+/* Squashed format from SQLite3 databases */
+ timestr = "20151205115703";
+ GncDateTime time4(timestr);
+ tm = time4.utc_tm();
+ EXPECT_EQ(tm.tm_year, 115);
+ EXPECT_EQ(tm.tm_mon, 11);
+ EXPECT_EQ(tm.tm_mday, 5);
+ EXPECT_EQ(tm.tm_hour,11);
+ EXPECT_EQ(tm.tm_min, 57);
+ EXPECT_EQ(tm.tm_sec, 3);
}
TEST(gnc_datetime_constructors, test_struct_tm_constructor)
commit fcf88262ca036439c711d91d2a8e7bf892f49b21
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Jan 9 13:58:25 2018 -0800
Extract function tz_from_string.
Also changes from calculating the Bug 767824 offset to using
boost::date_time::local_time_in() and provides unit tests.
diff --git a/libgnucash/engine/gnc-datetime.cpp b/libgnucash/engine/gnc-datetime.cpp
index 2bec648..795ae5c 100644
--- a/libgnucash/engine/gnc-datetime.cpp
+++ b/libgnucash/engine/gnc-datetime.cpp
@@ -262,48 +262,31 @@ GncDateTimeImpl::GncDateTimeImpl(const GncDateImpl& date, DayPart part) :
}
}
+using PTZ = boost::local_time::posix_time_zone;
+
+static TZ_Ptr
+tz_from_string(std::string str)
+{
+ if (str.empty()) return utc_zone;
+ std::string tzstr = "XXX" + str;
+ if (tzstr.length() > 6 && tzstr[6] != ':') //6 for XXXsHH, s is + or -
+ tzstr.insert(6, ":");
+ if (tzstr.length() > 9 && tzstr[9] != ':') //9 for XXXsHH:MM
+ {
+ tzstr.insert(9, ":");
+ }
+ return TZ_Ptr(new PTZ(tzstr));
+}
+
GncDateTimeImpl::GncDateTimeImpl(const std::string str) :
m_time(unix_epoch, utc_zone)
{
if (str.empty()) return;
- using std::string;
- using PTZ = boost::local_time::posix_time_zone;
- TZ_Ptr tzptr;
auto tzpos = str.find_first_of("+-", str.find(":"));
- int offset = 0L;
- if (tzpos != str.npos)
- {
- string tzstr = "XXX" + str.substr(tzpos);
- if (tzstr.length() > 6 && tzstr[6] != ':') //6 for XXXsHH, s is + or -
- tzstr.insert(6, ":");
- if (tzstr.length() > 9 && tzstr[9] != ':') //9 for XXXsHH:MM
- {
- tzstr.insert(9, ":");
- /* Bug 767824: A GLib bug in parsing the UTC timezone on
- * Windows may have created a bogus timezone of a random
- * number of minutes. Since there are no fractional-hour
- * timezones around the prime meridian we can safely check for
- * this in files by looking for minutes-only offsets and
- * making the appropriate correction.
- */
- if (tzstr.compare(7,8, "00") &&
- (tzstr.length() > 10 ? tzstr[10] != '0' :
- !tzstr.compare(10, 11, "00")))
- {
- offset = atoi(tzstr.substr(10,11).c_str());
- if (offset && tzpos == '-')
- offset = -offset;
- tzstr.replace(10, 11, "00");
- }
- }
- tzptr.reset(new PTZ(tzstr));
- if (str[tzpos - 1] == ' ') --tzpos;
- }
- else
- {
- tzptr = utc_zone;
- }
+ auto tzptr = tz_from_string(tzpos != str.npos ? str.substr(tzpos) : "");
+ if (tzpos != str.npos && str[tzpos - 1] == ' ') --tzpos;
+
try
{
using Facet = boost::posix_time::time_input_facet;
@@ -328,8 +311,15 @@ GncDateTimeImpl::GncDateTimeImpl(const std::string str) :
{
throw(std::invalid_argument("The date string was outside of the supported year range."));
}
- if (offset)
- m_time -= boost::posix_time::minutes(offset);
+ /* Bug 767824: A GLib bug in parsing the UTC timezone on Windows may have
+ * created a bogus timezone of a random number of minutes. Since there are
+ * no fractional-hour timezones around the prime meridian we can safely
+ * check for this in files by resetting to UTC if there's a
+ * less-than-an-hour offset.
+ */
+ auto offset = tzptr->base_utc_offset().seconds();
+ if (offset != 0 && std::abs(offset) < 3600)
+ m_time = m_time.local_time_in(utc_zone);
}
GncDateTimeImpl::operator time64() const
@@ -460,7 +450,7 @@ GncDateTime::GncDateTime(const time64 time) :
m_impl(new GncDateTimeImpl(time)) {}
GncDateTime::GncDateTime(const struct tm tm) :
m_impl(new GncDateTimeImpl(tm)) {}
-GncDateTime::GncDateTime(const std::string str) :
+GncDateTime::GncDateTime(const std::string str, std::string fmt) :
m_impl(new GncDateTimeImpl(str)) {}
GncDateTime::~GncDateTime() = default;
diff --git a/libgnucash/engine/test/gtest-gnc-datetime.cpp b/libgnucash/engine/test/gtest-gnc-datetime.cpp
index 350d22a..245562b 100644
--- a/libgnucash/engine/test/gtest-gnc-datetime.cpp
+++ b/libgnucash/engine/test/gtest-gnc-datetime.cpp
@@ -261,15 +261,38 @@ TEST(gnc_datetime_constructors, test_time64_constructor)
TEST(gnc_datetime_constructors, test_string_constructor)
{
- std::string timestr("2015-12-05 00:01:00");
- GncDateTime time(timestr);
- auto tm = time.utc_tm();
+/* Plain UTC date-time */
+ std::string timestr("2015-12-05 11:57:03");
+ GncDateTime time1(timestr);
+ auto tm = time1.utc_tm();
EXPECT_EQ(tm.tm_year, 115);
EXPECT_EQ(tm.tm_mon, 11);
EXPECT_EQ(tm.tm_mday, 5);
- EXPECT_EQ(tm.tm_hour, 0);
- EXPECT_EQ(tm.tm_min, 1);
- EXPECT_EQ(tm.tm_sec, 0);
+ EXPECT_EQ(tm.tm_hour,11);
+ EXPECT_EQ(tm.tm_min, 57);
+ EXPECT_EQ(tm.tm_sec, 3);
+
+/* Datetime with an offset */
+ timestr = "1993-07-22 15:21:19 +0300";
+ GncDateTime time2(timestr);
+ tm = time2.utc_tm();
+ EXPECT_EQ(tm.tm_year, 93);
+ EXPECT_EQ(tm.tm_mon, 6);
+ EXPECT_EQ(tm.tm_mday, 22);
+ EXPECT_EQ(tm.tm_hour, 12);
+ EXPECT_EQ(tm.tm_min, 21);
+ EXPECT_EQ(tm.tm_sec, 19);
+
+/* Bug 767824 date-time */
+ timestr = "1993-07-22 15:21:19 +0013";
+ GncDateTime time3(timestr);
+ tm = time3.utc_tm();
+ EXPECT_EQ(tm.tm_year, 93);
+ EXPECT_EQ(tm.tm_mon, 6);
+ EXPECT_EQ(tm.tm_mday, 22);
+ EXPECT_EQ(tm.tm_hour, 15);
+ EXPECT_EQ(tm.tm_min, 8);
+ EXPECT_EQ(tm.tm_sec, 19);
}
TEST(gnc_datetime_constructors, test_struct_tm_constructor)
Summary of changes:
libgnucash/engine/gnc-datetime.cpp | 78 +++++++++++----------------
libgnucash/engine/test/gtest-gnc-datetime.cpp | 45 +++++++++++++---
2 files changed, 71 insertions(+), 52 deletions(-)
More information about the gnucash-changes
mailing list