mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-16 18:25:11 -06:00
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.
This commit is contained in:
parent
a7ca20572d
commit
fd37051865
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user