TZ stuff fixed for VS2013

This commit is contained in:
ivanp2015 2015-11-29 07:56:59 +02:00
parent ca74113ae8
commit 50802176f3
3 changed files with 128 additions and 21 deletions

70
tz.cpp
View File

@ -273,12 +273,14 @@ static void get_windows_timezone_info(std::vector<timezone_info>& tz_list)
// Open the parent time zone key that has the list of timezones in. // Open the parent time zone key that has the list of timezones in.
reg_key zones_key; reg_key zones_key;
static const wchar_t zones_key_name[] = { L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones" }; static const wchar_t zones_key_name[] =
{ L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones" };
result = zones_key.open(zones_key_name); result = zones_key.open(zones_key_name);
// TODO! Review if this should happen here or be signalled later. // TODO! Review if this should happen here or be signalled later.
// We don't want the process to fail on startup because of this. // We don't want the process to fail on startup because of this.
if (result != ERROR_SUCCESS) if (result != ERROR_SUCCESS)
throw std::runtime_error("Time Zone registry key could not be opened: " + get_win32_message(result)); throw std::runtime_error("Time Zone registry key could not be opened: "
+ get_win32_message(result));
DWORD size; DWORD size;
wchar_t zone_key_name[256]; wchar_t zone_key_name[256];
@ -295,7 +297,8 @@ static void get_windows_timezone_info(std::vector<timezone_info>& tz_list)
auto status = RegEnumKeyExW(zones_key.handle(), zone_index, zone_key_name, &size, auto status = RegEnumKeyExW(zones_key.handle(), zone_index, zone_key_name, &size,
nullptr, nullptr, nullptr, nullptr); nullptr, nullptr, nullptr, nullptr);
if (status != ERROR_SUCCESS && status != ERROR_NO_MORE_ITEMS) if (status != ERROR_SUCCESS && status != ERROR_NO_MORE_ITEMS)
throw std::runtime_error("Can't enumerate time zone registry key" + get_win32_message(status)); throw std::runtime_error("Can't enumerate time zone registry key"
+ get_win32_message(status));
if (status == ERROR_NO_MORE_ITEMS) if (status == ERROR_NO_MORE_ITEMS)
break; break;
zone_key_name[size] = L'\0'; zone_key_name[size] = L'\0';
@ -389,25 +392,32 @@ load_timezone_mappings_from_csv_file(const std::string& input_path)
std::string copyright; std::string copyright;
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
getline(is, copyright); getline(is, copyright);
for (;;) for (;;)
{ {
timezone_mapping zm{}; timezone_mapping zm{};
is >> std::quoted(zm.other); char ch;
is.read(&ch, 1);
if (is.eof()) if (is.eof())
break; break;
std::getline(is, zm.other, '\"');
read_field_delim(); read_field_delim();
is >> std::quoted(zm.territory);
read_field_delim();
is >> std::quoted(zm.type);
char record_delim; is.read(&ch, 1);
is.read(&record_delim, 1); std::getline(is, zm.territory, '\"');
if (is.gcount() != 1 || record_delim != '\n') read_field_delim();
is.read(&ch, 1);
std::getline(is, zm.type, '\"');
is.read(&ch, 1);
if (is.gcount() != 1 || ch != '\n')
error("record delimiter LF expected"); error("record delimiter LF expected");
if (is.fail() || is.eof()) if (is.fail() || is.eof())
error("unexpected end of file, file read error or formatting error."); error("unexpected end of file, file read error or formatting error.");
++line; ++line;
mappings.push_back(std::move(zm)); mappings.push_back(std::move(zm));
} }
@ -416,7 +426,8 @@ load_timezone_mappings_from_csv_file(const std::string& input_path)
} }
static bool static bool
native_to_standard_timezone_name(const std::string& native_tz_name, std::string& standard_tz_name) native_to_standard_timezone_name(const std::string& native_tz_name,
std::string& standard_tz_name)
{ {
// TOOD! Need be a case insensitive compare? // TOOD! Need be a case insensitive compare?
if (native_tz_name == "UTC") if (native_tz_name == "UTC")
@ -757,7 +768,11 @@ operator>>(std::istream& is, MonthDayTime& x)
throw std::runtime_error(std::string("bad operator: ") + c + c2 throw std::runtime_error(std::string("bad operator: ") + c + c2
+ std::to_string(d)); + std::to_string(d));
x.type_ = c == '<' ? MonthDayTime::lteq : MonthDayTime::gteq; x.type_ = c == '<' ? MonthDayTime::lteq : MonthDayTime::gteq;
x.u = {date::month(m)/d, weekday(dow)}; #if !defined(_MSC_VER) || (_MSC_VER >= 1900)
x.u = {date::month(m)/d, date::weekday(dow)};
#else
x.u = MonthDayTime::U(date::month(m)/d, date::weekday(dow));
#endif
} }
else else
throw std::runtime_error(std::string("bad operator: ") + c); throw std::runtime_error(std::string("bad operator: ") + c);
@ -1005,7 +1020,7 @@ operator<<(std::ostream& os, const Rule& r)
{ {
using namespace date; using namespace date;
using namespace std::chrono; using namespace std::chrono;
save_stream _(os); detail::save_stream _(os);
os.fill(' '); os.fill(' ');
os.flags(std::ios::dec | std::ios::left); os.flags(std::ios::dec | std::ios::left);
os.width(15); os.width(15);
@ -1194,17 +1209,21 @@ Rule::split_overlaps(std::vector<Rule>& rules)
Zone::zonelet::~zonelet() Zone::zonelet::~zonelet()
{ {
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
using minutes = std::chrono::minutes; using minutes = std::chrono::minutes;
using string = std::string; using string = std::string;
if (tag_ == has_save) if (tag_ == has_save)
u.save_.~minutes(); u.save_.~minutes();
else else
u.rule_.~string(); u.rule_.~string();
#endif
} }
Zone::zonelet::zonelet() Zone::zonelet::zonelet()
{ {
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
::new(&u.rule_) std::string(); ::new(&u.rule_) std::string();
#endif
} }
Zone::zonelet::zonelet(const zonelet& i) Zone::zonelet::zonelet(const zonelet& i)
@ -1221,10 +1240,17 @@ Zone::zonelet::zonelet(const zonelet& i)
, first_rule_(i.first_rule_) , first_rule_(i.first_rule_)
, last_rule_(i.last_rule_) , last_rule_(i.last_rule_)
{ {
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
if (tag_ == has_save) if (tag_ == has_save)
::new(&u.save_) std::chrono::minutes(i.u.save_); ::new(&u.save_) std::chrono::minutes(i.u.save_);
else else
::new(&u.rule_) std::string(i.u.rule_); ::new(&u.rule_) std::string(i.u.rule_);
#else
if (tag_ == has_save)
u.save_ = i.u.save_;
else
u.rule_ = i.u.rule_;
#endif
} }
Zone::Zone(const std::string& s) Zone::Zone(const std::string& s)
@ -1344,7 +1370,8 @@ find_previous_rule(const Rule* r, date::year y)
// [first, last) all have the same name // [first, last) all have the same name
static static
std::pair<const Rule*, date::year> std::pair<const Rule*, date::year>
find_next_rule(const Rule* first_rule, const Rule* last_rule, const Rule* r, date::year y) find_next_rule(const Rule* first_rule, const Rule* last_rule, const Rule* r,
date::year y)
{ {
using namespace date; using namespace date;
if (y == r->ending_year()) if (y == r->ending_year())
@ -1564,9 +1591,15 @@ Zone::adjust_infos(const std::vector<Rule>& rules)
std::istringstream in(z.u.rule_); std::istringstream in(z.u.rule_);
in.exceptions(std::ios::failbit | std::ios::badbit); in.exceptions(std::ios::failbit | std::ios::badbit);
auto tmp = duration_cast<minutes>(parse_signed_time(in)); auto tmp = duration_cast<minutes>(parse_signed_time(in));
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
z.u.rule_.~string(); z.u.rule_.~string();
z.tag_ = zonelet::has_save; z.tag_ = zonelet::has_save;
::new(&z.u.save_) minutes(tmp); ::new(&z.u.save_) minutes(tmp);
#else
z.u.rule_.clear();
z.tag_ = zonelet::has_save;
z.u.save_ = tmp;
#endif
} }
catch (...) catch (...)
{ {
@ -1773,7 +1806,7 @@ operator<<(std::ostream& os, const Zone& z)
{ {
using namespace date; using namespace date;
using namespace std::chrono; using namespace std::chrono;
save_stream _(os); detail::save_stream _(os);
os.fill(' '); os.fill(' ');
os.flags(std::ios::dec | std::ios::left); os.flags(std::ios::dec | std::ios::left);
os.width(35); os.width(35);
@ -1832,7 +1865,7 @@ std::ostream&
operator<<(std::ostream& os, const Link& x) operator<<(std::ostream& os, const Link& x)
{ {
using namespace date; using namespace date;
save_stream _(os); detail::save_stream _(os);
os.fill(' '); os.fill(' ');
os.flags(std::ios::dec | std::ios::left); os.flags(std::ios::dec | std::ios::left);
os.width(35); os.width(35);
@ -2099,7 +2132,8 @@ current_zone()
if (tz_result == TIME_ZONE_ID_INVALID) if (tz_result == TIME_ZONE_ID_INVALID)
{ {
auto error_code = ::GetLastError(); // Store this quick before it gets overwritten. auto error_code = ::GetLastError(); // Store this quick before it gets overwritten.
throw std::runtime_error("GetTimeZoneInformation failed: " + get_win32_message(error_code)); throw std::runtime_error("GetTimeZoneInformation failed: "
+ get_win32_message(error_code));
} }
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::string standard_name(converter.to_bytes(tzi.StandardName)); std::string standard_name(converter.to_bytes(tzi.StandardName));

50
tz.h
View File

@ -201,8 +201,23 @@ private:
std::vector<zonelet> zonelets_; std::vector<zonelet> zonelets_;
public: public:
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
Zone(Zone&&) = default; Zone(Zone&&) = default;
Zone& operator=(Zone&&) = default; Zone& operator=(Zone&&) = default;
#else
Zone(Zone&& src)
:
name_(std::move(src.name_)),
zonelets_(std::move(zonelets_))
{}
Zone& operator=(Zone&& src)
{
name_ = std::move(src.name_);
zonelets_ = std::move(src.zonelets_);
return *this;
}
#endif
explicit Zone(const std::string& s); explicit Zone(const std::string& s);
@ -334,7 +349,8 @@ Zone::to_sys_impl(std::chrono::time_point<std::chrono::system_clock,
} }
return i.begin; return i.begin;
} }
assert(floor<seconds>(tp) >= i.begin + get_info(i.begin - seconds{1}, tz::utc).offset); assert(floor<seconds>(tp) >=
i.begin + get_info(i.begin - seconds{1}, tz::utc).offset);
} }
if (i.end - floor<seconds>(tp_sys) <= days{1}) if (i.end - floor<seconds>(tp_sys) <= days{1})
{ {
@ -577,8 +593,36 @@ struct TZ_DB
#endif #endif
TZ_DB() = default; TZ_DB() = default;
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
TZ_DB(TZ_DB&&) = default; TZ_DB(TZ_DB&&) = default;
TZ_DB& operator=(TZ_DB&&) = default; TZ_DB& operator=(TZ_DB&&) = default;
#else
TZ_DB(TZ_DB&& src)
:
zones(std::move(src.zones)),
links(std::move(links)),
leaps(std::move(leaps)),
rules(std::move(rules))
#if TIMEZONE_MAPPING
,
mappings(std::move(mappings)),
native_zones(std::move(native_zones))
#endif
{}
TZ_DB& operator=(TZ_DB&& src)
{
zones = std::move(src.zones);
links = std::move(links);
leaps = std::move(leaps);
rules = std::move(rules);
#if TIMEZONE_MAPPING
mappings = std::move(mappings);
native_zones = std::move(native_zones);
#endif
return *this;
}
#endif
}; };
std::ostream& operator<<(std::ostream& os, const TZ_DB& db); std::ostream& operator<<(std::ostream& os, const TZ_DB& db);
@ -604,7 +648,7 @@ public:
using time_point = std::chrono::time_point<utc_clock>; using time_point = std::chrono::time_point<utc_clock>;
static CONSTDATA bool is_steady = true; static CONSTDATA bool is_steady = true;
static time_point now() noexcept; static time_point now() NOEXCEPT;
template <class Duration> template <class Duration>
static static
@ -621,7 +665,7 @@ public:
inline inline
utc_clock::time_point utc_clock::time_point
utc_clock::now() noexcept utc_clock::now() NOEXCEPT
{ {
using namespace std::chrono; using namespace std::chrono;
return sys_to_utc(system_clock::now()); return sys_to_utc(system_clock::now());

View File

@ -33,6 +33,9 @@ class MonthDayTime
private: private:
struct pair struct pair
{ {
#if defined(_MSC_VER) && (_MSC_VER < 1900)
pair() : month_day_(date::jan / 1), weekday_(0U) {}
#endif
date::month_day month_day_; date::month_day month_day_;
date::weekday weekday_; date::weekday weekday_;
}; };
@ -40,17 +43,37 @@ private:
enum Type {month_day, month_last_dow, lteq, gteq}; enum Type {month_day, month_last_dow, lteq, gteq};
Type type_{month_day}; Type type_{month_day};
#if defined(_MSC_VER) && (_MSC_VER < 1900)
struct U
#else
union U union U
#endif
{ {
date::month_day month_day_; date::month_day month_day_;
date::month_weekday_last month_weekday_last_; date::month_weekday_last month_weekday_last_;
pair month_day_weekday_; pair month_day_weekday_;
#if !defined(_MSC_VER) && (_MSC_VER >= 1900)
U() : month_day_{date::jan/1} {} U() : month_day_{date::jan/1} {}
#else
U() :
month_day_(date::jan/1),
month_weekday_last_(date::month(0U), date::weekday_last(date::weekday(0U)))
{}
U(const date::month_day& month_day,
const date::weekday& weekday) :
month_day_(month_day),
month_weekday_last_(date::month(0U), date::weekday_last(weekday))
{}
#endif // !defined(_MSC_VER) && (_MSC_VER >= 1900)
U& operator=(const date::month_day& x); U& operator=(const date::month_day& x);
U& operator=(const date::month_weekday_last& x); U& operator=(const date::month_weekday_last& x);
U& operator=(const pair& x); U& operator=(const pair& x);
} u; } u;
std::chrono::hours h_{0}; std::chrono::hours h_{0};
std::chrono::minutes m_{0}; std::chrono::minutes m_{0};
std::chrono::seconds s_{0}; std::chrono::seconds s_{0};
@ -165,7 +188,12 @@ struct Zone::zonelet
std::chrono::seconds gmtoff_; std::chrono::seconds gmtoff_;
tag tag_ = has_rule; tag tag_ = has_rule;
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
union U union U
#else
struct U
#endif
{ {
std::string rule_; std::string rule_;
std::chrono::minutes save_; std::chrono::minutes save_;
@ -175,6 +203,7 @@ struct Zone::zonelet
U(const U&) {} U(const U&) {}
U& operator=(const U&) = delete; U& operator=(const U&) = delete;
} u; } u;
std::string format_; std::string format_;
date::year until_year_{0}; date::year until_year_{0};
MonthDayTime until_date_; MonthDayTime until_date_;