diff --git a/README.md b/README.md index 0d6fa46..273b5e0 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ This is actually several separate C++11/C++14 libraries: `"date.h"` and `"tz.h"` are now being proposed for standardization: * Current proposal: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0355r4.html + * Draft revision: http://howardhinnant.github.io/date/d0355r5.html List of projects using this library: diff --git a/include/date/tz.h b/include/date/tz.h index 59677b1..1387bf1 100644 --- a/include/date/tz.h +++ b/include/date/tz.h @@ -151,101 +151,6 @@ namespace detail struct undocumented; } -class nonexistent_local_time - : public std::runtime_error -{ -public: - template - nonexistent_local_time(local_time tp, local_seconds first, - const std::string& first_abbrev, local_seconds last, - const std::string& last_abbrev, sys_seconds time_sys); - -private: - template - static - std::string - make_msg(local_time tp, - local_seconds first, const std::string& first_abbrev, - local_seconds last, const std::string& last_abbrev, - sys_seconds time_sys); -}; - -template -inline -nonexistent_local_time::nonexistent_local_time(local_time tp, - local_seconds begin, - const std::string& first_abbrev, - local_seconds end, - const std::string& last_abbrev, - sys_seconds time_sys) - : std::runtime_error(make_msg(tp, begin, first_abbrev, end, last_abbrev, time_sys)) - {} - -template -std::string -nonexistent_local_time::make_msg(local_time tp, local_seconds begin, - const std::string& first_abbrev, local_seconds end, - const std::string& last_abbrev, sys_seconds time_sys) -{ - using namespace date; - std::ostringstream os; - os << tp << " is in a gap between\n" - << begin << ' ' << first_abbrev << " and\n" - << end << ' ' << last_abbrev - << " which are both equivalent to\n" - << time_sys << " UTC"; - return os.str(); -} - -class ambiguous_local_time - : public std::runtime_error -{ -public: - template - ambiguous_local_time(local_time tp, std::chrono::seconds first_offset, - const std::string& first_abbrev, - std::chrono::seconds second_offset, - const std::string& second_abbrev); - -private: - template - static - std::string - make_msg(local_time tp, - std::chrono::seconds first_offset, const std::string& first_abbrev, - std::chrono::seconds second_offset, const std::string& second_abbrev); -}; - -template -inline -ambiguous_local_time::ambiguous_local_time( - local_time tp, - std::chrono::seconds first_offset, - const std::string& first_abbrev, - std::chrono::seconds second_offset, - const std::string& second_abbrev) - : std::runtime_error(make_msg(tp, first_offset, first_abbrev, second_offset, - second_abbrev)) - {} - -template -std::string -ambiguous_local_time::make_msg(local_time tp, - std::chrono::seconds first_offset, - const std::string& first_abbrev, - std::chrono::seconds second_offset, - const std::string& second_abbrev) -{ - using namespace date; - std::ostringstream os; - os << tp << " is ambiguous. It could be\n" - << tp << ' ' << first_abbrev << " == " - << tp - first_offset << " UTC or\n" - << tp << ' ' << second_abbrev << " == " - << tp - second_offset << " UTC"; - return os.str(); -} - struct sys_info { sys_seconds begin; @@ -291,6 +196,79 @@ operator<<(std::basic_ostream& os, const local_info& r) return os; } +class nonexistent_local_time + : public std::runtime_error +{ +public: + template + nonexistent_local_time(local_time tp, const local_info& i); + +private: + template + static + std::string + make_msg(local_time tp, const local_info& i); +}; + +template +inline +nonexistent_local_time::nonexistent_local_time(local_time tp, + const local_info& i) + : std::runtime_error(make_msg(tp, i)) +{ +} + +template +std::string +nonexistent_local_time::make_msg(local_time tp, const local_info& i) +{ + assert(i.result == local_info::nonexistent); + std::ostringstream os; + os << tp << " is in a gap between\n" + << local_seconds{i.first.end.time_since_epoch()} + i.first.offset << ' ' + << i.first.abbrev << " and\n" + << local_seconds{i.second.begin.time_since_epoch()} + i.second.offset << ' ' + << i.second.abbrev + << " which are both equivalent to\n" + << i.first.end << " UTC"; + return os.str(); +} + +class ambiguous_local_time + : public std::runtime_error +{ +public: + template + ambiguous_local_time(local_time tp, const local_info& i); + +private: + template + static + std::string + make_msg(local_time tp, const local_info& i); +}; + +template +inline +ambiguous_local_time::ambiguous_local_time(local_time tp, const local_info& i) + : std::runtime_error(make_msg(tp, i)) +{ +} + +template +std::string +ambiguous_local_time::make_msg(local_time tp, const local_info& i) +{ + assert(i.result == local_info::ambiguous); + std::ostringstream os; + os << tp << " is ambiguous. It could be\n" + << tp << ' ' << i.first.abbrev << " == " + << tp - i.first.offset << " UTC or\n" + << tp << ' ' << i.second.abbrev << " == " + << tp - i.second.offset << " UTC"; + return os.str(); +} + class time_zone; #if HAS_STRING_VIEW @@ -958,19 +936,9 @@ time_zone::to_sys_impl(local_time tp, choose, std::true_type) const using namespace std::chrono; auto i = get_info(tp); if (i.result == local_info::nonexistent) - { - auto prev_end = local_seconds{i.first.end.time_since_epoch()} + - i.first.offset; - auto next_begin = local_seconds{i.second.begin.time_since_epoch()} + - i.second.offset; - throw nonexistent_local_time(tp, prev_end, i.first.abbrev, - next_begin, i.second.abbrev, i.first.end); - } + throw nonexistent_local_time(tp, i); else if (i.result == local_info::ambiguous) - { - throw ambiguous_local_time(tp, i.first.offset, i.first.abbrev, - i.second.offset, i.second.abbrev); - } + throw ambiguous_local_time(tp, i); return sys_time{tp.time_since_epoch()} - i.first.offset; }