Skip to content

[libc++][TZDB] Implements zoned_traits. #91059

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 10, 2024
Merged

Conversation

mordante
Copy link
Member

@mordante mordante commented May 4, 2024

Implements parts of:

  • P0355 Extending chrono to Calendars and Time Zones

@mordante mordante requested a review from a team as a code owner May 4, 2024 12:38
Copy link
Member

@ldionne ldionne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM w/ minor comment.

@mordante mordante force-pushed the users/mordante/time_zone__to_local branch from 5f205f7 to 33deefa Compare June 10, 2024 06:41
Base automatically changed from users/mordante/time_zone__to_local to main June 10, 2024 10:40
Implements parts of:
- P0355 Extending chrono to Calendars and Time Zones
@mordante mordante force-pushed the users/mordante/zoned_traits branch from 0a602d2 to 50da5f2 Compare June 10, 2024 10:41
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jun 10, 2024
@llvmbot
Copy link
Member

llvmbot commented Jun 10, 2024

@llvm/pr-subscribers-libcxx

Author: Mark de Wever (mordante)

Changes

Implements parts of:

  • P0355 Extending chrono to Calendars and Time Zones

Full diff: https://github.com/llvm/llvm-project/pull/91059.diff

9 Files Affected:

  • (modified) libcxx/include/CMakeLists.txt (+1)
  • (added) libcxx/include/__chrono/zoned_time.h (+55)
  • (modified) libcxx/include/chrono (+4)
  • (modified) libcxx/include/module.modulemap (+1)
  • (modified) libcxx/modules/std/chrono.inc (+1-2)
  • (modified) libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp (+6)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtraits/const_time_zone_default_zone.pass.cpp (+36)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtraits/const_time_zone_locate_zone.pass.cpp (+45)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtraits/types.compile.pass.cpp (+33)
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index cbbcc74e21b44..d65b7ce782ebd 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -277,6 +277,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 0000000000000..c6084426ad72b
--- /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 4d47dc57ba654..c1a92595ff1f5 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 e03ea989eb371..892d2c6b4af3c 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -1159,6 +1159,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 f12c2425592e0..87e32afbe4bdc 100644
--- a/libcxx/modules/std/chrono.inc
+++ b/libcxx/modules/std/chrono.inc
@@ -227,11 +227,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 cba7916ff2c64..6fed41bdb43ed 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 0000000000000..c6527094bb621
--- /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 0000000000000..1c8184455f23c
--- /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 0000000000000..6e3410795c824
--- /dev/null
+++ b/libcxx/test/std/time/time.zone/time.zone.zonedtraits/types.compile.pass.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_empty_v<std::chrono::zoned_traits<foo>>);
+static_assert(std::is_trivial_v<std::chrono::zoned_traits<foo>>);

@mordante mordante merged commit 151bd7c into main Jun 10, 2024
56 checks passed
@mordante mordante deleted the users/mordante/zoned_traits branch June 10, 2024 15:13
Lukacma pushed a commit to Lukacma/llvm-project that referenced this pull request Jun 12, 2024
Implements parts of:
- P0355 Extending chrono to Calendars and Time Zones
@HerrCai0907 HerrCai0907 mentioned this pull request Jun 13, 2024
fmayer added a commit to fmayer/llvm-project that referenced this pull request Sep 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants