Skip to content

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
@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