// The MIT License (MIT) // // Copyright (c) 2017 Howard Hinnant // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // template // class zoned_time // { // public: // using duration = typename std::common_type::type; // // zoned_time(); // zoned_time(const sys_time& st); // explicit zoned_time(const time_zone* z); // explicit zoned_time(std::string_view name); // // template , // sys_time>::value // >::type> // zoned_time(const zoned_time& zt) NOEXCEPT; // // zoned_time(const time_zone* z, const local_time& tp); // zoned_time(std::string_view name, const local_time& tp); // zoned_time(const time_zone* z, const local_time& tp, choose c); // zoned_time(std::string_view name, const local_time& tp, choose c); // // zoned_time(const time_zone* z, const zoned_time& zt); // zoned_time(std::string_view name, const zoned_time& zt); // zoned_time(const time_zone* z, const zoned_time& zt, choose); // zoned_time(std::string_view name, const zoned_time& zt, choose); // // zoned_time(const time_zone* z, const sys_time& st); // zoned_time(std::string_view name, const sys_time& st); // // zoned_time& operator=(const sys_time& st); // zoned_time& operator=(const local_time& ut); // // explicit operator sys_time() const; // explicit operator local_time() const; // // const time_zone* get_time_zone() const; // local_time get_local_time() const; // sys_time get_sys_time() const; // sys_info get_info() const; // // template // friend // bool // operator==(const zoned_time& x, const zoned_time& y); // // template // friend // std::basic_ostream& // operator<<(std::basic_ostream& os, const zoned_time& t); // }; // // using zoned_seconds = zoned_time; // // template // inline // bool // operator!=(const zoned_time& x, const zoned_time& y); // // template // zoned_time(sys_time) // -> zoned_time>; // // template // zoned_time(Zone, sys_time) // -> zoned_time>; // // template // zoned_time(Zone, local_time, choose = choose::earliest) // -> zoned_time>; // // template // zoned_time(Zone, zoned_time, choose = choose::earliest) // -> zoned_time>; #include "tz.h" #include #include #include int main() { using namespace std; using namespace std::chrono; using namespace date; static_assert( is_nothrow_destructible{}, ""); static_assert( is_default_constructible{}, ""); static_assert( is_nothrow_copy_constructible{}, ""); static_assert( is_nothrow_copy_assignable{}, ""); static_assert( is_nothrow_move_constructible{}, ""); static_assert( is_nothrow_move_assignable{}, ""); static_assert(is_same::duration, seconds>{}, ""); static_assert(is_same{}, ""); static_assert(is_same::duration, milliseconds>{}, ""); // zoned_time(); { zoned_seconds zt; assert(zt.get_sys_time() == sys_seconds{}); assert(zt.get_time_zone()->name() == "Etc/UTC"); } // zoned_time(const sys_time& st); { static_assert(!is_convertible{}, ""); static_assert( is_constructible{}, ""); static_assert( is_convertible{}, ""); static_assert(!is_convertible, zoned_seconds>{}, ""); static_assert(!is_constructible>{}, ""); auto now = floor(system_clock::now()); zoned_seconds zt = now; assert(zt.get_sys_time() == now); assert(zt.get_time_zone()->name() == "Etc/UTC"); } // explicit zoned_time(const time_zone* z); { static_assert(!is_convertible{}, ""); static_assert( is_constructible{}, ""); zoned_seconds zt{locate_zone("America/New_York")}; assert(zt.get_sys_time() == sys_seconds{}); assert(zt.get_time_zone()->name() == "America/New_York"); } // explicit zoned_time(std::string_view name); { static_assert(!is_convertible{}, ""); static_assert( is_constructible{}, ""); static_assert( is_constructible{}, ""); static_assert( is_constructible{}, ""); zoned_seconds zt{"America/New_York"}; assert(zt.get_sys_time() == sys_seconds{}); assert(zt.get_time_zone()->name() == "America/New_York"); } // template , // sys_time>::value // >::type> // zoned_time(const zoned_time& zt) NOEXCEPT; { static_assert( is_convertible, zoned_seconds>{}, ""); static_assert(!is_constructible, zoned_seconds>{}, ""); zoned_time zt1{"America/New_York", sys_days{2017_y/jul/5}}; zoned_seconds zt2 = zt1; assert(zt2.get_sys_time() == sys_days{2017_y/jul/5}); assert(zt2.get_time_zone()->name() == "America/New_York"); } // zoned_time(const time_zone* z, const local_time& tp); { static_assert( is_constructible{}, ""); zoned_seconds zt = {locate_zone("America/New_York"), local_days{2017_y/jul/5}}; assert(zt.get_local_time() == local_days{2017_y/jul/5}); assert(zt.get_time_zone()->name() == "America/New_York"); try { zoned_seconds zt1 = {locate_zone("America/New_York"), local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15}}; assert(false); } catch(const nonexistent_local_time&) { } try { zoned_seconds zt1 = {locate_zone("America/New_York"), local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15}}; assert(false); } catch(const ambiguous_local_time&) { } } // zoned_time(std::string_view name, const local_time& tp); { static_assert( is_constructible{}, ""); static_assert( is_constructible{}, ""); zoned_seconds zt = {"America/New_York", local_days{2017_y/jul/5}}; assert(zt.get_local_time() == local_days{2017_y/jul/5}); assert(zt.get_time_zone()->name() == "America/New_York"); try { zoned_seconds zt1 = {"America/New_York", local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15}}; assert(false); } catch(const nonexistent_local_time&) { } try { zoned_seconds zt1 = {"America/New_York", local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15}}; assert(false); } catch(const ambiguous_local_time&) { } } // zoned_time(const time_zone* z, const local_time& tp, choose c); { static_assert( is_constructible{}, ""); zoned_seconds zt = {locate_zone("America/New_York"), local_days{2017_y/jul/5} + hours{2} + minutes{15}, choose::earliest}; assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{6} + minutes{15}); assert(zt.get_time_zone()->name() == "America/New_York"); zt = {locate_zone("America/New_York"), local_days{2017_y/jul/5} + hours{2} + minutes{15}, choose::latest}; assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{6} + minutes{15}); assert(zt.get_time_zone()->name() == "America/New_York"); static_assert( is_constructible{}, ""); zoned_seconds zt1 = {locate_zone("America/New_York"), local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15}, choose::earliest}; assert(zt1.get_sys_time() == sys_days{2017_y/mar/12} + hours{7}); assert(zt1.get_time_zone()->name() == "America/New_York"); zoned_seconds zt2 = {locate_zone("America/New_York"), local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15}, choose::latest}; assert(zt2.get_sys_time() == sys_days{2017_y/mar/12} + hours{7}); assert(zt2.get_time_zone()->name() == "America/New_York"); zoned_seconds zt3 = {locate_zone("America/New_York"), local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15}, choose::earliest}; assert(zt3.get_sys_time() == sys_days{2017_y/nov/5} + hours{5} + minutes{15}); assert(zt3.get_time_zone()->name() == "America/New_York"); zoned_seconds zt4 = {locate_zone("America/New_York"), local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15}, choose::latest}; assert(zt4.get_sys_time() == sys_days{2017_y/nov/5} + hours{6} + minutes{15}); assert(zt4.get_time_zone()->name() == "America/New_York"); } // zoned_time(std::string_view name, const local_time& tp, choose c); { static_assert( is_constructible{}, ""); static_assert( is_constructible{}, ""); zoned_seconds zt = {"America/New_York", local_days{2017_y/jul/5} + hours{2} + minutes{15}, choose::earliest}; assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{6} + minutes{15}); assert(zt.get_time_zone()->name() == "America/New_York"); zt = {"America/New_York", local_days{2017_y/jul/5} + hours{2} + minutes{15}, choose::latest}; assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{6} + minutes{15}); assert(zt.get_time_zone()->name() == "America/New_York"); static_assert( is_constructible{}, ""); zoned_seconds zt1 = {"America/New_York", local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15}, choose::earliest}; assert(zt1.get_sys_time() == sys_days{2017_y/mar/12} + hours{7}); assert(zt1.get_time_zone()->name() == "America/New_York"); zoned_seconds zt2 = {"America/New_York", local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15}, choose::latest}; assert(zt2.get_sys_time() == sys_days{2017_y/mar/12} + hours{7}); assert(zt2.get_time_zone()->name() == "America/New_York"); zoned_seconds zt3 = {"America/New_York", local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15}, choose::earliest}; assert(zt3.get_sys_time() == sys_days{2017_y/nov/5} + hours{5} + minutes{15}); assert(zt3.get_time_zone()->name() == "America/New_York"); zoned_seconds zt4 = {"America/New_York", local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15}, choose::latest}; assert(zt4.get_sys_time() == sys_days{2017_y/nov/5} + hours{6} + minutes{15}); assert(zt4.get_time_zone()->name() == "America/New_York"); } // zoned_time(const time_zone* z, const sys_time& st); { static_assert( is_constructible{}, ""); zoned_seconds zt = {locate_zone("America/New_York"), sys_days{2017_y/jul/5} + hours{2} + minutes{15}}; assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{2} + minutes{15}); assert(zt.get_time_zone()->name() == "America/New_York"); } // zoned_time(std::string_view name, const sys_time& st); { static_assert( is_constructible{}, ""); static_assert( is_constructible{}, ""); zoned_seconds zt = {"America/New_York", sys_days{2017_y/jul/5} + hours{2} + minutes{15}}; assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{2} + minutes{15}); assert(zt.get_time_zone()->name() == "America/New_York"); } // zoned_time& operator=(const sys_time& st); { static_assert( is_assignable{}, ""); zoned_seconds zt{"America/New_York"}; zt = sys_days{2017_y/jul/5}; assert(zt.get_sys_time() == sys_days{2017_y/jul/5}); assert(zt.get_time_zone()->name() == "America/New_York"); } // zoned_time& operator=(const local_time& st); { static_assert( is_assignable{}, ""); zoned_seconds zt{"America/New_York"}; zt = local_days{2017_y/jul/5}; assert(zt.get_local_time() == local_days{2017_y/jul/5}); assert(zt.get_time_zone()->name() == "America/New_York"); try { zt = {"America/New_York", local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15}}; assert(false); } catch(const nonexistent_local_time&) { assert(zt.get_local_time() == local_days{2017_y/jul/5}); assert(zt.get_time_zone()->name() == "America/New_York"); } try { zt = {"America/New_York", local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15}}; assert(false); } catch(const ambiguous_local_time&) { assert(zt.get_local_time() == local_days{2017_y/jul/5}); assert(zt.get_time_zone()->name() == "America/New_York"); } } // explicit operator sys_time() const; { static_assert(!is_convertible{}, ""); static_assert( is_constructible{}, ""); auto now = floor(system_clock::now()); const zoned_seconds zt = {"America/New_York", now}; assert(sys_seconds{zt} == now); } // explicit operator local_time() const; { static_assert(!is_convertible{}, ""); static_assert( is_constructible{}, ""); auto now = local_days{2017_y/jul/5} + hours{23} + minutes{1} + seconds{48}; const zoned_seconds zt = {"America/New_York", now}; assert(local_seconds{zt} == now); } // const time_zone* get_time_zone() const; { const zoned_seconds zt{"America/New_York"}; assert(zt.get_time_zone() == locate_zone("America/New_York")); } // local_time get_local_time() const; { const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} + hours{3} + minutes{7} + seconds{9}}; assert(zt.get_local_time() == local_days{2017_y/jul/5} + hours{23} + minutes{7} + seconds{9}); } // sys_time get_sys_time() const; { const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} + hours{3} + minutes{7} + seconds{9}}; assert(zt.get_sys_time() == sys_days{2017_y/jul/6} + hours{3} + minutes{7} + seconds{9}); } // sys_info get_info() const; { const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} + hours{3} + minutes{7} + seconds{9}}; auto info = zt.get_info(); assert(info.begin == sys_days{2017_y/mar/12} + hours{7}); assert(info.end == sys_days{2017_y/nov/5} + hours{6}); assert(info.offset == hours{-4}); assert(info.save != minutes{0}); assert(info.abbrev == "EDT"); } // template // bool // operator==(const zoned_time& x, const zoned_time& y); { const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} + hours{3} + minutes{7} + seconds{9}}; const zoned_seconds zt1{"America/New_York", sys_days{2017_y/jul/6} + hours{3} + minutes{7} + seconds{10}}; assert(zt == zt); assert(!(zt == zt1)); } // template // bool // operator!=(const zoned_time& x, const zoned_time& y); { const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} + hours{3} + minutes{7} + seconds{9}}; const zoned_seconds zt1{"America/New_York", sys_days{2017_y/jul/6} + hours{3} + minutes{7} + seconds{10}}; assert(!(zt != zt)); assert(zt != zt1); } // template // std::basic_ostream& // operator<<(std::basic_ostream& os, const zoned_time& t); { const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} + hours{3} + minutes{7} + seconds{9}}; std::ostringstream test; test << zt; assert(test.str() == "2017-07-05 23:07:09 EDT"); } }