https://github.com/mordante updated https://github.com/llvm/llvm-project/pull/95010
>From e374d900e2b3524b466013d61b9c3911c862c8fa Mon Sep 17 00:00:00 2001 From: Mark de Wever <ko...@xs4all.nl> Date: Wed, 17 Apr 2024 21:00:22 +0200 Subject: [PATCH] [libc++][TZDB] Finishes zoned_time constructors. Completes - LWG3225 zoned_time converting constructor shall not be noexcept - LWG3226 zoned_time constructor from string_view should accept zoned_time<Duration2, TimeZonePtr2> Implements parts of: - P0355 Extending to chrono Calendars and Time Zones --- libcxx/docs/Status/Cxx20Issues.csv | 4 +- libcxx/include/__chrono/zoned_time.h | 70 ++++++- .../string_view_local_time.pass.cpp | 82 ++++++++ .../string_view_local_time_choose.pass.cpp | 105 ++++++++++ .../string_view_sys_time.pass.cpp | 82 ++++++++ ...ned_time_duration2_time_zone_ptr2.pass.cpp | 174 ++++++++++++++++ ...e_duration2_time_zone_ptr2_choose.pass.cpp | 185 ++++++++++++++++++ .../time_zone_pointer_local_time.pass.cpp | 80 ++++++++ ...me_zone_pointer_local_time_choose.pass.cpp | 109 +++++++++++ .../time_zone_pointer_sys_time.pass.cpp | 86 ++++++++ ...ned_time_duration2_time_zone_ptr2.pass.cpp | 109 +++++++++++ ...e_duration2_time_zone_ptr2_choose.pass.cpp | 115 +++++++++++ .../zoned_time_duration2.pass.cpp | 86 ++++++++ libcxx/test/support/test_offset_time_zone.h | 10 + 14 files changed, 1292 insertions(+), 5 deletions(-) create mode 100644 libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_local_time.pass.cpp create mode 100644 libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_local_time_choose.pass.cpp create mode 100644 libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_sys_time.pass.cpp create mode 100644 libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_zoned_time_duration2_time_zone_ptr2.pass.cpp create mode 100644 libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_zoned_time_duration2_time_zone_ptr2_choose.pass.cpp create mode 100644 libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_pointer_local_time.pass.cpp create mode 100644 libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_pointer_local_time_choose.pass.cpp create mode 100644 libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_pointer_sys_time.pass.cpp create mode 100644 libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_ptr_zoned_time_duration2_time_zone_ptr2.pass.cpp create mode 100644 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 create mode 100644 libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/zoned_time_duration2.pass.cpp diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv index d4db7876cb2ef..5051a2089c98e 100644 --- a/libcxx/docs/Status/Cxx20Issues.csv +++ b/libcxx/docs/Status/Cxx20Issues.csv @@ -162,7 +162,7 @@ "`3209 <https://wg21.link/LWG3209>`__","Expression in ``year::ok()``\ returns clause is ill-formed","Cologne","|Complete|","" "","","","","","" "`3231 <https://wg21.link/LWG3231>`__","``year_month_day_last::day``\ specification does not cover ``!ok()``\ values","Belfast","|Nothing To Do|","" -"`3225 <https://wg21.link/LWG3225>`__","``zoned_time``\ converting constructor shall not be ``noexcept``\ ","Belfast","","","|chrono|" +"`3225 <https://wg21.link/LWG3225>`__","``zoned_time``\ converting constructor shall not be ``noexcept``\ ","Belfast","|Complete|","19.0","|chrono|" "`3190 <https://wg21.link/LWG3190>`__","``std::allocator::allocate``\ sometimes returns too little storage","Belfast","|Complete|","14.0" "`3218 <https://wg21.link/LWG3218>`__","Modifier for ``%d``\ parse flag does not match POSIX and ``format``\ specification","Belfast","","","|chrono| |format|" "`3224 <https://wg21.link/LWG3224>`__","``zoned_time``\ constructor from ``TimeZonePtr``\ does not specify initialization of ``tp_``\ ","Belfast","|Complete|","19.0","|chrono|" @@ -199,7 +199,7 @@ "`3194 <https://wg21.link/LWG3194>`__","``ConvertibleTo``\ prose does not match code","Prague","|Complete|","13.0" "`3200 <https://wg21.link/LWG3200>`__","``midpoint``\ should not constrain ``T``\ is complete","Prague","|Nothing To Do|","" "`3201 <https://wg21.link/LWG3201>`__","``lerp``\ should be marked as ``noexcept``\ ","Prague","|Complete|","" -"`3226 <https://wg21.link/LWG3226>`__","``zoned_time``\ constructor from ``string_view``\ should accept ``zoned_time<Duration2, TimeZonePtr2>``\ ","Prague","","","|chrono|" +"`3226 <https://wg21.link/LWG3226>`__","``zoned_time``\ constructor from ``string_view``\ should accept ``zoned_time<Duration2, TimeZonePtr2>``\ ","Prague","|Complete|","19.0","|chrono|" "`3233 <https://wg21.link/LWG3233>`__","Broken requirements for ``shared_ptr``\ converting constructors","Prague","|Complete|","19.0" "`3237 <https://wg21.link/LWG3237>`__","LWG 3038 and 3190 have inconsistent PRs","Prague","|Complete|","16.0" "`3238 <https://wg21.link/LWG3238>`__","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 f7510c9121a59..bf8e04b6407ef 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<zoned_time, decltype(__traits::locate_zone(string_view{}))> + // 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<zoned_time, decltype(__traits::locate_zone(string_view{}))> - // 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 <class _Duration2> + _LIBCPP_HIDE_FROM_ABI zoned_time(const zoned_time<_Duration2, _TimeZonePtr>& __zt) + requires is_convertible_v<sys_time<_Duration2>, 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<decltype(std::declval<_TimeZonePtr&>() -> to_sys(local_time<_Duration>{})), + sys_time<duration>>) + : __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<decltype(std::declval<_TimeZonePtr&>() -> to_sys(local_time<_Duration>{})), + sys_time<duration>>) + : 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<duration>>) + : __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<decltype(std::declval<_TimeZonePtr&>() -> to_sys(local_time<_Duration>{}, choose::earliest)), + sys_time<duration>>) + : zoned_time{__traits::locate_zone(__name), __tp, __c} {} + + template <class _Duration2, class _TimeZonePtr2> + _LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const zoned_time<_Duration2, _TimeZonePtr2>& __zt) + requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>> + : __zone_{std::move(__zone)}, __tp_{__zt.get_sys_time()} {} + + // per wording choose has no effect + template <class _Duration2, class _TimeZonePtr2> + _LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const zoned_time<_Duration2, _TimeZonePtr2>& __zt, choose) + requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>> + : __zone_{std::move(__zone)}, __tp_{__zt.get_sys_time()} {} + + template <class _Duration2, class _TimeZonePtr2> + _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<_Duration2>, sys_time<_Duration>>) + : zoned_time{__traits::locate_zone(__name), __zt} {} + + template <class _Duration2, class _TimeZonePtr2> + _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<_Duration2>, 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<duration> 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 0000000000000..ff3b3af697fb2 --- /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 + +// <chrono> + +// template<class Duration, class TimeZonePtr = const time_zone*> +// class zoned_time; +// +// zoned_time(string_view name, const local_time<Duration>& st); + +#include <chrono> +#include <concepts> + +#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::chrono::zoned_time<std::chrono::seconds, ptr>, + std::string_view, + std::chrono::sys_seconds>); + + std::chrono::zoned_time<std::chrono::seconds> 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<offset_time_zone_flags::none>; + static_assert(!std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>, + std::string_view, + std::chrono::local_seconds>); + } + + { + using ptr = offset_time_zone<offset_time_zone_flags::has_default_zone>; + static_assert(!std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>, + std::string_view, + std::chrono::local_seconds>); + } + + { + using ptr = offset_time_zone<offset_time_zone_flags::has_locate_zone>; + static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>, + std::string_view, + std::chrono::local_seconds>); + + ptr tz; + std::chrono::zoned_time<std::chrono::seconds, ptr> 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<offset_time_zone_flags::both>; + static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>, + std::string_view, + std::chrono::local_seconds>); + + ptr tz; + std::chrono::zoned_time<std::chrono::seconds, ptr> 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 0000000000000..85be5bd0028b8 --- /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 + +// <chrono> + +// template<class Duration, class TimeZonePtr = const time_zone*> +// class zoned_time; +// +// zoned_time(string_view name, const local_time<Duration>& st, choose c); + +#include <chrono> +#include <concepts> +#include <cassert> + +#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<std::chrono::seconds> 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<std::chrono::seconds> 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<std::chrono::seconds> 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::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>, + std::string_view, + std::chrono::local_seconds, + std::chrono::choose>); + + static_assert(!std::constructible_from< + std::chrono::zoned_time<std::chrono::seconds, offset_time_zone<offset_time_zone_flags::none>>, + std::string_view, + std::chrono::local_seconds, + std::chrono::choose>); + + static_assert( + !std::constructible_from< + std::chrono::zoned_time<std::chrono::seconds, offset_time_zone<offset_time_zone_flags::has_default_zone>>, + std::string_view, + std::chrono::local_seconds, + std::chrono::choose>); + + static_assert( + !std::constructible_from< + std::chrono::zoned_time<std::chrono::seconds, offset_time_zone<offset_time_zone_flags::has_locate_zone>>, + std::string_view, + std::chrono::local_seconds, + std::chrono::choose>); + + static_assert(!std::constructible_from< + std::chrono::zoned_time<std::chrono::seconds, offset_time_zone<offset_time_zone_flags::both>>, + 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 0000000000000..5f29b5a83e10d --- /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 + +// <chrono> + +// template<class Duration, class TimeZonePtr = const time_zone*> +// class zoned_time; +// +// zoned_time(string_view name, const sys_time<Duration>& st); + +#include <chrono> +#include <concepts> + +#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::chrono::zoned_time<std::chrono::seconds, ptr>, + std::string_view, + std::chrono::sys_seconds>); + + std::chrono::zoned_time<std::chrono::seconds> 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<offset_time_zone_flags::none>; + static_assert(!std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>, + std::string_view, + std::chrono::sys_seconds>); + } + + { + using ptr = offset_time_zone<offset_time_zone_flags::has_default_zone>; + static_assert(!std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>, + std::string_view, + std::chrono::sys_seconds>); + } + + { + using ptr = offset_time_zone<offset_time_zone_flags::has_locate_zone>; + static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>, + std::string_view, + std::chrono::sys_seconds>); + + ptr tz; + std::chrono::zoned_time<std::chrono::seconds, ptr> 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<offset_time_zone_flags::both>; + static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>, + std::string_view, + std::chrono::sys_seconds>); + + ptr tz; + std::chrono::zoned_time<std::chrono::seconds, ptr> 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 0000000000000..42f7ce0b7d26d --- /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 + +// <chrono> + +// template<class Duration, class TimeZonePtr = const time_zone*> +// class zoned_time; + +// template<class Duration2, class TimeZonePtr2> +// zoned_time(string_view name, const zoned_time<Duration2, TimeZonePtr2>& y); + +#include <chrono> +#include <concepts> +#include <cassert> + +#include "test_offset_time_zone.h" + +template <> +struct std::chrono::zoned_traits<int> { + 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<Duration2>, sys_time<Duration>> is true. + { + using duration = std::chrono::microseconds; + using time_point = std::chrono::sys_time<duration>; + std::chrono::zoned_time<duration, int> zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time<duration2>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2>, + std::string_view, + std::chrono::zoned_time<duration, int>>); + std::chrono::zoned_time<duration2> 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<duration>; + std::chrono::zoned_time<duration, int> zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time<duration2>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2>, + std::string_view, + std::chrono::zoned_time<duration, int>>); + std::chrono::zoned_time<duration2> 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<duration>; + std::chrono::zoned_time<duration, int> zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time<duration2>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2>, + std::string_view, + std::chrono::zoned_time<duration, int>>); + std::chrono::zoned_time<duration2> 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<Duration2>, sys_time<Duration>> is false. + { + using duration = std::chrono::milliseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2>, + std::string_view, + std::chrono::zoned_time<duration, int>>); + } + { + using duration = std::chrono::microseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2>, + std::string_view, + std::chrono::zoned_time<duration, int>>); + } + { + using duration = std::chrono::nanoseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2>, + std::string_view, + std::chrono::zoned_time<duration, int>>); + } +} + +static void test_locate_zone() { + using duration = std::chrono::microseconds; + using time_point = std::chrono::sys_time<duration>; + std::chrono::zoned_time<duration, int> zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time<duration2>; + + { + using ptr = const std::chrono::time_zone*; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2, ptr>, + std::string_view, + std::chrono::zoned_time<duration, int>>); + ptr tz = std::chrono::locate_zone("UTC"); + std::chrono::zoned_time<duration2, ptr> zt2{"UTC", zt}; + + assert(zt2.get_time_zone() == tz); + assert(zt2.get_sys_time() == time_point2{duration2{42'000}}); + } + + { + using ptr = offset_time_zone<offset_time_zone_flags::none>; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2, ptr>, + std::string_view, + std::chrono::zoned_time<duration, int>>); + } + { + using ptr = offset_time_zone<offset_time_zone_flags::has_default_zone>; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2, ptr>, + std::string_view, + std::chrono::zoned_time<duration, int>>); + } + { + using ptr = offset_time_zone<offset_time_zone_flags::has_locate_zone>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2, ptr>, + std::string_view, + std::chrono::zoned_time<duration, int>>); + + ptr tz; + std::chrono::zoned_time<duration2, ptr> 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<offset_time_zone_flags::both>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2, ptr>, + std::string_view, + std::chrono::zoned_time<duration, int>>); + + ptr tz; + std::chrono::zoned_time<duration2, ptr> 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 0000000000000..1cec9e8e95d97 --- /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 + +// <chrono> + +// template<class Duration, class TimeZonePtr = const time_zone*> +// class zoned_time; + +// template<class Duration2, class TimeZonePtr2> +// zoned_time(string_view name, const zoned_time<Duration2, TimeZonePtr2>& y, choose c); + +#include <chrono> +#include <concepts> +#include <cassert> + +#include "test_offset_time_zone.h" + +template <> +struct std::chrono::zoned_traits<int> { + 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<Duration2>, sys_time<Duration>> is true. + { + using duration = std::chrono::microseconds; + using time_point = std::chrono::sys_time<duration>; + std::chrono::zoned_time<duration, int> zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time<duration2>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2>, + std::string_view, + std::chrono::zoned_time<duration, int>, + std::chrono::choose>); + std::chrono::zoned_time<duration2> 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<duration>; + std::chrono::zoned_time<duration, int> zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time<duration2>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2>, + std::string_view, + std::chrono::zoned_time<duration, int>, + std::chrono::choose>); + std::chrono::zoned_time<duration2> 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<duration>; + std::chrono::zoned_time<duration, int> zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time<duration2>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2>, + std::string_view, + std::chrono::zoned_time<duration, int>, + std::chrono::choose>); + std::chrono::zoned_time<duration2> 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<Duration2>, sys_time<Duration>> is false. + { + using duration = std::chrono::milliseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2>, + std::string_view, + std::chrono::zoned_time<duration, int>, + std::chrono::choose>); + } + { + using duration = std::chrono::microseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2>, + std::string_view, + std::chrono::zoned_time<duration, int>, + std::chrono::choose>); + } + { + using duration = std::chrono::nanoseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2>, + std::string_view, + std::chrono::zoned_time<duration, int>, + std::chrono::choose>); + } +} + +static void test_locate_zone() { + using duration = std::chrono::microseconds; + using time_point = std::chrono::sys_time<duration>; + std::chrono::zoned_time<duration, int> zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time<duration2>; + + { + using ptr = const std::chrono::time_zone*; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2, ptr>, + std::string_view, + std::chrono::zoned_time<duration, int>, + std::chrono::choose>); + ptr tz = std::chrono::locate_zone("UTC"); + std::chrono::zoned_time<duration2, ptr> 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<offset_time_zone_flags::none>; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2, ptr>, + std::string_view, + std::chrono::zoned_time<duration, int>, + std::chrono::choose>); + } + { + using ptr = offset_time_zone<offset_time_zone_flags::has_default_zone>; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2, ptr>, + std::string_view, + std::chrono::zoned_time<duration, int>, + std::chrono::choose>); + } + { + using ptr = offset_time_zone<offset_time_zone_flags::has_locate_zone>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2, ptr>, + std::string_view, + std::chrono::zoned_time<duration, int>, + std::chrono::choose>); + + ptr tz; + std::chrono::zoned_time<duration2, ptr> 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<offset_time_zone_flags::both>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2, ptr>, + std::string_view, + std::chrono::zoned_time<duration, int>, + std::chrono::choose>); + + ptr tz; + std::chrono::zoned_time<duration2, ptr> 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 0000000000000..58bf04ee02578 --- /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 + +// <chrono> + +// template<class Duration, class TimeZonePtr = const time_zone*> +// class zoned_time; +// +// zoned_time(TimeZonePtr z, const local_time<Duration>& st); + +#include <chrono> +#include <concepts> +#include <cassert> + +#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<std::chrono::seconds> 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<offset_time_zone_flags::none>; + ptr tz{"60"}; + std::chrono::zoned_time<std::chrono::seconds, ptr> 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<offset_time_zone_flags::has_default_zone>; + static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>, ptr>); + static_assert(!std::convertible_to<ptr, std::chrono::zoned_time<std::chrono::seconds, ptr>>); + + ptr tz{"60"}; + std::chrono::zoned_time<std::chrono::seconds, ptr> 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<offset_time_zone_flags::has_locate_zone>; + static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>, ptr>); + static_assert(!std::convertible_to<ptr, std::chrono::zoned_time<std::chrono::seconds, ptr>>); + + ptr tz{"60"}; + std::chrono::zoned_time<std::chrono::seconds, ptr> 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<offset_time_zone_flags::both>; + static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>, ptr>); + static_assert(!std::convertible_to<ptr, std::chrono::zoned_time<std::chrono::seconds, ptr>>); + + ptr tz{"60"}; + std::chrono::zoned_time<std::chrono::seconds, ptr> 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 0000000000000..7927c6c126023 --- /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 + +// <chrono> + +// template<class Duration, class TimeZonePtr = const time_zone*> +// class zoned_time; +// +// zoned_time(TimeZonePtr z, const local_time<Duration>& st, choose c); + +#include <chrono> +#include <concepts> +#include <cassert> + +#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<std::chrono::seconds> 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<std::chrono::seconds> 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<std::chrono::seconds> 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<std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>, + const std::chrono::time_zone*, + std::chrono::local_seconds, + std::chrono::choose>); + + static_assert(!std::constructible_from< + std::chrono::zoned_time<std::chrono::seconds, offset_time_zone<offset_time_zone_flags::none>>, + offset_time_zone<offset_time_zone_flags::none>, + std::chrono::local_seconds, + std::chrono::choose>); + + static_assert( + !std::constructible_from< + std::chrono::zoned_time<std::chrono::seconds, offset_time_zone<offset_time_zone_flags::has_default_zone>>, + offset_time_zone<offset_time_zone_flags::has_default_zone>, + std::chrono::local_seconds, + std::chrono::choose>); + + static_assert( + !std::constructible_from< + std::chrono::zoned_time<std::chrono::seconds, offset_time_zone<offset_time_zone_flags::has_locate_zone>>, + offset_time_zone<offset_time_zone_flags::has_locate_zone>, + std::chrono::local_seconds, + std::chrono::choose>); + + static_assert(!std::constructible_from< + std::chrono::zoned_time<std::chrono::seconds, offset_time_zone<offset_time_zone_flags::both>>, + offset_time_zone<offset_time_zone_flags::both>, + 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 0000000000000..9a84d93305679 --- /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 + +// <chrono> + +// template<class Duration, class TimeZonePtr = const time_zone*> +// class zoned_time; +// +// zoned_time(TimeZonePtr z, const sys_time<Duration>& st); + +#include <chrono> +#include <concepts> +#include <cassert> + +#include "test_offset_time_zone.h" + +int main(int, char**) { + { + using ptr = const std::chrono::time_zone*; + static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>, ptr>); + static_assert(!std::convertible_to<ptr, std::chrono::zoned_time<std::chrono::seconds, ptr>>); + + ptr tz = std::chrono::locate_zone("UTC"); + std::chrono::zoned_time<std::chrono::seconds> 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<offset_time_zone_flags::none>; + static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>, ptr>); + static_assert(!std::convertible_to<ptr, std::chrono::zoned_time<std::chrono::seconds, ptr>>); + + ptr tz; + std::chrono::zoned_time<std::chrono::seconds, ptr> 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<offset_time_zone_flags::has_default_zone>; + static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>, ptr>); + static_assert(!std::convertible_to<ptr, std::chrono::zoned_time<std::chrono::seconds, ptr>>); + + ptr tz; + std::chrono::zoned_time<std::chrono::seconds, ptr> 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<offset_time_zone_flags::has_locate_zone>; + static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>, ptr>); + static_assert(!std::convertible_to<ptr, std::chrono::zoned_time<std::chrono::seconds, ptr>>); + + ptr tz; + std::chrono::zoned_time<std::chrono::seconds, ptr> 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<offset_time_zone_flags::both>; + static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>, ptr>); + static_assert(!std::convertible_to<ptr, std::chrono::zoned_time<std::chrono::seconds, ptr>>); + + ptr tz; + std::chrono::zoned_time<std::chrono::seconds, ptr> 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 0000000000000..adaec5d18b5e7 --- /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 + +// <chrono> + +// template<class Duration, class TimeZonePtr = const time_zone*> +// class zoned_time; + +// template<class Duration2, class TimeZonePtr2> +// zoned_time(TimeZonePtr z, const zoned_time<Duration2, TimeZonePtr2>& y); + +#include <chrono> +#include <concepts> +#include <cassert> + +template <> +struct std::chrono::zoned_traits<int> { + 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<Duration2>, sys_time<Duration>> is true. + { + using duration = std::chrono::microseconds; + using time_point = std::chrono::sys_time<duration>; + std::chrono::zoned_time<duration, int> zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time<duration2>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2>, + const std::chrono::time_zone*, + std::chrono::zoned_time<duration, int>>); + std::chrono::zoned_time<duration2> 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<duration>; + std::chrono::zoned_time<duration, int> zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time<duration2>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2>, + const std::chrono::time_zone*, + std::chrono::zoned_time<duration, int>>); + std::chrono::zoned_time<duration2> 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<duration>; + std::chrono::zoned_time<duration, int> zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time<duration2>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2>, + const std::chrono::time_zone*, + std::chrono::zoned_time<duration, int>>); + std::chrono::zoned_time<duration2> 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<Duration2>, sys_time<Duration>> is false. + { + using duration = std::chrono::milliseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2>, + const std::chrono::time_zone*, + std::chrono::zoned_time<duration, int>>); + } + { + using duration = std::chrono::microseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2>, + const std::chrono::time_zone*, + std::chrono::zoned_time<duration, int>>); + } + { + using duration = std::chrono::nanoseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2>, + const std::chrono::time_zone*, + std::chrono::zoned_time<duration, int>>); + } + + 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 0000000000000..9392cb03eb894 --- /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 + +// <chrono> + +// template<class Duration, class TimeZonePtr = const time_zone*> +// class zoned_time; + +// template<class Duration2, class TimeZonePtr2> +// zoned_time(TimeZonePtr z, const zoned_time<Duration2, TimeZonePtr2>& y, choose); + +#include <chrono> +#include <concepts> +#include <cassert> + +template <> +struct std::chrono::zoned_traits<int> { + 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<Duration2>, sys_time<Duration>> is true. + { + using duration = std::chrono::microseconds; + using time_point = std::chrono::sys_time<duration>; + std::chrono::zoned_time<duration, int> zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time<duration2>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2>, + const std::chrono::time_zone*, + std::chrono::zoned_time<duration, int>, + std::chrono::choose>); + std::chrono::zoned_time<duration2> 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<duration>; + std::chrono::zoned_time<duration, int> zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time<duration2>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2>, + const std::chrono::time_zone*, + std::chrono::zoned_time<duration, int>, + std::chrono::choose>); + std::chrono::zoned_time<duration2> 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<duration>; + std::chrono::zoned_time<duration, int> zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time<duration2>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2>, + const std::chrono::time_zone*, + std::chrono::zoned_time<duration, int>, + std::chrono::choose>); + std::chrono::zoned_time<duration2> 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<Duration2>, sys_time<Duration>> is false. + { + using duration = std::chrono::milliseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2>, + const std::chrono::time_zone*, + std::chrono::zoned_time<duration, int>, + std::chrono::choose>); + } + { + using duration = std::chrono::microseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2>, + const std::chrono::time_zone*, + std::chrono::zoned_time<duration, int>, + std::chrono::choose>); + } + { + using duration = std::chrono::nanoseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2>, + const std::chrono::time_zone*, + std::chrono::zoned_time<duration, int>, + 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 0000000000000..b911532b22886 --- /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 + +// <chrono> + +// template<class Duration, class TimeZonePtr = const time_zone*> +// class zoned_time; + +// template<class Duration2> +// zoned_time(const zoned_time<Duration2, TimeZonePtr>& y); + +#include <chrono> +#include <concepts> +#include <cassert> + +int main(int, char**) { + // is_convertible_v<sys_time<Duration2>, sys_time<Duration>> is true. + { + using duration = std::chrono::microseconds; + using time_point = std::chrono::sys_time<duration>; + std::chrono::zoned_time<duration> zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time<duration2>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2>, std::chrono::zoned_time<duration>>); + std::chrono::zoned_time<duration2> zt2{zt}; + + assert(zt2.get_sys_time() == time_point2{duration2{42'000}}); + } + { + using duration = std::chrono::milliseconds; + using time_point = std::chrono::sys_time<duration>; + std::chrono::zoned_time<duration> zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time<duration2>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2>, std::chrono::zoned_time<duration>>); + std::chrono::zoned_time<duration2> 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<duration>; + std::chrono::zoned_time<duration> zt{time_point{duration{42}}}; + + using duration2 = std::chrono::nanoseconds; + using time_point2 = std::chrono::sys_time<duration2>; + static_assert(std::constructible_from<std::chrono::zoned_time<duration2>, std::chrono::zoned_time<duration>>); + std::chrono::zoned_time<duration2> zt2{zt}; + + assert(zt2.get_sys_time() == time_point2{duration2{42'000'000'000}}); + } + // is_convertible_v<sys_time<Duration2>, sys_time<Duration>> is false. + { + using duration = std::chrono::milliseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2>, std::chrono::zoned_time<duration>>); + } + { + using duration = std::chrono::microseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2>, std::chrono::zoned_time<duration>>); + } + { + using duration = std::chrono::nanoseconds; + + using duration2 = std::chrono::seconds; + static_assert(!std::constructible_from<std::chrono::zoned_time<duration2>, std::chrono::zoned_time<duration>>); + } + + return 0; +} diff --git a/libcxx/test/support/test_offset_time_zone.h b/libcxx/test/support/test_offset_time_zone.h index e1c9f05c2483c..90b3649fef7c9 100644 --- a/libcxx/test/support/test_offset_time_zone.h +++ b/libcxx/test/support/test_offset_time_zone.h @@ -14,6 +14,7 @@ #include <charconv> #include <chrono> #include <string_view> +#include <type_traits> 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 <class Duration> + std::chrono::sys_time<std::common_type_t<Duration, std::chrono::seconds>> + to_sys(const std::chrono::local_time<Duration>& local) const { + return std::chrono::sys_time<std::common_type_t<Duration, std::chrono::seconds>>{ + local.time_since_epoch() + offset_}; + } + private: std::chrono::seconds offset_; }; _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits