diff --git a/tz.cpp b/tz.cpp index 04974f5..32032f3 100644 --- a/tz.cpp +++ b/tz.cpp @@ -3346,10 +3346,18 @@ get_tzdb() } const time_zone* +#if HAS_STRING_VIEW +TZ_DB::locate_zone(std::string_view tz_name) const +#else TZ_DB::locate_zone(const std::string& tz_name) const +#endif { auto zi = std::lower_bound(zones.begin(), zones.end(), tz_name, +#if HAS_STRING_VIEW + [](const time_zone& z, const std::string_view& nm) +#else [](const time_zone& z, const std::string& nm) +#endif { return z.name() < nm; }); @@ -3357,7 +3365,11 @@ TZ_DB::locate_zone(const std::string& tz_name) const { #if !USE_OS_TZDB auto li = std::lower_bound(links.begin(), links.end(), tz_name, +#if HAS_STRING_VIEW + [](const link& z, const std::string_view& nm) +#else [](const link& z, const std::string& nm) +#endif { return z.name() < nm; }); @@ -3372,13 +3384,17 @@ TZ_DB::locate_zone(const std::string& tz_name) const return &*zi; } #endif // !USE_OS_TZDB - throw std::runtime_error(tz_name + " not found in timezone database"); + throw std::runtime_error(std::string(tz_name) + " not found in timezone database"); } return &*zi; } const time_zone* +#if HAS_STRING_VIEW +locate_zone(std::string_view tz_name) +#else locate_zone(const std::string& tz_name) +#endif { return get_tzdb().locate_zone(tz_name); } diff --git a/tz.h b/tz.h index f9347d2..6045c53 100644 --- a/tz.h +++ b/tz.h @@ -95,6 +95,14 @@ static_assert(HAS_REMOTE_API == 0 ? AUTO_DOWNLOAD == 0 : true, # endif #endif // HAS_DEDUCTION_GUIDES +#ifndef HAS_STRING_VIEW +# if __cplusplus >= 201703 +# define HAS_STRING_VIEW 1 +# else +# define HAS_STRING_VIEW 0 +# endif +#endif // HAS_STRING_VIEW + #include "date.h" #if defined(_MSC_VER) && (_MSC_VER < 1900) @@ -280,24 +288,34 @@ operator<<(std::basic_ostream& os, const local_info& r) } class time_zone; + +#if HAS_STRING_VIEW +DATE_API const time_zone* locate_zone(std::string_view tz_name); +#else DATE_API const time_zone* locate_zone(const std::string& tz_name); +#endif + DATE_API const time_zone* current_zone(); -template +template class zoned_time { public: using duration = typename std::common_type::type; private: - const time_zone* zone_; + TimeZonePtr zone_; sys_time tp_; public: zoned_time(); zoned_time(const sys_time& st); - explicit zoned_time(const time_zone* z); + explicit zoned_time(TimeZonePtr z); +#if HAS_STRING_VIEW + explicit zoned_time(const std::string_view& name); +#else explicit zoned_time(const std::string& name); +#endif template , sys_time>::value >::type> - zoned_time(const zoned_time& zt) NOEXCEPT; + zoned_time(const zoned_time& zt) NOEXCEPT; - zoned_time(const time_zone* z, const local_time& tp); - zoned_time(const std::string& name, const local_time& tp); - zoned_time(const char* name, const local_time& tp); - zoned_time(const time_zone* z, const local_time& tp, choose c); - zoned_time(const std::string& name, const local_time& tp, choose c); - zoned_time(const char* name, const local_time& tp, choose c); + zoned_time(TimeZonePtr z, const sys_time& st); + zoned_time(TimeZonePtr z, const local_time& tp); + zoned_time(TimeZonePtr z, const local_time& tp, choose c); + zoned_time(TimeZonePtr z, const zoned_time& zt); + zoned_time(TimeZonePtr z, const zoned_time& zt, choose); - zoned_time(const time_zone* z, const zoned_time& zt); - zoned_time(const std::string& name, const zoned_time& zt); - zoned_time(const char* name, const zoned_time& zt); - zoned_time(const time_zone* z, const zoned_time& zt, choose); - zoned_time(const std::string& name, const zoned_time& zt, choose); - zoned_time(const char* name, const zoned_time& zt, choose); - - zoned_time(const time_zone* z, const sys_time& st); +#if HAS_STRING_VIEW + zoned_time(std::string_view name, const sys_time& st); + zoned_time(std::string_view name, const local_time& tp); + zoned_time(std::string_view name, const local_time& tp, choose c); + zoned_time(std::string_view name, const zoned_time& zt); + zoned_time(std::string_view name, const zoned_time& zt, choose); +#else // !HAS_STRING_VIEW zoned_time(const std::string& name, const sys_time& st); zoned_time(const char* name, const sys_time& st); + zoned_time(const std::string& name, const local_time& tp); + zoned_time(const char* name, const local_time& tp); + zoned_time(const std::string& name, const local_time& tp, choose c); + zoned_time(const char* name, const local_time& tp, choose c); + zoned_time(const std::string& name, const zoned_time& zt); + zoned_time(const char* name, const zoned_time& zt); + zoned_time(const std::string& name, const zoned_time& zt, choose); + zoned_time(const char* name, const zoned_time& zt, choose); +#endif // !HAS_STRING_VIEW zoned_time& operator=(const sys_time& st); zoned_time& operator=(const local_time& ut); @@ -331,59 +356,102 @@ public: explicit operator sys_time() const; explicit operator local_time() const; - const time_zone* get_time_zone() const; + TimeZonePtr get_time_zone() const; local_time get_local_time() const; sys_time get_sys_time() const; sys_info get_info() const; - template + template friend bool - operator==(const zoned_time& x, const zoned_time& y); + operator==(const zoned_time& x, + const zoned_time& y); - template + template friend std::basic_ostream& - operator<<(std::basic_ostream& os, const zoned_time& t); + operator<<(std::basic_ostream& os, + const zoned_time& t); private: - template friend class zoned_time; + template friend class zoned_time; }; using zoned_seconds = zoned_time; #if HAS_DEDUCTION_GUIDES +zoned_time() + -> zoned_time; + template zoned_time(sys_time) -> zoned_time>; -template -zoned_time(Zone, sys_time) +template +zoned_time(TimeZonePtr) + -> zoned_time; + +template +zoned_time(TimeZonePtr, sys_time) + -> zoned_time, TimeZonePtr>; + +template +zoned_time(TimeZonePtr, local_time, choose = choose::earliest) + -> zoned_time, TimeZonePtr>; + +#if HAS_STRING_VIEW + +zoned_time(std::string_view) + -> zoned_time; + +template +zoned_time(std::string_view, sys_time) -> zoned_time>; -template -zoned_time(Zone, local_time, choose = choose::earliest) +template +zoned_time(std::string_view, local_time, choose = choose::earliest) -> zoned_time>; -template -zoned_time(Zone, zoned_time, choose = choose::earliest) +#else // !HAS_STRING_VIEW + +zoned_time(std::string) + -> zoned_time; + +template +zoned_time(std::string, sys_time) + -> zoned_time>; + +template +zoned_time(std::string, local_time, choose = choose::earliest) + -> zoned_time>; + +#endif // !HAS_STRING_VIEW + +template +zoned_time(const char*, sys_time) + -> zoned_time>; + +template +zoned_time(const char*, local_time, choose = choose::earliest) -> zoned_time>; #endif // HAS_DEDUCTION_GUIDES -template +template inline bool -operator==(const zoned_time& x, const zoned_time& y) +operator==(const zoned_time& x, + const zoned_time& y) { return x.zone_ == y.zone_ && x.tp_ == y.tp_; } -template +template inline bool -operator!=(const zoned_time& x, const zoned_time& y) +operator!=(const zoned_time& x, + const zoned_time& y) { return !(x == y); } @@ -834,7 +902,11 @@ struct TZ_DB } #endif // defined(_MSC_VER) && (_MSC_VER < 1900) +#if HAS_STRING_VIEW + const time_zone* locate_zone(std::string_view tz_name) const; +#else const time_zone* locate_zone(const std::string& tz_name) const; +#endif const time_zone* current_zone() const; }; @@ -859,209 +931,291 @@ DATE_API bool remote_install(const std::string& version); #endif -DATE_API const time_zone* locate_zone(const std::string& tz_name); -DATE_API const time_zone* current_zone(); - // zoned_time -template +template inline -zoned_time::zoned_time() +zoned_time::zoned_time() : zone_(locate_zone("UTC")) {} -template +template inline -zoned_time::zoned_time(const sys_time& st) +zoned_time::zoned_time(const sys_time& st) : zone_(locate_zone("UTC")) , tp_(st) {} -template +template inline -zoned_time::zoned_time(const time_zone* z) - : zone_(z) +zoned_time::zoned_time(TimeZonePtr z) + : zone_(std::move(z)) {assert(zone_ != nullptr);} -template +#if HAS_DEDUCTION_GUIDES + +template inline -zoned_time::zoned_time(const std::string& name) +zoned_time::zoned_time(const std::string_view& name) : zoned_time(locate_zone(name)) {} -template +#else + +template +inline +zoned_time::zoned_time(const std::string& name) + : zoned_time(locate_zone(name)) + {} + +#endif + +template template inline -zoned_time::zoned_time(const zoned_time& zt) NOEXCEPT +zoned_time::zoned_time(const zoned_time& zt) NOEXCEPT : zone_(zt.zone_) , tp_(zt.tp_) {} -template +template inline -zoned_time::zoned_time(const time_zone* z, const local_time& t) - : zone_(z) +zoned_time::zoned_time(TimeZonePtr z, const local_time& t) + : zone_(std::move(z)) , tp_(z->to_sys(t)) {} -template +#if HAS_STRING_VIEW + +template inline -zoned_time::zoned_time(const std::string& name, const local_time& t) +zoned_time::zoned_time(std::string_view name, const local_time& t) : zoned_time(locate_zone(name), t) {} -template +#else // !HAS_STRING_VIEW + +template inline -zoned_time::zoned_time(const char* name, const local_time& t) +zoned_time::zoned_time(const std::string& name, const local_time& t) : zoned_time(locate_zone(name), t) {} -template +template inline -zoned_time::zoned_time(const time_zone* z, const local_time& t, +zoned_time::zoned_time(const char* name, const local_time& t) + : zoned_time(locate_zone(name), t) + {} + +#endif // HAS_STRING_VIEW + +template +inline +zoned_time::zoned_time(TimeZonePtr z, const local_time& t, choose c) - : zone_(z) + : zone_(std::move(z)) , tp_(z->to_sys(t, c)) {} -template +#if HAS_STRING_VIEW + +template inline -zoned_time::zoned_time(const std::string& name, const local_time& t, +zoned_time::zoned_time(std::string_view name, const local_time& t, choose c) : zoned_time(locate_zone(name), t, c) {} -template +#else // !HAS_STRING_VIEW + +template inline -zoned_time::zoned_time(const char* name, const local_time& t, +zoned_time::zoned_time(const std::string& name, const local_time& t, choose c) : zoned_time(locate_zone(name), t, c) {} -template +template inline -zoned_time::zoned_time(const time_zone* z, const zoned_time& zt) - : zone_(z) +zoned_time::zoned_time(const char* name, const local_time& t, + choose c) + : zoned_time(locate_zone(name), t, c) + {} + +#endif // !HAS_STRING_VIEW + +template +inline +zoned_time::zoned_time(TimeZonePtr z, const zoned_time& zt) + : zone_(std::move(z)) , tp_(zt.tp_) {} -template +#if HAS_STRING_VIEW + +template inline -zoned_time::zoned_time(const std::string& name, const zoned_time& zt) +zoned_time::zoned_time(std::string_view name, + const zoned_time& zt) : zoned_time(locate_zone(name), zt) {} -template +#else // !HAS_STRING_VIEW + +template inline -zoned_time::zoned_time(const char* name, const zoned_time& zt) +zoned_time::zoned_time(const std::string& name, + const zoned_time& zt) : zoned_time(locate_zone(name), zt) {} -template +template inline -zoned_time::zoned_time(const time_zone* z, const zoned_time& zt, choose) - : zoned_time(z, zt) +zoned_time::zoned_time(const char* name, + const zoned_time& zt) + : zoned_time(locate_zone(name), zt) {} -template +#endif // !HAS_STRING_VIEW + +template inline -zoned_time::zoned_time(const std::string& name, - const zoned_time& zt, choose c) +zoned_time::zoned_time(TimeZonePtr z, + const zoned_time& zt, choose) + : zoned_time(std::move(z), zt) + {} + +#if HAS_STRING_VIEW + +template +inline +zoned_time::zoned_time(std::string_view name, + const zoned_time& zt, choose c) : zoned_time(locate_zone(name), zt, c) {} -template +#else // !HAS_STRING_VIEW + +template inline -zoned_time::zoned_time(const char* name, - const zoned_time& zt, choose c) +zoned_time::zoned_time(const std::string& name, + const zoned_time& zt, choose c) : zoned_time(locate_zone(name), zt, c) {} -template +template inline -zoned_time::zoned_time(const time_zone* z, const sys_time& st) - : zone_(z) +zoned_time::zoned_time(const char* name, + const zoned_time& zt, choose c) + : zoned_time(locate_zone(name), zt, c) + {} + +#endif // !HAS_STRING_VIEW + +template +inline +zoned_time::zoned_time(TimeZonePtr z, const sys_time& st) + : zone_(std::move(z)) , tp_(st) {} -template +#if HAS_STRING_VIEW + +template inline -zoned_time::zoned_time(const std::string& name, const sys_time& st) +zoned_time::zoned_time(std::string_view name, const sys_time& st) : zoned_time(locate_zone(name), st) {} -template +#else // !HAS_STRING_VIEW + +template inline -zoned_time::zoned_time(const char* name, const sys_time& st) +zoned_time::zoned_time(const std::string& name, const sys_time& st) : zoned_time(locate_zone(name), st) {} -template +template inline -zoned_time& -zoned_time::operator=(const sys_time& st) +zoned_time::zoned_time(const char* name, const sys_time& st) + : zoned_time(locate_zone(name), st) + {} + +#endif // !HAS_STRING_VIEW + +template +inline +zoned_time& +zoned_time::operator=(const sys_time& st) { tp_ = st; return *this; } -template +template inline -zoned_time& -zoned_time::operator=(const local_time& ut) +zoned_time& +zoned_time::operator=(const local_time& ut) { tp_ = zone_->to_sys(ut); return *this; } -template +template inline -zoned_time::operator local_time() const +zoned_time::operator local_time() const { return get_local_time(); } -template +template inline -zoned_time::operator sys_time() const +zoned_time::operator sys_time() const { return get_sys_time(); } -template +template inline -const time_zone* -zoned_time::get_time_zone() const +TimeZonePtr +zoned_time::get_time_zone() const { return zone_; } -template +template inline -local_time::duration> -zoned_time::get_local_time() const +local_time::duration> +zoned_time::get_local_time() const { return zone_->to_local(tp_); } -template +template inline -sys_time::duration> -zoned_time::get_sys_time() const +sys_time::duration> +zoned_time::get_sys_time() const { return tp_; } -template +template inline sys_info -zoned_time::get_info() const +zoned_time::get_info() const { return zone_->get_info(tp_); } // make_zoned_time +inline +zoned_time +make_zoned() +{ + return {}; +} + template inline zoned_time::type> @@ -1070,12 +1224,50 @@ make_zoned(const sys_time& tp) return {tp}; } -template +template ())>::type>{} + >::type + > inline -zoned_time::type> -make_zoned(const time_zone* zone, const local_time& tp) +zoned_time +make_zoned(TimeZonePtr z) { - return {zone, tp}; + return zoned_time{std::move(z)}; +} + +inline +zoned_seconds +make_zoned(const std::string& name) +{ + return zoned_seconds{name}; +} + +template ())>::type>{} + >::type + > +inline +zoned_time::type, TimeZonePtr> +make_zoned(TimeZonePtr zone, const local_time& tp) +{ + return {std::move(zone), tp}; +} + +template ())>::type>{} + >::type + > +inline +zoned_time::type, TimeZonePtr> +make_zoned(TimeZonePtr zone, const local_time& tp, choose c) +{ + return {std::move(zone), tp, c}; } template @@ -1086,14 +1278,6 @@ make_zoned(const std::string& name, const local_time& tp) return {name, tp}; } -template -inline -zoned_time::type> -make_zoned(const time_zone* zone, const local_time& tp, choose c) -{ - return {zone, tp, c}; -} - template inline zoned_time::type> @@ -1102,44 +1286,49 @@ make_zoned(const std::string& name, const local_time& tp, choose c) return {name, tp, c}; } -template +template inline -zoned_time::type> -make_zoned(const time_zone* zone, const zoned_time& zt) +zoned_time +make_zoned(TimeZonePtr zone, const zoned_time& zt) { - return {zone, zt}; + return {std::move(zone), zt}; } -template +template inline -zoned_time::type> -make_zoned(const std::string& name, const zoned_time& zt) +zoned_time +make_zoned(const std::string& name, const zoned_time& zt) { return {name, zt}; } -template +template inline -zoned_time::type> -make_zoned(const time_zone* zone, const zoned_time& zt, choose c) +zoned_time +make_zoned(TimeZonePtr zone, const zoned_time& zt, choose c) { - return {zone, zt, c}; + return {std::move(zone), zt, c}; } -template +template inline -zoned_time::type> -make_zoned(const std::string& name, const zoned_time& zt, choose c) +zoned_time +make_zoned(const std::string& name, const zoned_time& zt, choose c) { return {name, zt, c}; } -template +template ())>::type>{} + >::type + > inline -zoned_time::type> -make_zoned(const time_zone* zone, const sys_time& st) +zoned_time::type, TimeZonePtr> +make_zoned(TimeZonePtr zone, const sys_time& st) { - return {zone, st}; + return {std::move(zone), st}; } template @@ -1150,19 +1339,19 @@ make_zoned(const std::string& name, const sys_time& st) return {name, st}; } -template +template std::basic_ostream& to_stream(std::basic_ostream& os, const CharT* fmt, - const zoned_time& tp) + const zoned_time& tp) { auto const info = tp.get_info(); return to_stream(os, fmt, tp.get_local_time(), &info.abbrev, &info.offset); } -template +template inline std::basic_ostream& -operator<<(std::basic_ostream& os, const zoned_time& t) +operator<<(std::basic_ostream& os, const zoned_time& t) { const CharT fmt[] = {'%', 'F', ' ', '%', 'T', ' ', '%', 'Z', CharT{}}; return to_stream(os, fmt, t);