Fix timezone exceptions on Windows XP.

This commit is contained in:
John Ralls 2015-07-25 11:23:06 -07:00
parent 5cc99806d8
commit b78f102929
2 changed files with 18 additions and 10 deletions

View File

@ -28,7 +28,8 @@
#include <algorithm> #include <algorithm>
#include <boost/date_time/gregorian/gregorian.hpp> #include <boost/date_time/gregorian/gregorian.hpp>
#if PLATFORM(WINDOWS) #if PLATFORM(WINDOWS)
#include <codecvt> //We'd prefer to use std::codecvt, but it's not supported by gcc until 5.0.
#include <boost/locale/encoding_utf.hpp>
#endif #endif
using namespace gnc::date; using namespace gnc::date;
@ -38,6 +39,9 @@ using time_zone = boost::local_time::custom_time_zone;
using dst_offsets = boost::local_time::dst_adjustment_offsets; using dst_offsets = boost::local_time::dst_adjustment_offsets;
using calc_rule_ptr = boost::local_time::dst_calc_rule_ptr; using calc_rule_ptr = boost::local_time::dst_calc_rule_ptr;
const unsigned int TimeZoneProvider::min_year = 1400;
const unsigned int TimeZoneProvider::max_year = 9999;
template<typename T> template<typename T>
T* T*
endian_swap(T* t) endian_swap(T* t)
@ -193,7 +197,7 @@ TimeZoneProvider::load_windows_dynamic_tz (HKEY key, time_zone_names names)
zone_vector.push_back (std::make_pair(0, tz)); zone_vector.push_back (std::make_pair(0, tz));
zone_vector.push_back (std::make_pair(year, tz)); zone_vector.push_back (std::make_pair(year, tz));
} }
zone_vector.push_back (std::make_pair(9999, tz)); zone_vector.push_back (std::make_pair(max_year, tz));
} }
catch (std::invalid_argument) catch (std::invalid_argument)
{ {
@ -234,15 +238,16 @@ void
TimeZoneProvider::load_windows_default_tz() TimeZoneProvider::load_windows_default_tz()
{ {
TIME_ZONE_INFORMATION tzi {}; TIME_ZONE_INFORMATION tzi {};
if (GetTimeZoneInformation (&tzi) == TIME_ZONE_INVALID) GetTimeZoneInformation (&tzi);
throw std::system_error("No default time zone.");
RegTZI regtzi { tzi.Bias, tzi.StandardBias, tzi.DaylightBias, RegTZI regtzi { tzi.Bias, tzi.StandardBias, tzi.DaylightBias,
tzi.StandardDate, tzi.DaylightDate }; tzi.StandardDate, tzi.DaylightDate };
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> conversion; using boost::locale::conv::utf_to_utf;
auto std_name = conversion.to_bytes(tzi.StandardName); auto std_name = utf_to_utf<char>(tzi.StandardName,
auto dlt_name = conversion.to_bytes(tzi.DaylightName); tzi.StandardName + sizeof(tzi.StandardName));
auto dlt_name = utf_to_utf<char>(tzi.DaylightName,
tzi.DaylightName + sizeof(tzi.DaylightName));
time_zone_names names (std_name, std_name, dlt_name, dlt_name); time_zone_names names (std_name, std_name, dlt_name, dlt_name);
zone_vector.push_back(std::make_pair(0, zone_from_regtzi(regtzi, names))); zone_vector.push_back(std::make_pair(max_year, zone_from_regtzi(regtzi, names)));
} }
TimeZoneProvider::TimeZoneProvider (const std::string& identifier) : TimeZoneProvider::TimeZoneProvider (const std::string& identifier) :
@ -635,9 +640,9 @@ TimeZoneProvider::TimeZoneProvider(const std::string& tzname) : zone_vector {}
if (last_time.is_not_a_date_time() || if (last_time.is_not_a_date_time() ||
last_time.date().year() < parser.last_year) last_time.date().year() < parser.last_year)
zone_vector.push_back(zone_no_dst(9999, last_info)); zone_vector.push_back(zone_no_dst(max_year, last_info));
else //Last DST rule forever after. else //Last DST rule forever after.
zone_vector.push_back(zone_from_rule(9999, last_rule)); zone_vector.push_back(zone_from_rule(max_year, last_rule));
} }
#endif #endif

View File

@ -55,11 +55,14 @@ public:
TimeZoneProvider operator=(const TimeZoneProvider&) = delete; TimeZoneProvider operator=(const TimeZoneProvider&) = delete;
TimeZoneProvider operator=(const TimeZoneProvider&&) = delete; TimeZoneProvider operator=(const TimeZoneProvider&&) = delete;
TZ_Ptr get (int year) const noexcept; TZ_Ptr get (int year) const noexcept;
static const unsigned int min_year; //1400
static const unsigned int max_year; //9999
private: private:
TZ_Vector zone_vector; TZ_Vector zone_vector;
#if PLATFORM(WINDOWS) #if PLATFORM(WINDOWS)
void load_windows_dynamic_tz(HKEY, time_zone_names); void load_windows_dynamic_tz(HKEY, time_zone_names);
void load_windows_classic_tz(HKEY, time_zone_names); void load_windows_classic_tz(HKEY, time_zone_names);
void load_windows_default_tz(void);
#endif #endif
}; };