Skip to content

[libc++][TZDB] Finishes zoned_time constructors. #95010

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
Jul 9, 2024

Conversation

mordante
Copy link
Member

Completes

  • LWG3225 zoned_time converting constructor shall not be noexcept
  • LWG3226 zoned_time constructor from string_view should accept zoned_time<Duration2, TimeZonePtr2>

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 17:00
@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

Completes

  • LWG3225 zoned_time converting constructor shall not be noexcept
  • LWG3226 zoned_time constructor from string_view should accept zoned_time<Duration2, TimeZonePtr2>

Implements parts of:

  • P0355 Extending to chrono Calendars and Time Zones

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

14 Files Affected:

  • (modified) libcxx/docs/Status/Cxx20Issues.csv (+2-2)
  • (modified) libcxx/include/__chrono/zoned_time.h (+64-3)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_local_time.pass.cpp (+82)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_local_time_choose.pass.cpp (+107)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_sys_time.pass.cpp (+82)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_zoned_time_duration2_time_zone_ptr2.pass.cpp (+180)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_zoned_time_duration2_time_zone_ptr2_choose.pass.cpp (+191)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_pointer_local_time.pass.cpp (+80)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_pointer_local_time_choose.pass.cpp (+109)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_pointer_sys_time.pass.cpp (+86)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_ptr_zoned_time_duration2_time_zone_ptr2.pass.cpp (+113)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/time_zone_ptr_zoned_time_duration2_time_zone_ptr2_choose.pass.cpp (+121)
  • (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/zoned_time_duration2.pass.cpp (+92)
  • (modified) libcxx/test/support/test_offset_time_zone.h (+9)
diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv
index d4db7876cb2ef..5051a2089c98e 100644
--- a/libcxx/docs/Status/Cxx20Issues.csv
+++ b/libcxx/docs/Status/Cxx20Issues.csv
@@ -162,7 +162,7 @@
 "`3209 <https://wg21.link/LWG3209>`__","Expression in ``year::ok()``\  returns clause is ill-formed","Cologne","|Complete|",""
 "","","","","",""
 "`3231 <https://wg21.link/LWG3231>`__","``year_month_day_last::day``\  specification does not cover ``!ok()``\  values","Belfast","|Nothing To Do|",""
-"`3225 <https://wg21.link/LWG3225>`__","``zoned_time``\  converting constructor shall not be ``noexcept``\ ","Belfast","","","|chrono|"
+"`3225 <https://wg21.link/LWG3225>`__","``zoned_time``\  converting constructor shall not be ``noexcept``\ ","Belfast","|Complete|","19.0","|chrono|"
 "`3190 <https://wg21.link/LWG3190>`__","``std::allocator::allocate``\  sometimes returns too little storage","Belfast","|Complete|","14.0"
 "`3218 <https://wg21.link/LWG3218>`__","Modifier for ``%d``\  parse flag does not match POSIX and ``format``\  specification","Belfast","","","|chrono| |format|"
 "`3224 <https://wg21.link/LWG3224>`__","``zoned_time``\  constructor from ``TimeZonePtr``\  does not specify initialization of ``tp_``\ ","Belfast","|Complete|","19.0","|chrono|"
@@ -199,7 +199,7 @@
 "`3194 <https://wg21.link/LWG3194>`__","``ConvertibleTo``\  prose does not match code","Prague","|Complete|","13.0"
 "`3200 <https://wg21.link/LWG3200>`__","``midpoint``\  should not constrain ``T``\  is complete","Prague","|Nothing To Do|",""
 "`3201 <https://wg21.link/LWG3201>`__","``lerp``\  should be marked as ``noexcept``\ ","Prague","|Complete|",""
-"`3226 <https://wg21.link/LWG3226>`__","``zoned_time``\  constructor from ``string_view``\  should accept ``zoned_time<Duration2, TimeZonePtr2>``\ ","Prague","","","|chrono|"
+"`3226 <https://wg21.link/LWG3226>`__","``zoned_time``\  constructor from ``string_view``\  should accept ``zoned_time<Duration2, TimeZonePtr2>``\ ","Prague","|Complete|","19.0","|chrono|"
 "`3233 <https://wg21.link/LWG3233>`__","Broken requirements for ``shared_ptr``\  converting constructors","Prague","|Complete|","19.0"
 "`3237 <https://wg21.link/LWG3237>`__","LWG 3038 and 3190 have inconsistent PRs","Prague","|Complete|","16.0"
 "`3238 <https://wg21.link/LWG3238>`__","Insufficiently-defined behavior of ``std::function``\  deduction guides","Prague","|Nothing To Do|",""
diff --git a/libcxx/include/__chrono/zoned_time.h b/libcxx/include/__chrono/zoned_time.h
index f7510c9121a59..02945270cec7c 100644
--- a/libcxx/include/__chrono/zoned_time.h
+++ b/libcxx/include/__chrono/zoned_time.h
@@ -56,6 +56,10 @@ class zoned_time {
   static_assert(__is_duration<_Duration>::value,
                 "the program is ill-formed since _Duration is not a specialization of std::chrono::duration");
 
+  // There are several constraints like
+  //   constructible_from<zoned_time, decltype(__traits::locate_zone(string_view{}))>
+  // This would create a dependency on itself. Instead depend on the fact an
+  // constructor overload taking a _TimeZonePtr is present.
   using __traits = zoned_traits<_TimeZonePtr>;
 
 public:
@@ -76,12 +80,69 @@ class zoned_time {
 
   _LIBCPP_HIDE_FROM_ABI explicit zoned_time(string_view __name)
     requires(requires { __traits::locate_zone(string_view{}); } &&
-             // constructible_from<zoned_time, decltype(__traits::locate_zone(string_view{}))>
-             // would create a dependency on itself. Instead depend on the fact
-             // a constructor taking a _TimeZonePtr exists.
              constructible_from<_TimeZonePtr, decltype(__traits::locate_zone(string_view{}))>)
       : __zone_{__traits::locate_zone(__name)}, __tp_{} {}
 
+  template <class _Duration2>
+  _LIBCPP_HIDE_FROM_ABI zoned_time(const zoned_time<_Duration2, _TimeZonePtr>& __zt)
+    requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>
+      : __zone_{__zt.get_time_zone()}, __tp_{__zt.get_sys_time()} {}
+
+  _LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const sys_time<_Duration>& __tp)
+      : __zone_{std::move(__zone)}, __tp_{__tp} {}
+
+  _LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const sys_time<_Duration>& __tp)
+    requires requires { _TimeZonePtr{__traits::locate_zone(string_view{})}; }
+      : zoned_time{__traits::locate_zone(__name), __tp} {}
+
+  _LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const local_time<_Duration>& __tp)
+    requires(is_convertible_v<decltype(declval<_TimeZonePtr&>() -> to_sys(local_time<_Duration>{})),
+                              sys_time<duration>>)
+      : __zone_{std::move(__zone)}, __tp_{__zone_->to_sys(__tp)} {}
+
+  _LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const local_time<_Duration>& __tp)
+    requires(requires {
+      _TimeZonePtr{__traits::locate_zone(string_view{})};
+    } && is_convertible_v<decltype(declval<_TimeZonePtr&>() -> to_sys(local_time<_Duration>{})), sys_time<duration>>)
+      : zoned_time{__traits::locate_zone(__name), __tp} {}
+
+  _LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const local_time<_Duration>& __tp, choose __c)
+    requires(is_convertible_v<decltype(declval<_TimeZonePtr&>() -> to_sys(local_time<_Duration>{}, choose::earliest)),
+                              sys_time<duration>>)
+      : __zone_{std::move(__zone)}, __tp_{__zone_->to_sys(__tp, __c)} {}
+
+  _LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const local_time<_Duration>& __tp, choose __c)
+    requires(requires {
+      _TimeZonePtr{__traits::locate_zone(string_view{})};
+    } && is_convertible_v<decltype(declval<_TimeZonePtr&>() -> to_sys(local_time<_Duration>{}, choose::earliest)),
+                          sys_time<duration>>)
+      : zoned_time{__traits::locate_zone(__name), __tp, __c} {}
+
+  template <class _Duration2, class _TimeZonePtr2>
+  _LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const zoned_time<_Duration2, _TimeZonePtr2>& __zt)
+    requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>
+      : __zone_{std::move(__zone)}, __tp_{__zt.get_sys_time()} {}
+
+  // per wording choose has no effect
+  template <class _Duration2, class _TimeZonePtr2>
+  _LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const zoned_time<_Duration2, _TimeZonePtr2>& __zt, choose)
+    requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>
+      : __zone_{std::move(__zone)}, __tp_{__zt.get_sys_time()} {}
+
+  template <class _Duration2, class _TimeZonePtr2>
+  _LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const zoned_time<_Duration2, _TimeZonePtr2>& __zt)
+    requires(requires {
+      _TimeZonePtr{__traits::locate_zone(string_view{})};
+    } && is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>)
+      : zoned_time{__traits::locate_zone(__name), __zt} {}
+
+  template <class _Duration2, class _TimeZonePtr2>
+  _LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const zoned_time<_Duration2, _TimeZonePtr2>& __zt, choose __c)
+    requires(requires {
+      _TimeZonePtr{__traits::locate_zone(string_view{})};
+    } && is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>)
+      : zoned_time{__traits::locate_zone(__name), __zt, __c} {}
+
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _TimeZonePtr get_time_zone() const { return __zone_; }
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI sys_time<duration> get_sys_time() const { return __tp_; }
 
diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_local_time.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_local_time.pass.cpp
new file mode 100644
index 0000000000000..ff3b3af697fb2
--- /dev/null
+++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_local_time.pass.cpp
@@ -0,0 +1,82 @@
+//===----------------------------------------------------------------------===//
+//
+// 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(string_view name, const local_time<Duration>& st);
+
+#include <chrono>
+#include <concepts>
+
+#include "test_offset_time_zone.h"
+
+// Verify the results of the constructed object.
+int main(int, char**) {
+  {
+    using ptr = const std::chrono::time_zone*;
+    static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>,
+                                          std::string_view,
+                                          std::chrono::sys_seconds>);
+
+    std::chrono::zoned_time<std::chrono::seconds> zt{"Etc/GMT+1", std::chrono::local_seconds{std::chrono::seconds{0}}};
+
+    assert(zt.get_time_zone() == std::chrono::locate_zone("Etc/GMT+1"));
+    assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::hours{1}});
+  }
+
+  {
+    using ptr = offset_time_zone<offset_time_zone_flags::none>;
+    static_assert(!std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>,
+                                           std::string_view,
+                                           std::chrono::local_seconds>);
+  }
+
+  {
+    using ptr = offset_time_zone<offset_time_zone_flags::has_default_zone>;
+    static_assert(!std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>,
+                                           std::string_view,
+                                           std::chrono::local_seconds>);
+  }
+
+  {
+    using ptr = offset_time_zone<offset_time_zone_flags::has_locate_zone>;
+    static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>,
+                                          std::string_view,
+                                          std::chrono::local_seconds>);
+
+    ptr tz;
+    std::chrono::zoned_time<std::chrono::seconds, ptr> zt{"42", std::chrono::local_seconds{std::chrono::seconds{99}}};
+
+    assert(zt.get_time_zone().offset() == std::chrono::seconds{42});
+    assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{141}});
+  }
+
+  {
+    using ptr = offset_time_zone<offset_time_zone_flags::both>;
+    static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>,
+                                          std::string_view,
+                                          std::chrono::local_seconds>);
+
+    ptr tz;
+    std::chrono::zoned_time<std::chrono::seconds, ptr> zt{"42", std::chrono::local_seconds{std::chrono::seconds{99}}};
+
+    assert(zt.get_time_zone().offset() == std::chrono::seconds{42});
+    assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{141}});
+  }
+
+  return 0;
+}
diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_local_time_choose.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_local_time_choose.pass.cpp
new file mode 100644
index 0000000000000..f0d8e0954efd4
--- /dev/null
+++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_local_time_choose.pass.cpp
@@ -0,0 +1,107 @@
+//===----------------------------------------------------------------------===//
+//
+// 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(string_view name, const local_time<Duration>& st, choose c);
+
+#include <chrono>
+#include <concepts>
+#include <cassert>
+
+#include "test_offset_time_zone.h"
+
+int main(int, char**) {
+  // 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.
+  {
+    using ptr = const std::chrono::time_zone*;
+    std::chrono::zoned_time<std::chrono::seconds> zt{
+        "Etc/GMT+1", std::chrono::local_seconds{std::chrono::seconds{0}}, std::chrono::choose::earliest};
+
+    assert(zt.get_time_zone() == std::chrono::locate_zone("Etc/GMT+1"));
+    assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::hours{1}});
+  }
+
+  // Tests ambiguous conversions.
+  {
+    // 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 -
+
+    using namespace std::literals::chrono_literals;
+    using ptr = const std::chrono::time_zone*;
+    {
+      std::chrono::zoned_time<std::chrono::seconds> zt{
+          "Europe/Berlin",
+          std::chrono::local_seconds{
+              (std::chrono::sys_days{std::chrono::September / 28 / 1986} + 2h + 30min).time_since_epoch()},
+          std::chrono::choose::earliest};
+
+      assert(zt.get_time_zone() == std::chrono::locate_zone("Europe/Berlin"));
+      assert(zt.get_sys_time() == std::chrono::sys_days{std::chrono::September / 28 / 1986} + 0h + 30min);
+    }
+    {
+      std::chrono::zoned_time<std::chrono::seconds> zt{
+          "Europe/Berlin",
+          std::chrono::local_seconds{
+              (std::chrono::sys_days{std::chrono::September / 28 / 1986} + 2h + 30min).time_since_epoch()},
+          std::chrono::choose::latest};
+
+      assert(zt.get_time_zone() == std::chrono::locate_zone("Europe/Berlin"));
+      assert(zt.get_sys_time() == std::chrono::sys_days{std::chrono::September / 28 / 1986} + 1h + 30min);
+    }
+  }
+
+  static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>,
+                                        std::string_view,
+                                        std::chrono::local_seconds,
+                                        std::chrono::choose>);
+
+  static_assert(!std::constructible_from<
+                std::chrono::zoned_time<std::chrono::seconds, offset_time_zone<offset_time_zone_flags::none>>,
+                std::string_view,
+                std::chrono::local_seconds,
+                std::chrono::choose>);
+
+  static_assert(
+      !std::constructible_from<
+          std::chrono::zoned_time<std::chrono::seconds, offset_time_zone<offset_time_zone_flags::has_default_zone>>,
+          std::string_view,
+          std::chrono::local_seconds,
+          std::chrono::choose>);
+
+  static_assert(
+      !std::constructible_from<
+          std::chrono::zoned_time<std::chrono::seconds, offset_time_zone<offset_time_zone_flags::has_locate_zone>>,
+          std::string_view,
+          std::chrono::local_seconds,
+          std::chrono::choose>);
+
+  static_assert(!std::constructible_from<
+                std::chrono::zoned_time<std::chrono::seconds, offset_time_zone<offset_time_zone_flags::both>>,
+                std::string_view,
+                std::chrono::local_seconds,
+                std::chrono::choose>);
+
+  return 0;
+}
diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_sys_time.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_sys_time.pass.cpp
new file mode 100644
index 0000000000000..5f29b5a83e10d
--- /dev/null
+++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_sys_time.pass.cpp
@@ -0,0 +1,82 @@
+//===----------------------------------------------------------------------===//
+//
+// 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(string_view name, const sys_time<Duration>& st);
+
+#include <chrono>
+#include <concepts>
+
+#include "test_offset_time_zone.h"
+
+// Verify the results of the constructed object.
+int main(int, char**) {
+  {
+    using ptr = const std::chrono::time_zone*;
+    static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>,
+                                          std::string_view,
+                                          std::chrono::sys_seconds>);
+
+    std::chrono::zoned_time<std::chrono::seconds> zt{"UTC", std::chrono::sys_seconds{std::chrono::seconds{99}}};
+
+    assert(zt.get_time_zone() == std::chrono::locate_zone("UTC"));
+    assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{99}});
+  }
+
+  {
+    using ptr = offset_time_zone<offset_time_zone_flags::none>;
+    static_assert(!std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>,
+                                           std::string_view,
+                                           std::chrono::sys_seconds>);
+  }
+
+  {
+    using ptr = offset_time_zone<offset_time_zone_flags::has_default_zone>;
+    static_assert(!std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>,
+                                           std::string_view,
+                                           std::chrono::sys_seconds>);
+  }
+
+  {
+    using ptr = offset_time_zone<offset_time_zone_flags::has_locate_zone>;
+    static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>,
+                                          std::string_view,
+                                          std::chrono::sys_seconds>);
+
+    ptr tz;
+    std::chrono::zoned_time<std::chrono::seconds, ptr> zt{"42", std::chrono::sys_seconds{std::chrono::seconds{99}}};
+
+    assert(zt.get_time_zone().offset() == std::chrono::seconds{42});
+    assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{99}});
+  }
+
+  {
+    using ptr = offset_time_zone<offset_time_zone_flags::both>;
+    static_assert(std::constructible_from<std::chrono::zoned_time<std::chrono::seconds, ptr>,
+                                          std::string_view,
+                                          std::chrono::sys_seconds>);
+
+    ptr tz;
+    std::chrono::zoned_time<std::chrono::seconds, ptr> zt{"42", std::chrono::sys_seconds{std::chrono::seconds{99}}};
+
+    assert(zt.get_time_zone().offset() == std::chrono::seconds{42});
+    assert(zt.get_sys_time() == std::chrono::sys_seconds{std::chrono::seconds{99}});
+  }
+
+  return 0;
+}
diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_zoned_time_duration2_time_zone_ptr2.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_zoned_time_duration2_time_zone_ptr2.pass.cpp
new file mode 100644
index 0000000000000..d4efa14b85302
--- /dev/null
+++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.ctor/string_view_zoned_time_duration2_time_zone_ptr2.pass.cpp
@@ -0,0 +1,180 @@
+//===----------------------------------------------------------------------===//
+//
+// 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-localizat...
[truncated]

