diff options
author | Mark de Wever <koraq@xs4all.nl> | 2024-04-17 21:00:22 +0200 |
---|---|---|
committer | Mark de Wever <koraq@xs4all.nl> | 2024-05-04 14:38:05 +0200 |
commit | 0a602d2268923936a62034faaaf10f2401457d99 (patch) | |
tree | 79646fb596e38c07a3c34dc8d4c1fbd5949533b8 | |
parent | 5f205f7478a13a6f7034808dff390c3fe87564dc (diff) |
[libc++][TZDB] Implements zoned_traits.upstream/users/mordante/zoned_traits
Implements parts of:
- P0355 Extending chrono to Calendars and Time Zones
9 files changed, 181 insertions, 2 deletions
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 386bd967eed7..919f1ae39390 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -291,6 +291,7 @@ set(files __chrono/year_month.h __chrono/year_month_day.h __chrono/year_month_weekday.h + __chrono/zoned_time.h __compare/common_comparison_category.h __compare/compare_partial_order_fallback.h __compare/compare_strong_order_fallback.h diff --git a/libcxx/include/__chrono/zoned_time.h b/libcxx/include/__chrono/zoned_time.h new file mode 100644 index 000000000000..c6084426ad72 --- /dev/null +++ b/libcxx/include/__chrono/zoned_time.h @@ -0,0 +1,55 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html + +#ifndef _LIBCPP___CHRONO_ZONED_TIME_H +#define _LIBCPP___CHRONO_ZONED_TIME_H + +#include <version> +// Enable the contents of the header only when libc++ was built with experimental features enabled. +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) + +# include <__chrono/time_zone.h> +# include <__chrono/tzdb_list.h> +# include <__config> +# include <__fwd/string_view.h> + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +# if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_TIME_ZONE_DATABASE) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) && \ + !defined(_LIBCPP_HAS_NO_LOCALIZATION) + +namespace chrono { + +template <class> +struct zoned_traits {}; + +template <> +struct zoned_traits<const time_zone*> { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static const time_zone* default_zone() { return chrono::locate_zone("UTC"); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static const time_zone* locate_zone(string_view __name) { + return chrono::locate_zone(__name); + } +}; + +} // namespace chrono + +# endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_TIME_ZONE_DATABASE) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) + // && !defined(_LIBCPP_HAS_NO_LOCALIZATION) + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) + +#endif // _LIBCPP___CHRONO_ZONED_TIME_H diff --git a/libcxx/include/chrono b/libcxx/include/chrono index d6b889cdde73..7d341823755f 100644 --- a/libcxx/include/chrono +++ b/libcxx/include/chrono @@ -786,6 +786,9 @@ class time_zone { bool operator==(const time_zone& x, const time_zone& y) noexcept; // C++20 strong_ordering operator<=>(const time_zone& x, const time_zone& y) noexcept; // C++20 +// [time.zone.zonedtraits], class template zoned_traits +template<class T> struct zoned_traits; // C++20 + // [time.zone.leap], leap second support class leap_second { // C++20 public: @@ -959,6 +962,7 @@ constexpr chrono::year operator ""y(unsigned lo # include <__chrono/time_zone_link.h> # include <__chrono/tzdb.h> # include <__chrono/tzdb_list.h> +# include <__chrono/zoned_time.h> # endif #endif diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index e4c154d99602..5c0da3e81725 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -1170,6 +1170,7 @@ module std_private_chrono_year [system] { header "__chrono/yea module std_private_chrono_year_month [system] { header "__chrono/year_month.h" } module std_private_chrono_year_month_day [system] { header "__chrono/year_month_day.h" } module std_private_chrono_year_month_weekday [system] { header "__chrono/year_month_weekday.h" } +module std_private_chrono_zoned_time [system] { header "__chrono/zoned_time.h" } module std_private_compare_common_comparison_category [system] { header "__compare/common_comparison_category.h" } module std_private_compare_compare_partial_order_fallback [system] { header "__compare/compare_partial_order_fallback.h" } diff --git a/libcxx/modules/std/chrono.inc b/libcxx/modules/std/chrono.inc index 9e16f09bd31a..bd6cb6c83564 100644 --- a/libcxx/modules/std/chrono.inc +++ b/libcxx/modules/std/chrono.inc @@ -220,11 +220,10 @@ export namespace std { using std::chrono::choose; using std::chrono::time_zone; -# if 0 - // [time.zone.zonedtraits], class template zoned_traits using std::chrono::zoned_traits; +# if 0 // [time.zone.zonedtime], class template zoned_time using std::chrono::zoned_time; diff --git a/libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp b/libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp index cba7916ff2c6..6fed41bdb43e 100644 --- a/libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp +++ b/libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp @@ -72,4 +72,10 @@ void test() { leap.date(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} leap.value(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} } + + { + using t = std::chrono::zoned_traits<const std::chrono::time_zone*>; + t::default_zone(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + t::locate_zone(""); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + } } diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtraits/const_time_zone_default_zone.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtraits/const_time_zone_default_zone.pass.cpp new file mode 100644 index 000000000000..c6527094bb62 --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtraits/const_time_zone_default_zone.pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// 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<> struct zoned_traits<const time_zone*>; + +// static const time_zone* default_zone(); + +#include <chrono> +#include <cassert> + +int main(int, char**) { + std::same_as<const std::chrono::time_zone*> decltype(auto) tz = + std::chrono::zoned_traits<const std::chrono::time_zone*>::default_zone(); + assert(tz); + + // The time zone "UTC" can be a link, this means tz->name() can be something + // differently. For example, "Etc/UTC". Instead validate whether same time + // zone is returned by comparing the addresses. + const std::chrono::time_zone* expected = std::chrono::locate_zone("UTC"); + assert(tz == expected); + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtraits/const_time_zone_locate_zone.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtraits/const_time_zone_locate_zone.pass.cpp new file mode 100644 index 000000000000..1c8184455f23 --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtraits/const_time_zone_locate_zone.pass.cpp @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// 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<> struct zoned_traits<const time_zone*>; + +// static const time_zone* locate_zone(string_view name); + +#include <chrono> +#include <cassert> +#include <concepts> + +#include "assert_macros.h" + +static void test(std::string_view name) { + std::same_as<const std::chrono::time_zone*> decltype(auto) tz = + std::chrono::zoned_traits<const std::chrono::time_zone*>::locate_zone(name); + + const std::chrono::time_zone* expected = std::chrono::locate_zone(name); + assert(tz == expected); +} + +int main(int, char**) { + test("UTC"); + test("Europe/Berlin"); + test("Asia/Hong_Kong"); + + TEST_THROWS_TYPE(std::runtime_error, + TEST_IGNORE_NODISCARD std::chrono::zoned_traits<const std::chrono::time_zone*>::locate_zone( + "there_is_no_time_zone_with_this_name")); + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtraits/types.compile.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtraits/types.compile.pass.cpp new file mode 100644 index 000000000000..03c18215f3c3 --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtraits/types.compile.pass.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// 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 T> struct zoned_traits {}; +// +// A specialization for const time_zone* is provided by the implementation: +// template<> struct zoned_traits<const time_zone*> { ... } + +#include <chrono> +#include <type_traits> + +// This test test whether non-specialized versions exhibit the expected +// behavior. (Note these specializations are not really useful.) +static_assert(std::is_trivial_v<std::chrono::zoned_traits<int>>); +static_assert(std::is_trivial_v<std::chrono::zoned_traits<float>>); +static_assert(std::is_trivial_v<std::chrono::zoned_traits<void*>>); + +struct foo {}; +static_assert(std::is_trivial_v<std::chrono::zoned_traits<foo>>); |