mirror of
https://github.com/HowardHinnant/date.git
synced 2024-12-27 16:41:04 +08:00
TZ stuff fixed for VS2013
This commit is contained in:
parent
ca74113ae8
commit
50802176f3
70
tz.cpp
70
tz.cpp
@ -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
50
tz.h
@ -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());
|
||||||
|
29
tz_private.h
29
tz_private.h
@ -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_;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user