@mordante mordante force-pushed the users/mordante/zoned_time__constructor branch 3 times, most recently from edac504 to e374d90 Compare June 10, 2024 18:16
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.

This generally LGTM but the constraints seem wrong, so I'd like to see again once that is figured out.

@h-vetinari
Copy link
Contributor

Peanut gallery comment: it would be very cool if zoned_time could make it for libcxx 19; 🤞
It's IMO one of the most useful classes in <chrono>.

@mordante mordante force-pushed the users/mordante/zoned_time__class branch from d0b2016 to 6beadca Compare July 7, 2024 10:08
Copy link
Member Author

@mordante mordante left a comment

Choose a reason for hiding this comment

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

Peanut gallery comment: it would be very cool if zoned_time could make it for libcxx 19; 🤞 It's IMO one of the most useful classes in <chrono>.

I hope to get zoned_time and the missing clocks ready before LLVM-19. However it will be closer to the deadline than I hoped.

@mordante mordante force-pushed the users/mordante/zoned_time__constructor branch from e374d90 to 6d6dade Compare July 7, 2024 12:03
@ldionne ldionne added this to the LLVM 19.X Release milestone Jul 9, 2024
Base automatically changed from users/mordante/zoned_time__class to main July 9, 2024 18:14
Completes
- LWG3225 zoned_time converting constructor shall not be noexcept
- LWG3226 zoned_time constructor from string_view should accept zoned_time<Duration2, TimeZonePtr2>

Implements parts of:
- P0355 Extending to chrono Calendars and Time Zones
@mordante mordante force-pushed the users/mordante/zoned_time__constructor branch from 6d6dade to 59254ae Compare July 9, 2024 18:15
@mordante mordante merged commit a1d73ac into main Jul 9, 2024
9 of 10 checks passed
@mordante mordante deleted the users/mordante/zoned_time__constructor branch July 9, 2024 18:15
aaryanshukla pushed a commit to aaryanshukla/llvm-project that referenced this pull request Jul 14, 2024
Completes
- LWG3225 zoned_time converting constructor shall not be noexcept
- LWG3226 zoned_time constructor from string_view should accept
zoned_time<Duration2, TimeZonePtr2>

Implements parts of:
- P0355 Extending to chrono Calendars and Time Zones
qiaojbao pushed a commit to GPUOpen-Drivers/llvm-project that referenced this pull request Aug 13, 2024
…bf34a3c95

Local branch amd-gfx df3bf34 Merged main:faa4e35c622c13c7a565b979a6676d6cf3040cd4 into amd-gfx:b65e986d8413
Remote branch main a1d73ac [libc++][TZDB] Finishes zoned_time constructors. (llvm#95010)
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.

4 participants