From 0a95f2f7fe3a01fb94720dbb43679ef197b65f6a Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Wed, 10 Jul 2024 11:46:44 +0200 Subject: [PATCH] [libc++][TZDB] Finishes zoned_time member functions. (#95026) Note the implementation of zoned_time& operator=(const local_time& lt); is not correct; however the wording cannot be easily implemented. It could be if the object caches the local_time assigned. However this does not seem to intended. The current implementation matches MSVC STL and libstdc++. Implements parts of: - P0355 Extending to chrono Calendars and Time Zones --- libcxx/include/__chrono/zoned_time.h | 22 ++ .../diagnostics/chrono.nodiscard.verify.cpp | 12 +- .../assign.local_time.pass.cpp | 252 ++++++++++++++++++ .../assign.sys_time.pass.cpp | 144 ++++++++++ .../get_info.pass.cpp | 51 ++++ .../get_local_time.pass.cpp | 133 +++++++++ .../operator_local_time.pass.cpp | 135 ++++++++++ .../operator_sys_time.pass.cpp | 125 +++++++++ 8 files changed, 872 insertions(+), 2 deletions(-) create mode 100644 libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/assign.local_time.pass.cpp create mode 100644 libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/assign.sys_time.pass.cpp create mode 100644 libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/get_info.pass.cpp create mode 100644 libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/get_local_time.pass.cpp create mode 100644 libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/operator_local_time.pass.cpp create mode 100644 libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/operator_sys_time.pass.cpp diff --git a/libcxx/include/__chrono/zoned_time.h b/libcxx/include/__chrono/zoned_time.h index 08f7f37603920a..971c1c208352ec 100644 --- a/libcxx/include/__chrono/zoned_time.h +++ b/libcxx/include/__chrono/zoned_time.h @@ -18,6 +18,7 @@ # include <__chrono/calendar.h> # include <__chrono/duration.h> +# include <__chrono/sys_info.h> # include <__chrono/system_clock.h> # include <__chrono/time_zone.h> # include <__chrono/tzdb_list.h> @@ -147,8 +148,29 @@ class zoned_time { } && is_convertible_v, sys_time<_Duration>>) : zoned_time{__traits::locate_zone(__name), __zt, __c} {} + _LIBCPP_HIDE_FROM_ABI zoned_time& operator=(const sys_time<_Duration>& __tp) { + __tp_ = __tp; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI zoned_time& operator=(const local_time<_Duration>& __tp) { + // TODO TZDB This seems wrong. + // Assigning a non-existent or ambiguous time will throw and not satisfy + // the post condition. This seems quite odd; I constructed an object with + // choose::earliest and that choice is not respected. + // what did LEWG do with this. + // MSVC STL and libstdc++ behave the same + __tp_ = __zone_->to_sys(__tp); + return *this; + } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI operator sys_time() const { return get_sys_time(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit operator local_time() const { return get_local_time(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _TimeZonePtr get_time_zone() const { return __zone_; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI local_time get_local_time() const { return __zone_->to_local(__tp_); } [[nodiscard]] _LIBCPP_HIDE_FROM_ABI sys_time get_sys_time() const { return __tp_; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI sys_info get_info() const { return __zone_->get_info(__tp_); } private: _TimeZonePtr __zone_; diff --git a/libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp b/libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp index e8337cb33822e9..32a67dc4dc9c48 100644 --- a/libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp +++ b/libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp @@ -81,7 +81,15 @@ void test() { { std::chrono::zoned_time zt; - zt.get_time_zone(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} - zt.get_sys_time(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} + static_cast(zt); + // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} + static_cast(zt); + + zt.get_time_zone(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + zt.get_local_time(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + zt.get_sys_time(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + zt.get_info(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} } } diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/assign.local_time.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/assign.local_time.pass.cpp new file mode 100644 index 00000000000000..3f9ca5738ee589 --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/assign.local_time.pass.cpp @@ -0,0 +1,252 @@ +//===----------------------------------------------------------------------===// +// +// 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& operator=(const local_time& st); + +// TODO TZDB Investigate the issues in this test, this seems like +// a design issue of the class. +// +// [time.zone.zonedtime.members]/3 +// Effects: After assignment, get_local_time() == lt. +// This assignment has no effect on the return value of get_time_zone(). +// +// The test cases describe the issues. + +#include +#include +#include +#include + +#include "test_macros.h" + +namespace cr = std::chrono; + +// 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. +static void test_unique() { + // common_type_t -> duration + { + using duration = cr::nanoseconds; + using sys_time_point = cr::sys_time; + using local_time_point = cr::local_time; + using zoned_time = cr::zoned_time; + zoned_time zt{"Etc/GMT+1", sys_time_point{duration{42}}}; + + assert(zt.get_time_zone() == cr::locate_zone("Etc/GMT+1")); + assert(zt.get_sys_time() == sys_time_point{duration{42}}); + assert(zt.get_local_time() == local_time_point{duration{42} - cr::hours{1}}); + + std::same_as decltype(auto) result = zt = local_time_point{duration{99}}; + assert(&result == &zt); + assert(zt.get_time_zone() == cr::locate_zone("Etc/GMT+1")); + assert(zt.get_sys_time() == sys_time_point{duration{99} + cr::hours{1}}); + assert(zt.get_local_time() == local_time_point{duration{99}}); + } + { + using duration = cr::microseconds; + using sys_time_point = cr::sys_time; + using local_time_point = cr::local_time; + using zoned_time = cr::zoned_time; + zoned_time zt{"Etc/GMT+1", sys_time_point{duration{42}}}; + + assert(zt.get_time_zone() == cr::locate_zone("Etc/GMT+1")); + assert(zt.get_sys_time() == sys_time_point{duration{42}}); + assert(zt.get_local_time() == local_time_point{duration{42} - cr::hours{1}}); + + std::same_as decltype(auto) result = zt = local_time_point{duration{99}}; + assert(&result == &zt); + assert(zt.get_time_zone() == cr::locate_zone("Etc/GMT+1")); + assert(zt.get_sys_time() == sys_time_point{duration{99} + cr::hours{1}}); + assert(zt.get_local_time() == local_time_point{duration{99}}); + } + { + using duration = cr::milliseconds; + using sys_time_point = cr::sys_time; + using local_time_point = cr::local_time; + using zoned_time = cr::zoned_time; + zoned_time zt{"Etc/GMT+1", sys_time_point{duration{42}}}; + + assert(zt.get_time_zone() == cr::locate_zone("Etc/GMT+1")); + assert(zt.get_sys_time() == sys_time_point{duration{42}}); + assert(zt.get_local_time() == local_time_point{duration{42} - cr::hours{1}}); + + std::same_as decltype(auto) result = zt = local_time_point{duration{99}}; + assert(&result == &zt); + assert(zt.get_time_zone() == cr::locate_zone("Etc/GMT+1")); + assert(zt.get_sys_time() == sys_time_point{duration{99} + cr::hours{1}}); + assert(zt.get_local_time() == local_time_point{duration{99}}); + } + // common_type_t -> seconds + { + using duration = cr::seconds; + using sys_time_point = cr::sys_time; + using local_time_point = cr::local_time; + using zoned_time = cr::zoned_time; + zoned_time zt{"Etc/GMT+1", sys_time_point{duration{42}}}; + + assert(zt.get_time_zone() == cr::locate_zone("Etc/GMT+1")); + assert(zt.get_sys_time() == sys_time_point{duration{42}}); + assert(zt.get_local_time() == local_time_point{duration{42} - cr::hours{1}}); + + std::same_as decltype(auto) result = zt = local_time_point{duration{99}}; + assert(&result == &zt); + assert(zt.get_time_zone() == cr::locate_zone("Etc/GMT+1")); + assert(zt.get_sys_time() == sys_time_point{duration{99} + cr::hours{1}}); + assert(zt.get_local_time() == local_time_point{duration{99}}); + } + // common_type_t -> seconds + { + using duration = cr::days; + using sys_time_point = cr::sys_time; + using local_time_point = cr::local_time; + using zoned_time = cr::zoned_time; + zoned_time zt{"Etc/GMT+1", sys_time_point{duration{42}}}; + + assert(zt.get_time_zone() == cr::locate_zone("Etc/GMT+1")); + assert(zt.get_sys_time() == cr::sys_seconds{duration{42}}); + assert(zt.get_local_time() == cr::local_seconds{duration{42} - cr::hours{1}}); + + std::same_as decltype(auto) result = zt = local_time_point{duration{99}}; + assert(&result == &zt); + assert(zt.get_time_zone() == cr::locate_zone("Etc/GMT+1")); + assert(zt.get_sys_time() == cr::sys_seconds{duration{99} + cr::hours{1}}); + assert(zt.get_local_time() == cr::local_seconds{duration{99}}); + } + { + using duration = cr::weeks; + using sys_time_point = cr::sys_time; + using local_time_point = cr::local_time; + using zoned_time = cr::zoned_time; + zoned_time zt{"Etc/GMT+1", sys_time_point{duration{42}}}; + + assert(zt.get_time_zone() == cr::locate_zone("Etc/GMT+1")); + assert(zt.get_sys_time() == cr::sys_seconds{duration{42}}); + assert(zt.get_local_time() == cr::local_seconds{duration{42} - cr::hours{1}}); + + std::same_as decltype(auto) result = zt = local_time_point{duration{99}}; + assert(&result == &zt); + assert(zt.get_time_zone() == cr::locate_zone("Etc/GMT+1")); + assert(zt.get_sys_time() == cr::sys_seconds{duration{99} + cr::hours{1}}); + assert(zt.get_local_time() == cr::local_seconds{duration{99}}); + } + /* This does not work; due to using __tp_ = __zone_->to_sys(__tp); + * Here the ambiguous/non-existent exception can't stream months and years, + * leading to a compilation error. + { + using duration = cr::months; + using sys_time_point = cr::sys_time; + using local_time_point = cr::local_time; + using zoned_time = cr::zoned_time; + zoned_time zt{"Etc/GMT+1", sys_time_point{duration{42}}}; + + assert(zt.get_time_zone() == cr::locate_zone("Etc/GMT+1")); + assert(zt.get_sys_time() == cr::sys_seconds{duration{42}}); + assert(zt.get_local_time() == cr::local_seconds{duration{42} - cr::hours{1}}); + + std::same_as decltype(auto) result= zt = local_time_point{duration{99}}; + assert(&result == &zt); + assert(zt.get_time_zone() == cr::locate_zone("Etc/GMT+1")); + assert(zt.get_sys_time() == cr::sys_seconds{duration{99} + cr::hours{1}}); + assert(zt.get_local_time() == cr::local_seconds{duration{99}}); + } */ +} + +// Tests non-existent conversions. +static void test_nonexistent() { +#ifndef TEST_HAS_NO_EXCEPTIONS + using namespace std::literals::chrono_literals; + + const cr::time_zone* tz = cr::locate_zone("Europe/Berlin"); + + // 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 - + + // Pick an historic date where it's well known what the time zone rules were. + // This makes it unlikely updates to the database change these rules. + cr::local_time time{(cr::sys_days{cr::March / 30 / 1986} + 2h + 30min).time_since_epoch()}; + + using duration = cr::seconds; + using zoned_time = cr::zoned_time; + zoned_time zt{tz}; + + bool thrown = false; + try { + std::same_as decltype(auto) result = zt = time; + assert(&result == &zt); + } catch (const cr::nonexistent_local_time&) { + thrown = true; + } + // There is no system type that can represent the current local time. So the + // assertion passes. The current implementation throws an exception too. + assert(zt.get_local_time() != time); + assert(thrown); +#endif // TEST_HAS_NO_EXCEPTIONS +} + +// Tests ambiguous conversions. +static void test_ambiguous() { +#ifndef TEST_HAS_NO_EXCEPTIONS + using namespace std::literals::chrono_literals; + + const cr::time_zone* tz = cr::locate_zone("Europe/Berlin"); + + // 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 - + + // Pick an historic date where it's well known what the time zone rules were. + // This makes it unlikely updates to the database change these rules. + cr::local_time time{(cr::sys_days{cr::September / 28 / 1986} + 2h + 30min).time_since_epoch()}; + + using duration = cr::seconds; + using zoned_time = cr::zoned_time; + zoned_time zt{tz}; + + bool thrown = false; + try { + std::same_as decltype(auto) result = zt = time; + assert(&result == &zt); + } catch (const cr::ambiguous_local_time&) { + thrown = true; + } + // There is no system type that can represent the current local time. So the + // assertion passes. The current implementation throws an exception too. + assert(zt.get_local_time() != time); + assert(thrown); +#endif // TEST_HAS_NO_EXCEPTIONS +} + +int main(int, char**) { + test_unique(); + test_nonexistent(); + test_ambiguous(); + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/assign.sys_time.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/assign.sys_time.pass.cpp new file mode 100644 index 00000000000000..c4194595df619f --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/assign.sys_time.pass.cpp @@ -0,0 +1,144 @@ +//===----------------------------------------------------------------------===// +// +// 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& operator=(const sys_time& st); + +#include +#include +#include +#include + +namespace cr = std::chrono; + +int main(int, char**) { + { + using duration = cr::nanoseconds; + using time_point = cr::sys_time; + using zoned_time = cr::zoned_time; + zoned_time zt{time_point{duration{42}}}; + + assert(zt.get_time_zone() == cr::locate_zone("UTC")); + assert(zt.get_sys_time() == time_point{duration{42}}); + + std::same_as decltype(auto) result = zt = time_point{duration{99}}; + assert(&result == &zt); + assert(zt.get_time_zone() == cr::locate_zone("UTC")); + assert(zt.get_sys_time() == time_point{duration{99}}); + } + { + using duration = cr::microseconds; + using time_point = cr::sys_time; + using zoned_time = cr::zoned_time; + zoned_time zt{time_point{duration{42}}}; + + assert(zt.get_time_zone() == cr::locate_zone("UTC")); + assert(zt.get_sys_time() == time_point{duration{42}}); + + std::same_as decltype(auto) result = zt = time_point{duration{99}}; + assert(&result == &zt); + assert(zt.get_time_zone() == cr::locate_zone("UTC")); + assert(zt.get_sys_time() == time_point{duration{99}}); + } + { + using duration = cr::milliseconds; + using time_point = cr::sys_time; + using zoned_time = cr::zoned_time; + zoned_time zt{time_point{duration{42}}}; + + assert(zt.get_time_zone() == cr::locate_zone("UTC")); + assert(zt.get_sys_time() == time_point{duration{42}}); + + std::same_as decltype(auto) result = zt = time_point{duration{99}}; + assert(&result == &zt); + assert(zt.get_time_zone() == cr::locate_zone("UTC")); + assert(zt.get_sys_time() == time_point{duration{99}}); + } + { + using duration = cr::seconds; + using time_point = cr::sys_time; + using zoned_time = cr::zoned_time; + zoned_time zt{time_point{duration{42}}}; + + assert(zt.get_time_zone() == cr::locate_zone("UTC")); + assert(zt.get_sys_time() == time_point{duration{42}}); + + std::same_as decltype(auto) result = zt = time_point{duration{99}}; + assert(&result == &zt); + assert(zt.get_time_zone() == cr::locate_zone("UTC")); + assert(zt.get_sys_time() == time_point{duration{99}}); + } + { + using duration = cr::days; + using time_point = cr::sys_time; + using zoned_time = cr::zoned_time; + zoned_time zt{time_point{duration{42}}}; + + assert(zt.get_time_zone() == cr::locate_zone("UTC")); + assert(zt.get_sys_time() == time_point{duration{42}}); + + std::same_as decltype(auto) result = zt = time_point{duration{99}}; + assert(&result == &zt); + assert(zt.get_time_zone() == cr::locate_zone("UTC")); + assert(zt.get_sys_time() == time_point{duration{99}}); + } + { + using duration = cr::weeks; + using time_point = cr::sys_time; + using zoned_time = cr::zoned_time; + zoned_time zt{time_point{duration{42}}}; + + assert(zt.get_time_zone() == cr::locate_zone("UTC")); + assert(zt.get_sys_time() == time_point{duration{42}}); + + std::same_as decltype(auto) result = zt = time_point{duration{99}}; + assert(&result == &zt); + assert(zt.get_time_zone() == cr::locate_zone("UTC")); + assert(zt.get_sys_time() == time_point{duration{99}}); + } + { + using duration = cr::months; + using time_point = cr::sys_time; + using zoned_time = cr::zoned_time; + zoned_time zt{time_point{duration{42}}}; + + assert(zt.get_time_zone() == cr::locate_zone("UTC")); + assert(zt.get_sys_time() == time_point{duration{42}}); + + std::same_as decltype(auto) result = zt = time_point{duration{99}}; + assert(&result == &zt); + assert(zt.get_time_zone() == cr::locate_zone("UTC")); + assert(zt.get_sys_time() == time_point{duration{99}}); + } + { + using duration = cr::years; + using time_point = cr::sys_time; + using zoned_time = cr::zoned_time; + zoned_time zt{time_point{duration{42}}}; + + assert(zt.get_time_zone() == cr::locate_zone("UTC")); + assert(zt.get_sys_time() == time_point{duration{42}}); + + std::same_as decltype(auto) result = zt = time_point{duration{99}}; + assert(&result == &zt); + assert(zt.get_time_zone() == cr::locate_zone("UTC")); + assert(zt.get_sys_time() == time_point{duration{99}}); + } + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/get_info.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/get_info.pass.cpp new file mode 100644 index 00000000000000..4bce11618a1296 --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/get_info.pass.cpp @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// 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; +// +// sys_info get_info() const; + +#include +#include +#include + +namespace cr = std::chrono; + +int main(int, char**) { + { + cr::zoned_time zt; + + std::same_as decltype(auto) info = zt.get_info(); + assert(info.begin == cr::sys_seconds::min()); + assert(info.end == cr::sys_seconds::max()); + assert(info.offset == cr::seconds{0}); + assert(info.save == cr::minutes{0}); + assert(info.abbrev == "UTC"); + } + { + const cr::zoned_time zt; + + std::same_as decltype(auto) info = zt.get_info(); + assert(info.begin == cr::sys_seconds::min()); + assert(info.end == cr::sys_seconds::max()); + assert(info.offset == cr::seconds{0}); + assert(info.save == cr::minutes{0}); + assert(info.abbrev == "UTC"); + } + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/get_local_time.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/get_local_time.pass.cpp new file mode 100644 index 00000000000000..c465cda36c51e7 --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/get_local_time.pass.cpp @@ -0,0 +1,133 @@ +//===----------------------------------------------------------------------===// +// +// 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; +// +// local_time get_local_time() const; + +#include +#include + +#include "../test_offset_time_zone.h" + +namespace cr = std::chrono; + +static void test_callable_with_non_const_and_const_objects() { + { + using duration = cr::nanoseconds; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = zt.get_local_time(); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } + { + using duration = cr::nanoseconds; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + const cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = zt.get_local_time(); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } +} + +static void test_duration_conversion() { + // common_type_t -> duration + { + using duration = cr::nanoseconds; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = zt.get_local_time(); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } + { + using duration = cr::microseconds; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = zt.get_local_time(); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } + { + using duration = cr::milliseconds; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = zt.get_local_time(); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } + // common_type_t -> seconds + { + using duration = cr::seconds; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = zt.get_local_time(); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } + // common_type_t -> seconds + { + using duration = cr::days; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = zt.get_local_time(); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } + { + using duration = cr::weeks; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = zt.get_local_time(); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } + { + using duration = cr::months; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = zt.get_local_time(); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } + { + using duration = cr::years; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = zt.get_local_time(); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } +} + +int main(int, char**) { + test_callable_with_non_const_and_const_objects(); + test_duration_conversion(); + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/operator_local_time.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/operator_local_time.pass.cpp new file mode 100644 index 00000000000000..2a9c2419974385 --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/operator_local_time.pass.cpp @@ -0,0 +1,135 @@ +//===----------------------------------------------------------------------===// +// +// 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; +// +// explicit operator local_time() const; + +#include +#include + +#include "../test_offset_time_zone.h" + +namespace cr = std::chrono; + +static void test_callable_with_non_const_and_const_objects() { + { + using duration = cr::nanoseconds; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + static_assert(!std::is_convertible_v>); + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } + { + using duration = cr::nanoseconds; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + static_assert(!std::is_convertible_v>); + const cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } +} + +static void test_duration_conversion() { + // common_type_t -> duration + { + using duration = cr::nanoseconds; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } + { + using duration = cr::microseconds; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } + { + using duration = cr::milliseconds; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } + // common_type_t -> seconds + { + using duration = cr::seconds; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } + // common_type_t -> seconds + { + using duration = cr::days; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } + { + using duration = cr::weeks; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } + { + using duration = cr::months; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } + { + using duration = cr::years; + using time_point = cr::sys_time; + using local_time_point = cr::local_time; + cr::zoned_time zt{"Etc/GMT+1", time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == local_time_point{duration{42} - cr::hours{1}}); + } +} + +int main(int, char**) { + test_callable_with_non_const_and_const_objects(); + test_duration_conversion(); + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/operator_sys_time.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/operator_sys_time.pass.cpp new file mode 100644 index 00000000000000..327ed495aed1ac --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/operator_sys_time.pass.cpp @@ -0,0 +1,125 @@ +//===----------------------------------------------------------------------===// +// +// 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; +// +// operator sys_time() const; + +#include +#include + +#include "../test_offset_time_zone.h" + +namespace cr = std::chrono; + +static void test_const_member() { + { + using duration = cr::nanoseconds; + using time_point = cr::sys_time; + static_assert(std::is_convertible_v>); + cr::zoned_time zt{time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == time_point{duration{42}}); + } + { + using duration = cr::nanoseconds; + using time_point = cr::sys_time; + static_assert(std::is_convertible_v>); + const cr::zoned_time zt{time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == time_point{duration{42}}); + } +} + +static void test_duration_conversion() { + // common_type_t -> duration + { + using duration = cr::nanoseconds; + using time_point = cr::sys_time; + cr::zoned_time zt{time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == time_point{duration{42}}); + } + { + using duration = cr::microseconds; + using time_point = cr::sys_time; + cr::zoned_time zt{time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == time_point{duration{42}}); + } + { + using duration = cr::milliseconds; + using time_point = cr::sys_time; + cr::zoned_time zt{time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == time_point{duration{42}}); + } + // common_type_t -> seconds + { + using duration = cr::seconds; + using time_point = cr::sys_time; + cr::zoned_time zt{time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == time_point{duration{42}}); + } + // common_type_t -> seconds + { + using duration = cr::days; + using time_point = cr::sys_time; + cr::zoned_time zt{time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == time_point{duration{42}}); + } + { + using duration = cr::weeks; + using time_point = cr::sys_time; + cr::zoned_time zt{time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == time_point{duration{42}}); + } + { + using duration = cr::months; + using time_point = cr::sys_time; + cr::zoned_time zt{time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == time_point{duration{42}}); + } + { + using duration = cr::years; + using time_point = cr::sys_time; + cr::zoned_time zt{time_point{duration{42}}}; + + std::same_as decltype(auto) time = static_cast(zt); + assert(time == time_point{duration{42}}); + } +} + +int main(int, char**) { + test_const_member(); + test_duration_conversion(); + + return 0; +}