gnucash master: Multiple changes pushed
John Ralls
jralls at code.gnucash.org
Tue Sep 27 09:19:39 EDT 2016
Updated via https://github.com/Gnucash/gnucash/commit/ba002bbe (commit)
via https://github.com/Gnucash/gnucash/commit/fd370518 (commit)
via https://github.com/Gnucash/gnucash/commit/a7ca2057 (commit)
via https://github.com/Gnucash/gnucash/commit/158b17d5 (commit)
via https://github.com/Gnucash/gnucash/commit/0dd672c6 (commit)
from https://github.com/Gnucash/gnucash/commit/081d6ec0 (commit)
commit ba002bbec4c1580502358881dbaeb49a199aac2b
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Sep 27 15:19:08 2016 +0200
Fix test failure when in Spain.
It turns out that some timezones use local time for pre-1900 dates in
the 32bit timezone file, too.
diff --git a/src/libqof/qof/test/test-gnc-date.c b/src/libqof/qof/test/test-gnc-date.c
index a3dfc21..dc22b76 100644
--- a/src/libqof/qof/test/test-gnc-date.c
+++ b/src/libqof/qof/test/test-gnc-date.c
@@ -261,10 +261,10 @@ test_gnc_mktime (void)
{
time64 secs = gnc_mktime (&time[ind]);
#if !PLATFORM(WINDOWS)
- //The 64-bit timezone database uses local time for some
+ //The timezone database uses local time for some
//timezones before 1900, which screws up the offset.
- if (time[ind].tm_year < 0 && sizeof(time_t) == sizeof(int64_t))
- continue;
+ if (time[ind].tm_year < 0)
+ continue;
#endif
g_assert_cmpint (secs, ==, ans[ind] - offset);
commit fd3705186524f2600654cd20d372073906f92d1f
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Sep 27 15:17:39 2016 +0200
gnc-timezone: Enable POSIX-style timezone strings on Unix systems.
E.g. CEST01CEDT,M4.1.0,M10.1.0.
Also reorder priority of finding TZ information: Passed-in timezone string
is tried first; if that's empty or fails, try the TZ variable, then
/etc/localtime, and finally give up and use UTC. Exceptions never leave
GncTimeZoneProvider and *some* timezone is always returned.
Provide a new test for posix timezones and invert the exception test.
diff --git a/src/libqof/qof/gnc-timezone.cpp b/src/libqof/qof/gnc-timezone.cpp
index bd52498..d6b8c89 100644
--- a/src/libqof/qof/gnc-timezone.cpp
+++ b/src/libqof/qof/gnc-timezone.cpp
@@ -377,15 +377,6 @@ namespace IANAParser
}
}
- if (!ifs.is_open())
- {
- if (!tzname.empty())
- std::cerr << "Failed to open time zone " << tzname <<
- "; No such file. Falling back on system default timezone.\n";
- ifs.open("/etc/localtime",
- std::ios::in|std::ios::binary|std::ios::ate);
- }
-
if (! ifs.is_open())
throw std::invalid_argument("The timezone string failed to resolve to a valid filename");
std::streampos filesize = ifs.tellg();
@@ -609,7 +600,8 @@ zone_from_rule(int year, DSTRule::DSTRule rule)
return std::make_pair(year, tz);
}
-TimeZoneProvider::TimeZoneProvider(const std::string& tzname) : zone_vector {}
+void
+TimeZoneProvider::parse_file(const std::string& tzname)
{
IANAParser::IANAParser parser(tzname);
auto last_info = std::find_if(parser.tzinfo.begin(), parser.tzinfo.end(),
@@ -675,6 +667,34 @@ TimeZoneProvider::TimeZoneProvider(const std::string& tzname) : zone_vector {}
zone_vector.push_back(zone_from_rule(max_year, last_rule));
}
+TimeZoneProvider::TimeZoneProvider(const std::string& tzname) : zone_vector {}
+{
+ try
+ {
+ parse_file(tzname);
+ }
+ catch(const std::invalid_argument& err)
+ {
+ try
+ {
+ TZ_Ptr zone(new PTZ(tzname));
+ zone_vector.push_back(std::make_pair(max_year, zone));
+ }
+ catch(const std::exception& err)
+ {
+ std::cerr << "Unable to use either provided tzname or TZ environment variable. Resorting to /etc/localtime.\n";
+ try
+ {
+ parse_file("/etc/localtime");
+ }
+ catch(const std::invalid_argument& env)
+ {
+ std::cerr << "/etc/localtime invalid, resorting to GMT.";
+ TZ_Ptr zone(new PTZ("UTC0"));
+ zone_vector.push_back(std::make_pair(max_year, zone));
+ }
+ }
+ }
}
#endif
diff --git a/src/libqof/qof/gnc-timezone.hpp b/src/libqof/qof/gnc-timezone.hpp
index efbfc65..546bbf3 100644
--- a/src/libqof/qof/gnc-timezone.hpp
+++ b/src/libqof/qof/gnc-timezone.hpp
@@ -58,6 +58,7 @@ public:
static const unsigned int min_year; //1400
static const unsigned int max_year; //9999
private:
+ void parse_file(const std::string& tzname);
TZ_Vector zone_vector;
#if PLATFORM(WINDOWS)
void load_windows_dynamic_tz(HKEY, time_zone_names);
diff --git a/src/libqof/qof/test/gtest-gnc-timezone.cpp b/src/libqof/qof/test/gtest-gnc-timezone.cpp
index b20f11a..b7e4f51 100644
--- a/src/libqof/qof/test/gtest-gnc-timezone.cpp
+++ b/src/libqof/qof/test/gtest-gnc-timezone.cpp
@@ -57,8 +57,23 @@ TEST(gnc_timezone_constructors, test_pacific_time_constructor)
EXPECT_TRUE(tz->base_utc_offset().hours() == -8);
}
+#if !PLATFORM(WINDOWS)
+TEST(gnc_timezone_constructors, test_posix_timezone)
+{
+ std::string timezone("FST08FDT07,M4.1.0,M10.31.0");
+ TimeZoneProvider tzp(timezone);
+ TZ_Ptr tz = tzp.get(2006);
+ EXPECT_TRUE(tz->std_zone_abbrev() == "FST");
+ EXPECT_TRUE(tz->dst_zone_abbrev() == "FDT");
+ EXPECT_TRUE(tz->base_utc_offset().hours() == 8L);
+ EXPECT_TRUE(tz->dst_offset().hours() == 7L);
+}
+#endif
+
TEST(gnc_timezone_constructors, test_bogus_time_constructor)
{
- EXPECT_THROW (TimeZoneProvider tzp ("New York Standard Time"),
- std::invalid_argument);
+ TimeZoneProvider tzp ("New York Standard Time");
+ TimeZoneProvider machine ("");
+ EXPECT_TRUE(machine.get(2006)->std_zone_abbrev() ==
+ tzp.get(2006)->std_zone_abbrev());
}
commit a7ca20572d6e42573d47536b40ca40c62bcec6a6
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Sep 27 15:11:06 2016 +0200
Fix whitespace in function about to be extracted.
diff --git a/src/libqof/qof/gnc-timezone.cpp b/src/libqof/qof/gnc-timezone.cpp
index 710eebd..bd52498 100644
--- a/src/libqof/qof/gnc-timezone.cpp
+++ b/src/libqof/qof/gnc-timezone.cpp
@@ -613,66 +613,68 @@ TimeZoneProvider::TimeZoneProvider(const std::string& tzname) : zone_vector {}
{
IANAParser::IANAParser parser(tzname);
auto last_info = std::find_if(parser.tzinfo.begin(), parser.tzinfo.end(),
- [](IANAParser::TZInfo tz)
- {return !tz.info.isdst;});
+ [](IANAParser::TZInfo tz)
+ {return !tz.info.isdst;});
auto last_time = ptime();
DSTRule::DSTRule last_rule;
using boost::gregorian::date;
using boost::posix_time::ptime;
using boost::posix_time::time_duration;
for (auto txi = parser.transitions.begin();
- txi != parser.transitions.end(); ++txi)
+ txi != parser.transitions.end(); ++txi)
{
- auto this_info = parser.tzinfo.begin() + txi->index;
+ auto this_info = parser.tzinfo.begin() + txi->index;
//Can't use boost::posix_date::from_time_t() constructor because it
//silently casts the time_t to an int32_t.
- auto this_time = ptime(date(1970, 1, 1),
- time_duration(txi->timestamp / 3600, 0,
- txi->timestamp % 3600));
- try
- {
- auto this_year = this_time.date().year();
- //Initial case
- if (last_time.is_not_a_date_time())
- zone_vector.push_back(zone_no_dst(this_year - 1, last_info));
- //gap in transitions > 1 year, non-dst zone
- //change. In the last case the exact date of the change will be
- //wrong because boost::local_date::timezone isn't able to
- //represent it. For GnuCash's purposes this isn't likely to be
- //important as the last time this sort of transition happened
- //was 1946, but we have to handle the case in order to parse
- //the tz file.
- else if (this_year - last_time.date().year() > 1 ||
- last_info->info.isdst == this_info->info.isdst)
- {
- zone_vector.push_back(zone_no_dst(this_year, last_info));
- }
-
- else
- {
- DSTRule::DSTRule new_rule(last_info, this_info,
- last_time, this_time);
- if (new_rule != last_rule)
- {
- last_rule = new_rule;
- zone_vector.push_back(zone_from_rule (this_time.date().year(),
- new_rule));
- }
- }
- }
- catch(boost::gregorian::bad_year err)
- {
- continue;
- }
- last_time = this_time;
- last_info = this_info;
+ auto this_time = ptime(date(1970, 1, 1),
+ time_duration(txi->timestamp / 3600, 0,
+ txi->timestamp % 3600));
+ try
+ {
+ auto this_year = this_time.date().year();
+ //Initial case
+ if (last_time.is_not_a_date_time())
+ zone_vector.push_back(zone_no_dst(this_year - 1, last_info));
+ //gap in transitions > 1 year, non-dst zone
+ //change. In the last case the exact date of the change will be
+ //wrong because boost::local_date::timezone isn't able to
+ //represent it. For GnuCash's purposes this isn't likely to be
+ //important as the last time this sort of transition happened
+ //was 1946, but we have to handle the case in order to parse
+ //the tz file.
+ else if (this_year - last_time.date().year() > 1 ||
+ last_info->info.isdst == this_info->info.isdst)
+ {
+ zone_vector.push_back(zone_no_dst(this_year, last_info));
+ }
+
+ else
+ {
+ DSTRule::DSTRule new_rule(last_info, this_info,
+ last_time, this_time);
+ if (new_rule != last_rule)
+ {
+ last_rule = new_rule;
+ zone_vector.push_back(zone_from_rule (this_time.date().year(),
+ new_rule));
+ }
+ }
+ }
+ catch(const boost::gregorian::bad_year& err)
+ {
+ continue;
+ }
+ last_time = this_time;
+ last_info = this_info;
}
if (last_time.is_not_a_date_time() ||
- last_time.date().year() < parser.last_year)
- zone_vector.push_back(zone_no_dst(max_year, last_info));
+ last_time.date().year() < parser.last_year)
+ zone_vector.push_back(zone_no_dst(max_year, last_info));
else //Last DST rule forever after.
- zone_vector.push_back(zone_from_rule(max_year, last_rule));
+ zone_vector.push_back(zone_from_rule(max_year, last_rule));
+}
+
}
#endif
commit 158b17d582e4a3667d448a2dc8caa8a5926544ae
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Sep 27 15:06:56 2016 +0200
gnu-timezone: Alias boost::local_time::posix_time_zone.
diff --git a/src/libqof/qof/gnc-timezone.cpp b/src/libqof/qof/gnc-timezone.cpp
index 1f745cc..710eebd 100644
--- a/src/libqof/qof/gnc-timezone.cpp
+++ b/src/libqof/qof/gnc-timezone.cpp
@@ -44,6 +44,7 @@ using duration = boost::posix_time::time_duration;
using time_zone = boost::local_time::custom_time_zone;
using dst_offsets = boost::local_time::dst_adjustment_offsets;
using calc_rule_ptr = boost::local_time::dst_calc_rule_ptr;
+using PTZ = boost::local_time::posix_time_zone;
const unsigned int TimeZoneProvider::min_year = 1400;
const unsigned int TimeZoneProvider::max_year = 9999;
@@ -688,7 +689,7 @@ TimeZoneProvider::get(int year) const noexcept
year);
if (!zone_vector.empty())
return zone_vector.back().second;
- return TZ_Ptr(new boost::local_time::posix_time_zone("UTC0"));
+ return TZ_Ptr(new PTZ("UTC0"));
}
return iter->second;
}
commit 0dd672c622938b9d9ec9299f0e5d45af13e02042
Author: John Ralls <jralls at ceridwen.us>
Date: Mon Sep 26 18:29:19 2016 +0200
Handle TZ that's not a file name by opening /etc/localtime.
diff --git a/src/libqof/qof/gnc-timezone.cpp b/src/libqof/qof/gnc-timezone.cpp
index 46a7ca9..1f745cc 100644
--- a/src/libqof/qof/gnc-timezone.cpp
+++ b/src/libqof/qof/gnc-timezone.cpp
@@ -356,13 +356,8 @@ namespace IANAParser
if (auto tzenv = getenv("TZ"))
tzname = std::string(std::getenv("TZ"));
//std::cout << "Testing tzname " << tzname << "\n";
- if (tzname.empty())
- {
- ifs.open("/etc/localtime",
- std::ios::in|std::ios::binary|std::ios::ate);
- }
- else
- {
+ if (!tzname.empty())
+ {
//POSIX specifies that that identifier should begin with ':', but we
//should be liberal. If it's there, it's not part of the filename.
if (tzname[0] == ':')
@@ -380,6 +375,16 @@ namespace IANAParser
std::ios::in|std::ios::binary|std::ios::ate);
}
}
+
+ if (!ifs.is_open())
+ {
+ if (!tzname.empty())
+ std::cerr << "Failed to open time zone " << tzname <<
+ "; No such file. Falling back on system default timezone.\n";
+ ifs.open("/etc/localtime",
+ std::ios::in|std::ios::binary|std::ios::ate);
+ }
+
if (! ifs.is_open())
throw std::invalid_argument("The timezone string failed to resolve to a valid filename");
std::streampos filesize = ifs.tellg();
Summary of changes:
src/libqof/qof/gnc-timezone.cpp | 140 +++++++++++++++++------------
src/libqof/qof/gnc-timezone.hpp | 1 +
src/libqof/qof/test/gtest-gnc-timezone.cpp | 19 +++-
src/libqof/qof/test/test-gnc-date.c | 6 +-
4 files changed, 105 insertions(+), 61 deletions(-)
More information about the gnucash-changes
mailing list