Skip to content
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

[libc++][TZDB] Finishes zoned_time member functions. #95026

Merged
merged 1 commit into from
Jul 10, 2024

Conversation

mordante
Copy link
Member

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

@mordante mordante requested a review from a team as a code owner June 10, 2024 19:23
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jun 10, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jun 10, 2024

@llvm/pr-subscribers-libcxx

Author: Mark de Wever (mordante)

Changes

Note the implementation of
zoned_time& operator=(const local_time<Duration>& 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

Patch is 38.33 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/95026.diff

8 Files Affected:

  • (modified) libcxx/include/__chrono/zoned_time.h (+21)
  • (modified) libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp (+10-2)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/assign.local_time.pass.cpp (+245)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/assign.sys_time.pass.cpp (+134)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/get_info.pass.cpp (+49)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/get_local_time.pass.cpp (+131)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/operator_local_time.pass.cpp (+133)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/operator_sys_time.pass.cpp (+123)
diff --git a/libcxx/include/__chrono/zoned_time.h b/libcxx/include/__chrono/zoned_time.h
index bf8e04b6407ef..e59f527f4d825 100644
--- a/libcxx/include/__chrono/zoned_time.h
+++ b/libcxx/include/__chrono/zoned_time.h
@@ -146,8 +146,29 @@ class zoned_time {
     } && is_convertible_v<sys_time<_Duration2>, 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-existant or abiguous 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<duration>() const { return get_sys_time(); }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit operator local_time<duration>() const { return get_local_time(); }
+
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _TimeZonePtr get_time_zone() const { return __zone_; }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI local_time<duration> get_local_time() const { return __zone_->to_local(__tp_); }
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI sys_time<duration> 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 e8337cb33822e..32a67dc4dc9c4 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<std::chrono::seconds> 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<std::chrono::sys_seconds>(zt);
+    // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    static_cast<std::chrono::local_seconds>(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 0000000000000..e5f2e5d92e71a
--- /dev/null
+++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/assign.local_time.pass.cpp
@@ -0,0 +1,245 @@
+//===----------------------------------------------------------------------===//
+//
+// 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& operator=(const local_time<Duration>& 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 <cassert>
+#include <chrono>
+#include <concepts>
+#include <type_traits>
+
+// 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, seconds> -> duration
+  {
+    using duration         = std::chrono::nanoseconds;
+    using sys_time_point   = std::chrono::sys_time<duration>;
+    using local_time_point = std::chrono::local_time<duration>;
+    using zoned_time       = std::chrono::zoned_time<duration>;
+    zoned_time zt{"Etc/GMT+1", sys_time_point{duration{42}}};
+
+    assert(zt.get_time_zone() == std::chrono::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} - std::chrono::hours{1}});
+
+    std::same_as<zoned_time&> decltype(auto) _ = zt = local_time_point{duration{99}};
+    assert(zt.get_time_zone() == std::chrono::locate_zone("Etc/GMT+1"));
+    assert(zt.get_sys_time() == sys_time_point{duration{99} + std::chrono::hours{1}});
+    assert(zt.get_local_time() == local_time_point{duration{99}});
+  }
+  {
+    using duration         = std::chrono::microseconds;
+    using sys_time_point   = std::chrono::sys_time<duration>;
+    using local_time_point = std::chrono::local_time<duration>;
+    using zoned_time       = std::chrono::zoned_time<duration>;
+    zoned_time zt{"Etc/GMT+1", sys_time_point{duration{42}}};
+
+    assert(zt.get_time_zone() == std::chrono::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} - std::chrono::hours{1}});
+
+    std::same_as<zoned_time&> decltype(auto) _ = zt = local_time_point{duration{99}};
+    assert(zt.get_time_zone() == std::chrono::locate_zone("Etc/GMT+1"));
+    assert(zt.get_sys_time() == sys_time_point{duration{99} + std::chrono::hours{1}});
+    assert(zt.get_local_time() == local_time_point{duration{99}});
+  }
+  {
+    using duration         = std::chrono::milliseconds;
+    using sys_time_point   = std::chrono::sys_time<duration>;
+    using local_time_point = std::chrono::local_time<duration>;
+    using zoned_time       = std::chrono::zoned_time<duration>;
+    zoned_time zt{"Etc/GMT+1", sys_time_point{duration{42}}};
+
+    assert(zt.get_time_zone() == std::chrono::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} - std::chrono::hours{1}});
+
+    std::same_as<zoned_time&> decltype(auto) _ = zt = local_time_point{duration{99}};
+    assert(zt.get_time_zone() == std::chrono::locate_zone("Etc/GMT+1"));
+    assert(zt.get_sys_time() == sys_time_point{duration{99} + std::chrono::hours{1}});
+    assert(zt.get_local_time() == local_time_point{duration{99}});
+  }
+  // common_type_t<seconds, seconds> -> seconds
+  {
+    using duration         = std::chrono::seconds;
+    using sys_time_point   = std::chrono::sys_time<duration>;
+    using local_time_point = std::chrono::local_time<duration>;
+    using zoned_time       = std::chrono::zoned_time<duration>;
+    zoned_time zt{"Etc/GMT+1", sys_time_point{duration{42}}};
+
+    assert(zt.get_time_zone() == std::chrono::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} - std::chrono::hours{1}});
+
+    std::same_as<zoned_time&> decltype(auto) _ = zt = local_time_point{duration{99}};
+    assert(zt.get_time_zone() == std::chrono::locate_zone("Etc/GMT+1"));
+    assert(zt.get_sys_time() == sys_time_point{duration{99} + std::chrono::hours{1}});
+    assert(zt.get_local_time() == local_time_point{duration{99}});
+  }
+  // common_type_t<duration, seconds> -> seconds
+  {
+    using duration         = std::chrono::days;
+    using sys_time_point   = std::chrono::sys_time<duration>;
+    using local_time_point = std::chrono::local_time<duration>;
+    using zoned_time       = std::chrono::zoned_time<duration>;
+    zoned_time zt{"Etc/GMT+1", sys_time_point{duration{42}}};
+
+    assert(zt.get_time_zone() == std::chrono::locate_zone("Etc/GMT+1"));
+    assert(zt.get_sys_time() == std::chrono::sys_seconds{duration{42}});
+    assert(zt.get_local_time() == std::chrono::local_seconds{duration{42} - std::chrono::hours{1}});
+
+    std::same_as<zoned_time&> decltype(auto) _ = zt = local_time_point{duration{99}};
+    assert(zt.get_time_zone() == std::chrono::locate_zone("Etc/GMT+1"));
+    assert(zt.get_sys_time() == std::chrono::sys_seconds{duration{99} + std::chrono::hours{1}});
+    assert(zt.get_local_time() == std::chrono::local_seconds{duration{99}});
+  }
+  {
+    using duration         = std::chrono::weeks;
+    using sys_time_point   = std::chrono::sys_time<duration>;
+    using local_time_point = std::chrono::local_time<duration>;
+    using zoned_time       = std::chrono::zoned_time<duration>;
+    zoned_time zt{"Etc/GMT+1", sys_time_point{duration{42}}};
+
+    assert(zt.get_time_zone() == std::chrono::locate_zone("Etc/GMT+1"));
+    assert(zt.get_sys_time() == std::chrono::sys_seconds{duration{42}});
+    assert(zt.get_local_time() == std::chrono::local_seconds{duration{42} - std::chrono::hours{1}});
+
+    std::same_as<zoned_time&> decltype(auto) _ = zt = local_time_point{duration{99}};
+    assert(zt.get_time_zone() == std::chrono::locate_zone("Etc/GMT+1"));
+    assert(zt.get_sys_time() == std::chrono::sys_seconds{duration{99} + std::chrono::hours{1}});
+    assert(zt.get_local_time() == std::chrono::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         = std::chrono::months;
+    using sys_time_point   = std::chrono::sys_time<duration>;
+    using local_time_point = std::chrono::local_time<duration>;
+    using zoned_time       = std::chrono::zoned_time<duration>;
+    zoned_time zt{"Etc/GMT+1", sys_time_point{duration{42}}};
+
+    assert(zt.get_time_zone() == std::chrono::locate_zone("Etc/GMT+1"));
+    assert(zt.get_sys_time() == std::chrono::sys_seconds{duration{42}});
+    assert(zt.get_local_time() == std::chrono::local_seconds{duration{42} - std::chrono::hours{1}});
+
+    std::same_as<zoned_time&> decltype(auto) _ = zt = local_time_point{duration{99}};
+    assert(zt.get_time_zone() == std::chrono::locate_zone("Etc/GMT+1"));
+    assert(zt.get_sys_time() == std::chrono::sys_seconds{duration{99} + std::chrono::hours{1}});
+    assert(zt.get_local_time() == std::chrono::local_seconds{duration{99}});
+  } */
+}
+
+// Tests non-existant conversions.
+static void test_nonexistent() {
+  using namespace std::literals::chrono_literals;
+
+  const std::chrono::time_zone* tz = std::chrono::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.
+  std::chrono::local_time<std::chrono::seconds> time{
+      (std::chrono::sys_days{std::chrono::March / 30 / 1986} + 2h + 30min).time_since_epoch()};
+
+  using duration         = std::chrono::seconds;
+  using sys_time_point   = std::chrono::sys_time<duration>;
+  using local_time_point = std::chrono::local_time<duration>;
+  using zoned_time       = std::chrono::zoned_time<duration>;
+  zoned_time zt{tz};
+
+#ifndef TEST_NOEXCEPT
+  bool thrown = false;
+  try {
+    std::same_as<zoned_time&> decltype(auto) _ = zt = time;
+  } catch (const std::chrono::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
+}
+
+// Tests ambiguous conversions.
+static void test_ambiguous() {
+  using namespace std::literals::chrono_literals;
+
+  const std::chrono::time_zone* tz = std::chrono::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.
+  std::chrono::local_time<std::chrono::seconds> time{
+      (std::chrono::sys_days{std::chrono::September / 28 / 1986} + 2h + 30min).time_since_epoch()};
+
+  using duration         = std::chrono::seconds;
+  using sys_time_point   = std::chrono::sys_time<duration>;
+  using local_time_point = std::chrono::local_time<duration>;
+  using zoned_time       = std::chrono::zoned_time<duration>;
+  zoned_time zt{tz};
+
+#ifndef TEST_NOEXCEPT
+  bool thrown = false;
+  try {
+    std::same_as<zoned_time&> decltype(auto) _ = zt = time;
+  } catch (const std::chrono::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
+}
+
+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 0000000000000..ab824bce15447
--- /dev/null
+++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/assign.sys_time.pass.cpp
@@ -0,0 +1,134 @@
+//===----------------------------------------------------------------------===//
+//
+// 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& operator=(const sys_time<Duration>& st);
+
+#include <cassert>
+#include <chrono>
+#include <concepts>
+#include <type_traits>
+
+int main(int, char**) {
+  {
+    using duration   = std::chrono::nanoseconds;
+    using time_point = std::chrono::sys_time<duration>;
+    using zoned_time = std::chrono::zoned_time<duration>;
+    zoned_time zt{time_point{duration{42}}};
+
+    assert(zt.get_time_zone() == std::chrono::locate_zone("UTC"));
+    assert(zt.get_sys_time() == time_point{duration{42}});
+
+    std::same_as<zoned_time&> decltype(auto) _ = zt = time_point{duration{99}};
+    assert(zt.get_time_zone() == std::chrono::locate_zone("UTC"));
+    assert(zt.get_sys_time() == time_point{duration{99}});
+  }
+  {
+    using duration   = std::chrono::microseconds;
+    using time_point = std::chrono::sys_time<duration>;
+    using zoned_time = std::chrono::zoned_time<duration>;
+    zoned_time zt{time_point{duration{42}}};
+
+    assert(zt.get_time_zone() == std::chrono::locate_zone("UTC"));
+    assert(zt.get_sys_time() == time_point{duration{42}});
+
+    std::same_as<zoned_time&> decltype(auto) _ = zt = time_point{duration{99}};
+    assert(zt.get_time_zone() == std::chrono::locate_zone("UTC"));
+    assert(zt.get_sys_time() == time_point{duration{99}});
+  }
+  {
+    using duration   = std::chrono::milliseconds;
+    using time_point = std::chrono::sys_time<duration>;
+    using zoned_time = std::chrono::zoned_time<duration>;
+    zoned_time zt{time_point{duration{42}}};
+
+    assert(zt.get_time_zone() == std::chrono::locate_zone("UTC"));
+    assert(zt.get_sys_time() == time_point{duration{42}});
+
+    std::same_as<zoned_time&> decltype(auto) _ = zt = time_point{duration{99}};
+    assert(zt.get_time_zone() == std::chrono::locate_zone("UTC"));
+    assert(zt.get_sys_time() == time_point{duration{99}});
+  }
+  {
+    using duration   = std::chrono::seconds;
+    using time_point = std::chrono::sys_time<duration>;
+    using zoned_time = std::chrono::zoned_time<duration>;
+    zoned_time zt{time_point{duration{42}}};
+
+    assert(zt.get_time_zone() == std::chrono::locate_zone("UTC"));
+    assert(zt.get_sys_time() == time_point{duration{42}});
+
+    std::same_as<zoned_time&> decltype(auto) _ = zt = time_point{duration{99}};
+    assert(zt.get_time_zone() == std::chrono::locate_zone("UTC"));
+    assert(zt.get_sys_time() == time_point{duration{99}});
+  }
+  {
+    using duration   = std::chrono::days;
+    using time_point = std::chrono::sys_time<duration>;
+    using zoned_time = std::chrono::zoned_time<duration>;
+    zoned_time zt{time_point{duration{42}}};
+
+    assert(zt.get_time_zone() == std::chrono::locate_zone("UTC"));
+    assert(zt.get_sys_time() == time_point{duration{42}});
+
+    std::same_as<zoned_time&> decltype(auto) _ = zt = time_point{duration{99}};
+    assert(zt.get_time_zone() == std::chrono::locate_zone("UTC"));
+    assert(zt.get_sys_time() == time_point{duration{99}});
+  }
+  {
+    using duration   = std::chrono::weeks;
+    using time_point = std::chrono::sys_time<duration>;
+    using zoned_time = std::chrono::zoned_time<duration>;
+    zoned_time zt{time_point{duration{42}}};
+
+    assert(zt.get_time_zone() == std::chrono::locate_zone("UTC"));
+    assert(zt.get_sys_time() == time_point{duration{42}});
+
+    std::same_as<zoned_time&> decltype(auto) _ = zt = time_point{duration{99}};
+    assert(zt.get_time_zone() == std::chrono::locate_zone("UTC"));
+    assert(zt.get_sys_time() == time_point{duration{99}});
+  }
+  {
+    using duration   = std::chrono::months;
+    using time_point = std::chrono::sys_time<duration>;
+    using zoned_time = std::chrono::zoned_time<duration>;
+    zoned_time zt{time_point{duration{42}}};
+
+    assert(zt.get_time_zone() == std::chrono::locate_zone("UTC"));
+    assert(zt.get_sys_time() == time_point{duration{42}});
+
+    std::same_as<zoned_time&> decltype(auto) _ = zt = time_point{duration{99}};
+    assert(zt.get_time_zone() == std::chrono::locate_zone("UTC"));
+    assert(zt.get_sys_time() == time_point{duration{99}});
+  }
+  {
+    using duration   = std::chrono::years;
+    using time_point = std::chrono::sys_time<duration>;
+    using zoned_time = std::chrono::zoned_time<duration>;
+    zoned_time zt{time_point{duration{42}}};
+
+    assert(zt.get_time_zone() == std::chrono::locate_zone("UTC"));
+    assert(zt.get_sys_time() == time_point{duration{42}});
+
+    std::same_as<zoned_time&> decltype(auto) _ = zt = time_point{duration{99}};
+    assert(zt.get_time_zone() == std::chrono::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 0000000000000..2206692aba616
--- /dev/null
+++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.members/get_info.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------...
[truncated]

@mordante mordante force-pushed the users/mordante/zoned_time__members branch from 368f0d4 to ad83e31 Compare June 10, 2024 20:14
@mordante mordante force-pushed the users/mordante/zoned_time__constructor branch from e374d90 to 6d6dade Compare July 7, 2024 12:03
@mordante mordante force-pushed the users/mordante/zoned_time__members branch 2 times, most recently from 3dcb187 to 5195d39 Compare July 7, 2024 15:32
@ldionne ldionne added this to the LLVM 19.X Release milestone Jul 9, 2024
@ldionne ldionne self-assigned this Jul 9, 2024
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 with a few suggestions!

@mordante mordante force-pushed the users/mordante/zoned_time__constructor branch from 6d6dade to 59254ae Compare July 9, 2024 18:15
Base automatically changed from users/mordante/zoned_time__constructor to main July 9, 2024 18:15
Note the implementation of
  zoned_time& operator=(const local_time<Duration>& 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
@mordante mordante force-pushed the users/mordante/zoned_time__members branch from 5195d39 to dd3aa9c Compare July 10, 2024 05:51
@mordante mordante merged commit 0a95f2f into main Jul 10, 2024
52 of 54 checks passed
@mordante mordante deleted the users/mordante/zoned_time__members branch July 10, 2024 09:46
aaryanshukla pushed a commit to aaryanshukla/llvm-project that referenced this pull request Jul 14, 2024
Note the implementation of
  zoned_time& operator=(const local_time<Duration>& 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
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