diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv index d4db7876cb2ef9..5051a2089c98e4 100644 --- a/libcxx/docs/Status/Cxx20Issues.csv +++ b/libcxx/docs/Status/Cxx20Issues.csv @@ -162,7 +162,7 @@ "`3209 `__","Expression in ``year::ok()``\ returns clause is ill-formed","Cologne","|Complete|","" "","","","","","" "`3231 `__","``year_month_day_last::day``\ specification does not cover ``!ok()``\ values","Belfast","|Nothing To Do|","" -"`3225 `__","``zoned_time``\ converting constructor shall not be ``noexcept``\ ","Belfast","","","|chrono|" +"`3225 `__","``zoned_time``\ converting constructor shall not be ``noexcept``\ ","Belfast","|Complete|","19.0","|chrono|" "`3190 `__","``std::allocator::allocate``\ sometimes returns too little storage","Belfast","|Complete|","14.0" "`3218 `__","Modifier for ``%d``\ parse flag does not match POSIX and ``format``\ specification","Belfast","","","|chrono| |format|" "`3224 `__","``zoned_time``\ constructor from ``TimeZonePtr``\ does not specify initialization of ``tp_``\ ","Belfast","|Complete|","19.0","|chrono|" @@ -199,7 +199,7 @@ "`3194 `__","``ConvertibleTo``\ prose does not match code","Prague","|Complete|","13.0" "`3200 `__","``midpoint``\ should not constrain ``T``\ is complete","Prague","|Nothing To Do|","" "`3201 `__","``lerp``\ should be marked as ``noexcept``\ ","Prague","|Complete|","" -"`3226 `__","``zoned_time``\ constructor from ``string_view``\ should accept ``zoned_time``\ ","Prague","","","|chrono|" +"`3226 `__","``zoned_time``\ constructor from ``string_view``\ should accept ``zoned_time``\ ","Prague","|Complete|","19.0","|chrono|" "`3233 `__","Broken requirements for ``shared_ptr``\ converting constructors","Prague","|Complete|","19.0" "`3237 `__","LWG 3038 and 3190 have inconsistent PRs","Prague","|Complete|","16.0" "`3238 `__","Insufficiently-defined behavior of ``std::function``\ deduction guides","Prague","|Nothing To Do|","" diff --git a/libcxx/include/__chrono/zoned_time.h b/libcxx/include/__chrono/zoned_time.h index f7510c9121a594..bf8e04b6407ef9 100644 --- a/libcxx/include/__chrono/zoned_time.h +++ b/libcxx/include/__chrono/zoned_time.h @@ -16,6 +16,7 @@ // Enable the contents of the header only when libc++ was built with experimental features enabled. #if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) +# include <__chrono/calendar.h> # include <__chrono/duration.h> # include <__chrono/system_clock.h> # include <__chrono/time_zone.h> @@ -56,6 +57,10 @@ class zoned_time { static_assert(__is_duration<_Duration>::value, "the program is ill-formed since _Duration is not a specialization of std::chrono::duration"); + // There are several constraints like + // constructible_from + // This would create a dependency on itself. Instead depend on the fact an + // constructor overload taking a _TimeZonePtr is present. using __traits = zoned_traits<_TimeZonePtr>; public: @@ -76,12 +81,71 @@ class zoned_time { _LIBCPP_HIDE_FROM_ABI explicit zoned_time(string_view __name) requires(requires { __traits::locate_zone(string_view{}); } && - // constructible_from - // would create a dependency on itself. Instead depend on the fact - // a constructor taking a _TimeZonePtr exists. constructible_from<_TimeZonePtr, decltype(__traits::locate_zone(string_view{}))>) : __zone_{__traits::locate_zone(__name)}, __tp_{} {} + template + _LIBCPP_HIDE_FROM_ABI zoned_time(const zoned_time<_Duration2, _TimeZonePtr>& __zt) + requires is_convertible_v, sys_time<_Duration>> + : __zone_{__zt.get_time_zone()}, __tp_{__zt.get_sys_time()} {} + + _LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const sys_time<_Duration>& __tp) + : __zone_{std::move(__zone)}, __tp_{__tp} {} + + _LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const sys_time<_Duration>& __tp) + requires requires { _TimeZonePtr{__traits::locate_zone(string_view{})}; } + : zoned_time{__traits::locate_zone(__name), __tp} {} + + _LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const local_time<_Duration>& __tp) + requires(is_convertible_v() -> to_sys(local_time<_Duration>{})), + sys_time>) + : __zone_{std::move(__zone)}, __tp_{__zone_->to_sys(__tp)} {} + + _LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const local_time<_Duration>& __tp) + requires(requires { + _TimeZonePtr{__traits::locate_zone(string_view{})}; + } && is_convertible_v() -> to_sys(local_time<_Duration>{})), + sys_time>) + : zoned_time{__traits::locate_zone(__name), __tp} {} + + _LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const local_time<_Duration>& __tp, choose __c) + requires(is_convertible_v< + decltype(std::declval<_TimeZonePtr&>() -> to_sys(local_time<_Duration>{}, choose::earliest)), + sys_time>) + : __zone_{std::move(__zone)}, __tp_{__zone_->to_sys(__tp, __c)} {} + + _LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const local_time<_Duration>& __tp, choose __c) + requires(requires { + _TimeZonePtr{__traits::locate_zone(string_view{})}; + } && is_convertible_v() -> to_sys(local_time<_Duration>{}, choose::earliest)), + sys_time>) + : zoned_time{__traits::locate_zone(__name), __tp, __c} {} + + template + _LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const zoned_time<_Duration2, _TimeZonePtr2>& __zt) + requires is_convertible_v, sys_time<_Duration>> + : __zone_{std::move(__zone)}, __tp_{__zt.get_sys_time()} {} + + // per wording choose has no effect + template + _LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const zoned_time<_Duration2, _TimeZonePtr2>& __zt, choose) + requires is_convertible_v, sys_time<_Duration>> + : __zone_{std::move(__zone)}, __tp_{__zt.get_sys_time()} {} + + template + _LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const zoned_time<_Duration2, _TimeZonePtr2>& __zt) + requires(requires { + _TimeZonePtr{__traits::locate_zone(string_view{})}; + } && is_convertible_v, sys_time<_Duration>>) + : zoned_time{__traits::locate_zone(__name), __zt} {} + + template + _LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const zoned_time<_Duration2, _TimeZonePtr2>& __zt, choose __c) + requires(requires { + _TimeZonePtr{__traits::locate_zone(string_view{})}; + } && is_convertible_v, sys_time<_Duration>>) + : zoned_time{__traits::locate_zone(__name), __zt, __c} {} + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _TimeZonePtr get_time_zone() const { return __zone_; } [[nodiscard]] _LIBCPP_HIDE_FROM_ABI sys_time get_sys_time() const { return __tp_; } diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_local_time.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_local_time.pass.cpp new file mode 100644 index 00000000000000..ff3b3af697fb25 --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_local_time.pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-filesystem, no-localization, no-tzdb + +// XFAIL: libcpp-has-no-experimental-tzdb +// XFAIL: availability-tzdb-missing + +// + +// template +// class zoned_time; +// +// zoned_time(string_view name, const local_time& st); + +#include +#include + +#include "test_offset_time_zone.h" + +// Verify the results of the constructed object. +int main(int, char**) { + { + using ptr = const std::chrono::time_zone*; + static_assert(std::constructible_from, + std::string_view, + std::chrono::sys_seconds>); + + std::chrono::zoned_time zt{"Etc/GMT+1", std::chrono::local_seconds{std::chrono::seconds{0}}}; + + assert(zt.get_time_zone() == std::chrono::locate_zone("Etc/GMT+1")); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::hours{1}}); + } + + { + using ptr = offset_time_zone; + static_assert(!std::constructible_from, + std::string_view, + std::chrono::local_seconds>); + } + + { + using ptr = offset_time_zone; + static_assert(!std::constructible_from, + std::string_view, + std::chrono::local_seconds>); + } + + { + using ptr = offset_time_zone; + static_assert(std::constructible_from, + std::string_view, + std::chrono::local_seconds>); + + ptr tz; + std::chrono::zoned_time zt{"42", std::chrono::local_seconds{std::chrono::seconds{99}}}; + + assert(zt.get_time_zone().offset() == std::chrono::seconds{42}); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{141}}); + } + + { + using ptr = offset_time_zone; + static_assert(std::constructible_from, + std::string_view, + std::chrono::local_seconds>); + + ptr tz; + std::chrono::zoned_time zt{"42", std::chrono::local_seconds{std::chrono::seconds{99}}}; + + assert(zt.get_time_zone().offset() == std::chrono::seconds{42}); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{141}}); + } + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_local_time_choose.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_local_time_choose.pass.cpp new file mode 100644 index 00000000000000..85be5bd0028b8a --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_local_time_choose.pass.cpp @@ -0,0 +1,105 @@ +//===----------------------------------------------------------------------===/ +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-filesystem, no-localization, no-tzdb + +// XFAIL: libcpp-has-no-experimental-tzdb +// XFAIL: availability-tzdb-missing + +// + +// template +// class zoned_time; +// +// zoned_time(string_view name, const local_time& st, choose c); + +#include +#include +#include + +#include "test_offset_time_zone.h" + +int main(int, char**) { + // Tests unique conversions. To make sure the test is does not depend on changes + // in the database it uses a time zone with a fixed offset. + { + std::chrono::zoned_time zt{ + "Etc/GMT+1", std::chrono::local_seconds{std::chrono::seconds{0}}, std::chrono::choose::earliest}; + + assert(zt.get_time_zone() == std::chrono::locate_zone("Etc/GMT+1")); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::hours{1}}); + } + + // Tests ambiguous conversions. + { + // Z Europe/Berlin 0:53:28 - LMT 1893 Ap + // ... + // 1 DE CE%sT 1980 + // 1 E CE%sT + // + // ... + // R E 1981 ma - Mar lastSu 1u 1 S + // R E 1996 ma - O lastSu 1u 0 - + + using namespace std::literals::chrono_literals; + { + std::chrono::zoned_time zt{ + "Europe/Berlin", + std::chrono::local_seconds{ + (std::chrono::sys_days{std::chrono::September / 28 / 1986} + 2h + 30min).time_since_epoch()}, + std::chrono::choose::earliest}; + + assert(zt.get_time_zone() == std::chrono::locate_zone("Europe/Berlin")); + assert(zt.get_sys_time() == std::chrono::sys_days{std::chrono::September / 28 / 1986} + 0h + 30min); + } + { + std::chrono::zoned_time zt{ + "Europe/Berlin", + std::chrono::local_seconds{ + (std::chrono::sys_days{std::chrono::September / 28 / 1986} + 2h + 30min).time_since_epoch()}, + std::chrono::choose::latest}; + + assert(zt.get_time_zone() == std::chrono::locate_zone("Europe/Berlin")); + assert(zt.get_sys_time() == std::chrono::sys_days{std::chrono::September / 28 / 1986} + 1h + 30min); + } + } + + static_assert(std::constructible_from, + std::string_view, + std::chrono::local_seconds, + std::chrono::choose>); + + static_assert(!std::constructible_from< + std::chrono::zoned_time>, + std::string_view, + std::chrono::local_seconds, + std::chrono::choose>); + + static_assert( + !std::constructible_from< + std::chrono::zoned_time>, + std::string_view, + std::chrono::local_seconds, + std::chrono::choose>); + + static_assert( + !std::constructible_from< + std::chrono::zoned_time>, + std::string_view, + std::chrono::local_seconds, + std::chrono::choose>); + + static_assert(!std::constructible_from< + std::chrono::zoned_time>, + std::string_view, + std::chrono::local_seconds, + std::chrono::choose>); + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_sys_time.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_sys_time.pass.cpp new file mode 100644 index 00000000000000..5f29b5a83e10d5 --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_sys_time.pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-filesystem, no-localization, no-tzdb + +// XFAIL: libcpp-has-no-experimental-tzdb +// XFAIL: availability-tzdb-missing + +// + +// template +// class zoned_time; +// +// zoned_time(string_view name, const sys_time& st); + +#include +#include + +#include "test_offset_time_zone.h" + +// Verify the results of the constructed object. +int main(int, char**) { + { + using ptr = const std::chrono::time_zone*; + static_assert(std::constructible_from, + std::string_view, + std::chrono::sys_seconds>); + + std::chrono::zoned_time zt{"UTC", std::chrono::sys_seconds{std::chrono::seconds{99}}}; + + assert(zt.get_time_zone() == std::chrono::locate_zone("UTC")); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{99}}); + } + + { + using ptr = offset_time_zone; + static_assert(!std::constructible_from, + std::string_view, + std::chrono::sys_seconds>); + } + + { + using ptr = offset_time_zone; + static_assert(!std::constructible_from, + std::string_view, + std::chrono::sys_seconds>); + } + + { + using ptr = offset_time_zone; + static_assert(std::constructible_from, + std::string_view, + std::chrono::sys_seconds>); + + ptr tz; + std::chrono::zoned_time zt{"42", std::chrono::sys_seconds{std::chrono::seconds{99}}}; + + assert(zt.get_time_zone().offset() == std::chrono::seconds{42}); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{99}}); + } + + { + using ptr = offset_time_zone; + static_assert(std::constructible_from, + std::string_view, + std::chrono::sys_seconds>); + + ptr tz; + std::chrono::zoned_time zt{"42", std::chrono::sys_seconds{std::chrono::seconds{99}}}; + + assert(zt.get_time_zone().offset() == std::chrono::seconds{42}); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{99}}); + } + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_zoned_time_duration2_time_zone_ptr2.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_zoned_time_duration2_time_zone_ptr2.pass.cpp new file mode 100644 index 00000000000000..42f7ce0b7d26dd --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_zoned_time_duration2_time_zone_ptr2.pass.cpp @@ -0,0 +1,174 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-filesystem, no-localization, no-tzdb + +// XFAIL: libcpp-has-no-experimental-tzdb +// XFAIL: availability-tzdb-missing + +// + +// template +// class zoned_time; + +// template +// zoned_time(string_view name, const zoned_time& y); + +#include +#include +#include + +#include "test_offset_time_zone.h" + +template <> +struct std::chrono::zoned_traits { + static int default_zone() { return 0; } +}; + +static void test_duration_conversion() { + using ptr = const std::chrono::time_zone*; + ptr tz = std::chrono::locate_zone("UTC"); + + // is_convertible_v, sys_time> is true. + { + using duration = std::chrono::microseconds; + using time_point = std::chrono::sys_time; + std::chrono::zoned_time zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time; + static_assert(std::constructible_from, + std::string_view, + std::chrono::zoned_time>); + std::chrono::zoned_time zt2{"UTC", zt}; + + assert(zt2.get_time_zone() == tz); + assert(zt2.get_sys_time() == time_point2{duration2{42'000}}); + } + { + using duration = std::chrono::milliseconds; + using time_point = std::chrono::sys_time; + std::chrono::zoned_time zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time; + static_assert(std::constructible_from, + std::string_view, + std::chrono::zoned_time>); + std::chrono::zoned_time zt2{"UTC", zt}; + + assert(zt2.get_time_zone() == tz); + assert(zt2.get_sys_time() == time_point2{duration2{42'000'000}}); + } + { + using duration = std::chrono::seconds; + using time_point = std::chrono::sys_time; + std::chrono::zoned_time zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time; + static_assert(std::constructible_from, + std::string_view, + std::chrono::zoned_time>); + std::chrono::zoned_time zt2{"UTC", zt}; + + assert(zt2.get_time_zone() == tz); + assert(zt2.get_sys_time() == time_point2{duration2{42'000'000'000}}); + } + // is_convertible_v, sys_time> is false. + { + using duration = std::chrono::milliseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from, + std::string_view, + std::chrono::zoned_time>); + } + { + using duration = std::chrono::microseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from, + std::string_view, + std::chrono::zoned_time>); + } + { + using duration = std::chrono::nanoseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from, + std::string_view, + std::chrono::zoned_time>); + } +} + +static void test_locate_zone() { + using duration = std::chrono::microseconds; + using time_point = std::chrono::sys_time; + std::chrono::zoned_time zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time; + + { + using ptr = const std::chrono::time_zone*; + static_assert(std::constructible_from, + std::string_view, + std::chrono::zoned_time>); + ptr tz = std::chrono::locate_zone("UTC"); + std::chrono::zoned_time zt2{"UTC", zt}; + + assert(zt2.get_time_zone() == tz); + assert(zt2.get_sys_time() == time_point2{duration2{42'000}}); + } + + { + using ptr = offset_time_zone; + static_assert(!std::constructible_from, + std::string_view, + std::chrono::zoned_time>); + } + { + using ptr = offset_time_zone; + static_assert(!std::constructible_from, + std::string_view, + std::chrono::zoned_time>); + } + { + using ptr = offset_time_zone; + static_assert(std::constructible_from, + std::string_view, + std::chrono::zoned_time>); + + ptr tz; + std::chrono::zoned_time zt2{"99", zt}; + + assert(zt2.get_time_zone().offset() == std::chrono::seconds{99}); + assert(zt2.get_sys_time() == time_point2{duration2{42'000}}); + } + { + using ptr = offset_time_zone; + static_assert(std::constructible_from, + std::string_view, + std::chrono::zoned_time>); + + ptr tz; + std::chrono::zoned_time zt2{"99", zt}; + + assert(zt2.get_time_zone().offset() == std::chrono::seconds{99}); + assert(zt2.get_sys_time() == time_point2{duration2{42'000}}); + } +} + +int main(int, char**) { + test_duration_conversion(); + test_locate_zone(); + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_zoned_time_duration2_time_zone_ptr2_choose.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_zoned_time_duration2_time_zone_ptr2_choose.pass.cpp new file mode 100644 index 00000000000000..1cec9e8e95d976 --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_zoned_time_duration2_time_zone_ptr2_choose.pass.cpp @@ -0,0 +1,185 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-filesystem, no-localization, no-tzdb + +// XFAIL: libcpp-has-no-experimental-tzdb +// XFAIL: availability-tzdb-missing + +// + +// template +// class zoned_time; + +// template +// zoned_time(string_view name, const zoned_time& y, choose c); + +#include +#include +#include + +#include "test_offset_time_zone.h" + +template <> +struct std::chrono::zoned_traits { + static int default_zone() { return 0; } +}; + +static void test_duration_conversion() { + using ptr = const std::chrono::time_zone*; + ptr tz = std::chrono::locate_zone("UTC"); + + // is_convertible_v, sys_time> is true. + { + using duration = std::chrono::microseconds; + using time_point = std::chrono::sys_time; + std::chrono::zoned_time zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time; + static_assert(std::constructible_from, + std::string_view, + std::chrono::zoned_time, + std::chrono::choose>); + std::chrono::zoned_time zt2{"UTC", zt, std::chrono::choose::earliest}; + + assert(zt2.get_time_zone() == tz); + assert(zt2.get_sys_time() == time_point2{duration2{42'000}}); + } + { + using duration = std::chrono::milliseconds; + using time_point = std::chrono::sys_time; + std::chrono::zoned_time zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time; + static_assert(std::constructible_from, + std::string_view, + std::chrono::zoned_time, + std::chrono::choose>); + std::chrono::zoned_time zt2{"UTC", zt, std::chrono::choose::earliest}; + + assert(zt2.get_time_zone() == tz); + assert(zt2.get_sys_time() == time_point2{duration2{42'000'000}}); + } + { + using duration = std::chrono::seconds; + using time_point = std::chrono::sys_time; + std::chrono::zoned_time zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time; + static_assert(std::constructible_from, + std::string_view, + std::chrono::zoned_time, + std::chrono::choose>); + std::chrono::zoned_time zt2{"UTC", zt, std::chrono::choose::earliest}; + + assert(zt2.get_time_zone() == tz); + assert(zt2.get_sys_time() == time_point2{duration2{42'000'000'000}}); + } + // is_convertible_v, sys_time> is false. + { + using duration = std::chrono::milliseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from, + std::string_view, + std::chrono::zoned_time, + std::chrono::choose>); + } + { + using duration = std::chrono::microseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from, + std::string_view, + std::chrono::zoned_time, + std::chrono::choose>); + } + { + using duration = std::chrono::nanoseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from, + std::string_view, + std::chrono::zoned_time, + std::chrono::choose>); + } +} + +static void test_locate_zone() { + using duration = std::chrono::microseconds; + using time_point = std::chrono::sys_time; + std::chrono::zoned_time zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time; + + { + using ptr = const std::chrono::time_zone*; + static_assert(std::constructible_from, + std::string_view, + std::chrono::zoned_time, + std::chrono::choose>); + ptr tz = std::chrono::locate_zone("UTC"); + std::chrono::zoned_time zt2{"UTC", zt, std::chrono::choose::earliest}; + + assert(zt2.get_time_zone() == tz); + assert(zt2.get_sys_time() == time_point2{duration2{42'000}}); + } + + { + using ptr = offset_time_zone; + static_assert(!std::constructible_from, + std::string_view, + std::chrono::zoned_time, + std::chrono::choose>); + } + { + using ptr = offset_time_zone; + static_assert(!std::constructible_from, + std::string_view, + std::chrono::zoned_time, + std::chrono::choose>); + } + { + using ptr = offset_time_zone; + static_assert(std::constructible_from, + std::string_view, + std::chrono::zoned_time, + std::chrono::choose>); + + ptr tz; + std::chrono::zoned_time zt2{"99", zt, std::chrono::choose::earliest}; + + assert(zt2.get_time_zone().offset() == std::chrono::seconds{99}); + assert(zt2.get_sys_time() == time_point2{duration2{42'000}}); + } + { + using ptr = offset_time_zone; + static_assert(std::constructible_from, + std::string_view, + std::chrono::zoned_time, + std::chrono::choose>); + + ptr tz; + std::chrono::zoned_time zt2{"99", zt, std::chrono::choose::earliest}; + + assert(zt2.get_time_zone().offset() == std::chrono::seconds{99}); + assert(zt2.get_sys_time() == time_point2{duration2{42'000}}); + } +} + +int main(int, char**) { + test_duration_conversion(); + test_locate_zone(); + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_pointer_local_time.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_pointer_local_time.pass.cpp new file mode 100644 index 00000000000000..58bf04ee025783 --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_pointer_local_time.pass.cpp @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-filesystem, no-localization, no-tzdb + +// XFAIL: libcpp-has-no-experimental-tzdb +// XFAIL: availability-tzdb-missing + +// + +// template +// class zoned_time; +// +// zoned_time(TimeZonePtr z, const local_time& st); + +#include +#include +#include + +#include "test_offset_time_zone.h" + +int main(int, char**) { + { + using ptr = const std::chrono::time_zone*; + ptr tz = std::chrono::locate_zone("Etc/GMT+1"); + std::chrono::zoned_time zt{tz, std::chrono::local_seconds{std::chrono::seconds{0}}}; + + assert(zt.get_time_zone() == tz); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::hours{1}}); + } + { + using ptr = offset_time_zone; + ptr tz{"60"}; + std::chrono::zoned_time zt{tz, std::chrono::local_seconds{std::chrono::seconds{42}}}; + + assert(zt.get_time_zone().offset() == tz.offset()); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{102}}); + } + { + using ptr = offset_time_zone; + static_assert(std::constructible_from, ptr>); + static_assert(!std::convertible_to>); + + ptr tz{"60"}; + std::chrono::zoned_time zt{tz, std::chrono::local_seconds{std::chrono::seconds{42}}}; + + assert(zt.get_time_zone().offset() == tz.offset()); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{102}}); + } + { + using ptr = offset_time_zone; + static_assert(std::constructible_from, ptr>); + static_assert(!std::convertible_to>); + + ptr tz{"60"}; + std::chrono::zoned_time zt{tz, std::chrono::local_seconds{std::chrono::seconds{42}}}; + + assert(zt.get_time_zone().offset() == tz.offset()); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{102}}); + } + { + using ptr = offset_time_zone; + static_assert(std::constructible_from, ptr>); + static_assert(!std::convertible_to>); + + ptr tz{"60"}; + std::chrono::zoned_time zt{tz, std::chrono::local_seconds{std::chrono::seconds{42}}}; + + assert(zt.get_time_zone().offset() == tz.offset()); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{102}}); + } + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_pointer_local_time_choose.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_pointer_local_time_choose.pass.cpp new file mode 100644 index 00000000000000..7927c6c1260237 --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_pointer_local_time_choose.pass.cpp @@ -0,0 +1,109 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-filesystem, no-localization, no-tzdb + +// XFAIL: libcpp-has-no-experimental-tzdb +// XFAIL: availability-tzdb-missing + +// + +// template +// class zoned_time; +// +// zoned_time(TimeZonePtr z, const local_time& st, choose c); + +#include +#include +#include + +#include "test_offset_time_zone.h" + +int main(int, char**) { + // Tests unique conversions. To make sure the test is does not depend on changes + // in the database it uses a time zone with a fixed offset. + { + using ptr = const std::chrono::time_zone*; + ptr tz = std::chrono::locate_zone("Etc/GMT+1"); + std::chrono::zoned_time zt{ + tz, std::chrono::local_seconds{std::chrono::seconds{0}}, std::chrono::choose::earliest}; + + assert(zt.get_time_zone() == tz); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::hours{1}}); + } + + // Tests ambiguous conversions. + { + // Z Europe/Berlin 0:53:28 - LMT 1893 Ap + // ... + // 1 DE CE%sT 1980 + // 1 E CE%sT + // + // ... + // R E 1981 ma - Mar lastSu 1u 1 S + // R E 1996 ma - O lastSu 1u 0 - + + using namespace std::literals::chrono_literals; + using ptr = const std::chrono::time_zone*; + ptr tz = std::chrono::locate_zone("Europe/Berlin"); + { + std::chrono::zoned_time zt{ + tz, + std::chrono::local_seconds{ + (std::chrono::sys_days{std::chrono::September / 28 / 1986} + 2h + 30min).time_since_epoch()}, + std::chrono::choose::earliest}; + + assert(zt.get_time_zone() == tz); + assert(zt.get_sys_time() == std::chrono::sys_days{std::chrono::September / 28 / 1986} + 0h + 30min); + } + { + std::chrono::zoned_time zt{ + tz, + std::chrono::local_seconds{ + (std::chrono::sys_days{std::chrono::September / 28 / 1986} + 2h + 30min).time_since_epoch()}, + std::chrono::choose::latest}; + + assert(zt.get_time_zone() == tz); + assert(zt.get_sys_time() == std::chrono::sys_days{std::chrono::September / 28 / 1986} + 1h + 30min); + } + } + + static_assert(std::constructible_from, + const std::chrono::time_zone*, + std::chrono::local_seconds, + std::chrono::choose>); + + static_assert(!std::constructible_from< + std::chrono::zoned_time>, + offset_time_zone, + std::chrono::local_seconds, + std::chrono::choose>); + + static_assert( + !std::constructible_from< + std::chrono::zoned_time>, + offset_time_zone, + std::chrono::local_seconds, + std::chrono::choose>); + + static_assert( + !std::constructible_from< + std::chrono::zoned_time>, + offset_time_zone, + std::chrono::local_seconds, + std::chrono::choose>); + + static_assert(!std::constructible_from< + std::chrono::zoned_time>, + offset_time_zone, + std::chrono::local_seconds, + std::chrono::choose>); + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_pointer_sys_time.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_pointer_sys_time.pass.cpp new file mode 100644 index 00000000000000..9a84d933056797 --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_pointer_sys_time.pass.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-filesystem, no-localization, no-tzdb + +// XFAIL: libcpp-has-no-experimental-tzdb +// XFAIL: availability-tzdb-missing + +// + +// template +// class zoned_time; +// +// zoned_time(TimeZonePtr z, const sys_time& st); + +#include +#include +#include + +#include "test_offset_time_zone.h" + +int main(int, char**) { + { + using ptr = const std::chrono::time_zone*; + static_assert(std::constructible_from, ptr>); + static_assert(!std::convertible_to>); + + ptr tz = std::chrono::locate_zone("UTC"); + std::chrono::zoned_time zt{tz, std::chrono::sys_seconds{std::chrono::seconds{42}}}; + + assert(zt.get_time_zone() == tz); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{42}}); + } + { + using ptr = offset_time_zone; + static_assert(std::constructible_from, ptr>); + static_assert(!std::convertible_to>); + + ptr tz; + std::chrono::zoned_time zt{tz, std::chrono::sys_seconds{std::chrono::seconds{42}}}; + + assert(zt.get_time_zone().offset() == tz.offset()); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{42}}); + } + { + using ptr = offset_time_zone; + static_assert(std::constructible_from, ptr>); + static_assert(!std::convertible_to>); + + ptr tz; + std::chrono::zoned_time zt{tz, std::chrono::sys_seconds{std::chrono::seconds{42}}}; + + assert(zt.get_time_zone().offset() == tz.offset()); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{42}}); + } + { + using ptr = offset_time_zone; + static_assert(std::constructible_from, ptr>); + static_assert(!std::convertible_to>); + + ptr tz; + std::chrono::zoned_time zt{tz, std::chrono::sys_seconds{std::chrono::seconds{42}}}; + + assert(zt.get_time_zone().offset() == tz.offset()); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{42}}); + } + { + using ptr = offset_time_zone; + static_assert(std::constructible_from, ptr>); + static_assert(!std::convertible_to>); + + ptr tz; + std::chrono::zoned_time zt{tz, std::chrono::sys_seconds{std::chrono::seconds{42}}}; + + assert(zt.get_time_zone().offset() == tz.offset()); + assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{42}}); + } + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_ptr_zoned_time_duration2_time_zone_ptr2.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_ptr_zoned_time_duration2_time_zone_ptr2.pass.cpp new file mode 100644 index 00000000000000..adaec5d18b5e7e --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_ptr_zoned_time_duration2_time_zone_ptr2.pass.cpp @@ -0,0 +1,109 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-filesystem, no-localization, no-tzdb + +// XFAIL: libcpp-has-no-experimental-tzdb +// XFAIL: availability-tzdb-missing + +// + +// template +// class zoned_time; + +// template +// zoned_time(TimeZonePtr z, const zoned_time& y); + +#include +#include +#include + +template <> +struct std::chrono::zoned_traits { + static int default_zone() { return 0; } +}; + +int main(int, char**) { + using ptr = const std::chrono::time_zone*; + ptr tz = std::chrono::locate_zone("UTC"); + + // is_convertible_v, sys_time> is true. + { + using duration = std::chrono::microseconds; + using time_point = std::chrono::sys_time; + std::chrono::zoned_time zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time; + static_assert(std::constructible_from, + const std::chrono::time_zone*, + std::chrono::zoned_time>); + std::chrono::zoned_time zt2{tz, zt}; + + assert(zt2.get_time_zone() == tz); + assert(zt2.get_sys_time() == time_point2{duration2{42'000}}); + } + { + using duration = std::chrono::milliseconds; + using time_point = std::chrono::sys_time; + std::chrono::zoned_time zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time; + static_assert(std::constructible_from, + const std::chrono::time_zone*, + std::chrono::zoned_time>); + std::chrono::zoned_time zt2{tz, zt}; + + assert(zt2.get_time_zone() == tz); + assert(zt2.get_sys_time() == time_point2{duration2{42'000'000}}); + } + { + using duration = std::chrono::seconds; + using time_point = std::chrono::sys_time; + std::chrono::zoned_time zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time; + static_assert(std::constructible_from, + const std::chrono::time_zone*, + std::chrono::zoned_time>); + std::chrono::zoned_time zt2{tz, zt}; + + assert(zt2.get_time_zone() == tz); + assert(zt2.get_sys_time() == time_point2{duration2{42'000'000'000}}); + } + // is_convertible_v, sys_time> is false. + { + using duration = std::chrono::milliseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from, + const std::chrono::time_zone*, + std::chrono::zoned_time>); + } + { + using duration = std::chrono::microseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from, + const std::chrono::time_zone*, + std::chrono::zoned_time>); + } + { + using duration = std::chrono::nanoseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from, + const std::chrono::time_zone*, + std::chrono::zoned_time>); + } + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_ptr_zoned_time_duration2_time_zone_ptr2_choose.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_ptr_zoned_time_duration2_time_zone_ptr2_choose.pass.cpp new file mode 100644 index 00000000000000..9392cb03eb8949 --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_ptr_zoned_time_duration2_time_zone_ptr2_choose.pass.cpp @@ -0,0 +1,115 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-filesystem, no-localization, no-tzdb + +// XFAIL: libcpp-has-no-experimental-tzdb +// XFAIL: availability-tzdb-missing + +// + +// template +// class zoned_time; + +// template +// zoned_time(TimeZonePtr z, const zoned_time& y, choose); + +#include +#include +#include + +template <> +struct std::chrono::zoned_traits { + static int default_zone() { return 0; } +}; + +int main(int, char**) { + using ptr = const std::chrono::time_zone*; + ptr tz = std::chrono::locate_zone("UTC"); + + // is_convertible_v, sys_time> is true. + { + using duration = std::chrono::microseconds; + using time_point = std::chrono::sys_time; + std::chrono::zoned_time zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time; + static_assert(std::constructible_from, + const std::chrono::time_zone*, + std::chrono::zoned_time, + std::chrono::choose>); + std::chrono::zoned_time zt2{tz, zt, std::chrono::choose::earliest}; + + assert(zt2.get_time_zone() == tz); + assert(zt2.get_sys_time() == time_point2{duration2{42'000}}); + } + { + using duration = std::chrono::milliseconds; + using time_point = std::chrono::sys_time; + std::chrono::zoned_time zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time; + static_assert(std::constructible_from, + const std::chrono::time_zone*, + std::chrono::zoned_time, + std::chrono::choose>); + std::chrono::zoned_time zt2{tz, zt, std::chrono::choose::earliest}; + + assert(zt2.get_time_zone() == tz); + assert(zt2.get_sys_time() == time_point2{duration2{42'000'000}}); + } + { + using duration = std::chrono::seconds; + using time_point = std::chrono::sys_time; + std::chrono::zoned_time zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time; + static_assert(std::constructible_from, + const std::chrono::time_zone*, + std::chrono::zoned_time, + std::chrono::choose>); + std::chrono::zoned_time zt2{tz, zt, std::chrono::choose::earliest}; + + assert(zt2.get_time_zone() == tz); + assert(zt2.get_sys_time() == time_point2{duration2{42'000'000'000}}); + } + // is_convertible_v, sys_time> is false. + { + using duration = std::chrono::milliseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from, + const std::chrono::time_zone*, + std::chrono::zoned_time, + std::chrono::choose>); + } + { + using duration = std::chrono::microseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from, + const std::chrono::time_zone*, + std::chrono::zoned_time, + std::chrono::choose>); + } + { + using duration = std::chrono::nanoseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from, + const std::chrono::time_zone*, + std::chrono::zoned_time, + std::chrono::choose>); + } + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/zoned_time_duration2.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/zoned_time_duration2.pass.cpp new file mode 100644 index 00000000000000..b911532b228867 --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/zoned_time_duration2.pass.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-filesystem, no-localization, no-tzdb + +// XFAIL: libcpp-has-no-experimental-tzdb +// XFAIL: availability-tzdb-missing + +// + +// template +// class zoned_time; + +// template +// zoned_time(const zoned_time& y); + +#include +#include +#include + +int main(int, char**) { + // is_convertible_v, sys_time> is true. + { + using duration = std::chrono::microseconds; + using time_point = std::chrono::sys_time; + std::chrono::zoned_time zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time; + static_assert(std::constructible_from, std::chrono::zoned_time>); + std::chrono::zoned_time zt2{zt}; + + assert(zt2.get_sys_time() == time_point2{duration2{42'000}}); + } + { + using duration = std::chrono::milliseconds; + using time_point = std::chrono::sys_time; + std::chrono::zoned_time zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time; + static_assert(std::constructible_from, std::chrono::zoned_time>); + std::chrono::zoned_time zt2{zt}; + + assert(zt2.get_sys_time() == time_point2{duration2{42'000'000}}); + } + { + using duration = std::chrono::seconds; + using time_point = std::chrono::sys_time; + std::chrono::zoned_time zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time; + static_assert(std::constructible_from, std::chrono::zoned_time>); + std::chrono::zoned_time zt2{zt}; + + assert(zt2.get_sys_time() == time_point2{duration2{42'000'000'000}}); + } + // is_convertible_v, sys_time> is false. + { + using duration = std::chrono::milliseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from, std::chrono::zoned_time>); + } + { + using duration = std::chrono::microseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from, std::chrono::zoned_time>); + } + { + using duration = std::chrono::nanoseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from, std::chrono::zoned_time>); + } + + return 0; +} diff --git a/libcxx/test/support/test_offset_time_zone.h b/libcxx/test/support/test_offset_time_zone.h index e1c9f05c2483c0..90b3649fef7c9c 100644 --- a/libcxx/test/support/test_offset_time_zone.h +++ b/libcxx/test/support/test_offset_time_zone.h @@ -14,6 +14,7 @@ #include #include #include +#include enum class offset_time_zone_flags { none = 0, @@ -39,6 +40,15 @@ class offset_time_zone { std::chrono::seconds offset() const { return offset_; } + offset_time_zone* operator->() { return this; } + + template + std::chrono::sys_time> + to_sys(const std::chrono::local_time& local) const { + return std::chrono::sys_time>{ + local.time_since_epoch() + offset_}; + } + private: std::chrono::seconds offset_; };