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] Adds local_info formatter. #86256

Merged
merged 1 commit into from
Apr 18, 2024

Conversation

mordante
Copy link
Member

This adds the local_info type and its formatting options.
The usage of the local_info object will be done in separate patches.

Implements parts of:

  • P0355 Extending to Calendars and Time Zones
  • P1361 Integration of chrono with text formatting

@mordante mordante requested a review from a team as a code owner March 22, 2024 08:46
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Mar 22, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Mar 22, 2024

@llvm/pr-subscribers-libcxx

Author: Mark de Wever (mordante)

Changes

This adds the local_info type and its formatting options.
The usage of the local_info object will be done in separate patches.

Implements parts of:

  • P0355 Extending to Calendars and Time Zones
  • P1361 Integration of chrono with text formatting

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

12 Files Affected:

  • (modified) libcxx/docs/Status/FormatPaper.csv (+1-1)
  • (modified) libcxx/include/CMakeLists.txt (+1)
  • (modified) libcxx/include/__chrono/convert_to_tm.h (+3)
  • (modified) libcxx/include/__chrono/formatter.h (+20)
  • (added) libcxx/include/__chrono/local_info.h (+50)
  • (modified) libcxx/include/__chrono/ostream.h (+22)
  • (modified) libcxx/include/chrono (+16)
  • (modified) libcxx/include/libcxx.imp (+1)
  • (modified) libcxx/modules/std/chrono.inc (+1)
  • (added) libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp (+114)
  • (added) libcxx/test/std/time/time.syn/formatter.local_info.pass.cpp (+126)
  • (added) libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp (+51)
diff --git a/libcxx/docs/Status/FormatPaper.csv b/libcxx/docs/Status/FormatPaper.csv
index 32166ec72da753..b1a957c7b65dd1 100644
--- a/libcxx/docs/Status/FormatPaper.csv
+++ b/libcxx/docs/Status/FormatPaper.csv
@@ -25,7 +25,7 @@ Section,Description,Dependencies,Assignee,Status,First released version
 `[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::year_month_weekday_last``",,Mark de Wever,|Complete|,16.0
 `[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::hh_mm_ss<duration<Rep, Period>>``",,Mark de Wever,|Complete|,17.0
 `[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::sys_info``",,Mark de Wever,|Complete|,19.0
-`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::local_info``",A ``<chrono>`` implementation,Mark de Wever,,
+`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::local_info``",,Mark de Wever,|Complete|,19.0
 `[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::zoned_time<Duration, TimeZonePtr>``",A ``<chrono>`` implementation,Mark de Wever,,
 
 `P2286R8 <https://wg21.link/P2286R8>`__,"Formatting ranges"
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 2fc329d9e71457..a343e4c69c472c 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -283,6 +283,7 @@ set(files
   __chrono/high_resolution_clock.h
   __chrono/leap_second.h
   __chrono/literals.h
+  __chrono/local_info.h
   __chrono/month.h
   __chrono/month_weekday.h
   __chrono/monthday.h
diff --git a/libcxx/include/__chrono/convert_to_tm.h b/libcxx/include/__chrono/convert_to_tm.h
index d2c5cf922ba671..f7256db3bea661 100644
--- a/libcxx/include/__chrono/convert_to_tm.h
+++ b/libcxx/include/__chrono/convert_to_tm.h
@@ -16,6 +16,7 @@
 #include <__chrono/duration.h>
 #include <__chrono/file_clock.h>
 #include <__chrono/hh_mm_ss.h>
+#include <__chrono/local_info.h>
 #include <__chrono/month.h>
 #include <__chrono/month_weekday.h>
 #include <__chrono/monthday.h>
@@ -175,6 +176,8 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoT& __value) {
 #  if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)
   } else if constexpr (same_as<_ChronoT, chrono::sys_info>) {
     // Has no time information.
+  } else if constexpr (same_as<_ChronoT, chrono::local_info>) {
+    // Has no time information.
 #  endif
   } else
     static_assert(sizeof(_ChronoT) == 0, "Add the missing type specialization");
diff --git a/libcxx/include/__chrono/formatter.h b/libcxx/include/__chrono/formatter.h
index 79192fa103fbdb..a090eb0bfcc88a 100644
--- a/libcxx/include/__chrono/formatter.h
+++ b/libcxx/include/__chrono/formatter.h
@@ -18,6 +18,7 @@
 #include <__chrono/duration.h>
 #include <__chrono/file_clock.h>
 #include <__chrono/hh_mm_ss.h>
+#include <__chrono/local_info.h>
 #include <__chrono/month.h>
 #include <__chrono/month_weekday.h>
 #include <__chrono/monthday.h>
@@ -420,6 +421,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_ok(const _Tp& __value) {
 #  if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)
   else if constexpr (same_as<_Tp, chrono::sys_info>)
     return true;
+  else if constexpr (same_as<_Tp, chrono::local_info>)
+    return true;
 #  endif
   else
     static_assert(sizeof(_Tp) == 0, "Add the missing type specialization");
@@ -464,6 +467,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_name_ok(const _Tp& __value) {
 #  if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)
   else if constexpr (same_as<_Tp, chrono::sys_info>)
     return true;
+  else if constexpr (same_as<_Tp, chrono::local_info>)
+    return true;
 #  endif
   else
     static_assert(sizeof(_Tp) == 0, "Add the missing type specialization");
@@ -508,6 +513,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __date_ok(const _Tp& __value) {
 #  if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)
   else if constexpr (same_as<_Tp, chrono::sys_info>)
     return true;
+  else if constexpr (same_as<_Tp, chrono::local_info>)
+    return true;
 #  endif
   else
     static_assert(sizeof(_Tp) == 0, "Add the missing type specialization");
@@ -552,6 +559,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __month_name_ok(const _Tp& __value) {
 #  if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)
   else if constexpr (same_as<_Tp, chrono::sys_info>)
     return true;
+  else if constexpr (same_as<_Tp, chrono::local_info>)
+    return true;
 #  endif
   else
     static_assert(sizeof(_Tp) == 0, "Add the missing type specialization");
@@ -894,6 +903,17 @@ struct formatter<chrono::sys_info, _CharT> : public __formatter_chrono<_CharT> {
     return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__time_zone);
   }
 };
+
+template <__fmt_char_type _CharT>
+struct formatter<chrono::local_info, _CharT> : public __formatter_chrono<_CharT> {
+public:
+  using _Base = __formatter_chrono<_CharT>;
+
+  template <class _ParseContext>
+  _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) {
+    return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags{});
+  }
+};
 #  endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)
 
 #endif // if _LIBCPP_STD_VER >= 20
diff --git a/libcxx/include/__chrono/local_info.h b/libcxx/include/__chrono/local_info.h
new file mode 100644
index 00000000000000..b1a03ad7df2aca
--- /dev/null
+++ b/libcxx/include/__chrono/local_info.h
@@ -0,0 +1,50 @@
+// -*- 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_LOCAL_INFO_H
+#define _LIBCPP___CHRONO_LOCAL_INFO_H
+
+#include <version>
+// Enable the contents of the header only when libc++ was built with experimental features enabled.
+#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)
+
+#  include <__chrono/sys_info.h>
+#  include <__config>
+
+#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#    pragma GCC system_header
+#  endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#  if _LIBCPP_STD_VER >= 20
+
+namespace chrono {
+
+struct local_info {
+  static constexpr int unique      = 0;
+  static constexpr int nonexistent = 1;
+  static constexpr int ambiguous   = 2;
+
+  int result;
+  sys_info first;
+  sys_info second;
+};
+
+} // namespace chrono
+
+#  endif // _LIBCPP_STD_VER >= 20
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)
+
+#endif // _LIBCPP___CHRONO_LOCAL_INFO_H
diff --git a/libcxx/include/__chrono/ostream.h b/libcxx/include/__chrono/ostream.h
index 01608b8c29c9ce..2dfc3cde993ea6 100644
--- a/libcxx/include/__chrono/ostream.h
+++ b/libcxx/include/__chrono/ostream.h
@@ -15,6 +15,7 @@
 #include <__chrono/duration.h>
 #include <__chrono/file_clock.h>
 #include <__chrono/hh_mm_ss.h>
+#include <__chrono/local_info.h>
 #include <__chrono/month.h>
 #include <__chrono/month_weekday.h>
 #include <__chrono/monthday.h>
@@ -280,6 +281,27 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_info& __info) {
              __abbrev);
 }
 
+template <class _CharT, class _Traits>
+_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
+operator<<(basic_ostream<_CharT, _Traits>& __os, const local_info& __info) {
+  auto __result = [&] -> basic_string<_CharT> {
+    switch (__info.result) {
+    case local_info::unique:
+      return _LIBCPP_STATICALLY_WIDEN(_CharT, "unique");
+    case local_info::nonexistent:
+      return _LIBCPP_STATICALLY_WIDEN(_CharT, "non-existent");
+    case local_info::ambiguous:
+      return _LIBCPP_STATICALLY_WIDEN(_CharT, "ambiguous");
+
+    default:
+      return std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "unspecified result ({})"), __info.result);
+    };
+  };
+
+  return __os << std::format(
+             _LIBCPP_STATICALLY_WIDEN(_CharT, "{}: {{{}, {}}}"), __result(), __info.first, __info.second);
+}
+
 #  endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)
 
 } // namespace chrono
diff --git a/libcxx/include/chrono b/libcxx/include/chrono
index 91e57f7f4fb62b..53bcf452b3c629 100644
--- a/libcxx/include/chrono
+++ b/libcxx/include/chrono
@@ -737,6 +737,20 @@ template<class charT, class traits>
   basic_ostream<charT, traits>&
     operator<<(basic_ostream<charT, traits>& os, const sys_info& si);
 
+struct local_info {                                                             // C++20
+  static constexpr int unique      = 0;
+  static constexpr int nonexistent = 1;
+  static constexpr int ambiguous   = 2;
+
+  int result;
+  sys_info first;
+  sys_info second;
+};
+
+template<class charT, class traits>                                              // C++20
+  basic_ostream<charT, traits>&
+    operator<<(basic_ostream<charT, traits>& os, const local_info& li);
+
 // 25.10.5, class time_zone                                                      // C++20
 enum class choose {earliest, latest};
 class time_zone {
@@ -834,6 +848,7 @@ namespace std {
   template<class Rep, class Period, class charT>
     struct formatter<chrono::hh_mm_ss<duration<Rep, Period>>, charT>;             // C++20
   template<class charT> struct formatter<chrono::sys_info, charT>;                // C++20
+  template<class charT> struct formatter<chrono::local_info, charT>;              // C++20
 } // namespace std
 
 namespace chrono {
@@ -894,6 +909,7 @@ constexpr chrono::year                                  operator ""y(unsigned lo
 #include <__chrono/hh_mm_ss.h>
 #include <__chrono/high_resolution_clock.h>
 #include <__chrono/literals.h>
+#include <__chrono/local_info.h>
 #include <__chrono/month.h>
 #include <__chrono/month_weekday.h>
 #include <__chrono/monthday.h>
diff --git a/libcxx/include/libcxx.imp b/libcxx/include/libcxx.imp
index e3a08860c0b059..4bf24585bb5541 100644
--- a/libcxx/include/libcxx.imp
+++ b/libcxx/include/libcxx.imp
@@ -280,6 +280,7 @@
   { include: [ "<__chrono/high_resolution_clock.h>", "private", "<chrono>", "public" ] },
   { include: [ "<__chrono/leap_second.h>", "private", "<chrono>", "public" ] },
   { include: [ "<__chrono/literals.h>", "private", "<chrono>", "public" ] },
+  { include: [ "<__chrono/local_info.h>", "private", "<chrono>", "public" ] },
   { include: [ "<__chrono/month.h>", "private", "<chrono>", "public" ] },
   { include: [ "<__chrono/month_weekday.h>", "private", "<chrono>", "public" ] },
   { include: [ "<__chrono/monthday.h>", "private", "<chrono>", "public" ] },
diff --git a/libcxx/modules/std/chrono.inc b/libcxx/modules/std/chrono.inc
index 575e6347aecce1..1265e21dc54ef6 100644
--- a/libcxx/modules/std/chrono.inc
+++ b/libcxx/modules/std/chrono.inc
@@ -215,6 +215,7 @@ export namespace std {
 #    endif // if 0
 
     // [time.zone.info], information classes
+    using std::chrono::local_info;
     using std::chrono::sys_info;
 
 #    if 0
diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp
new file mode 100644
index 00000000000000..be3b14645e9e05
--- /dev/null
+++ b/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp
@@ -0,0 +1,114 @@
+//===----------------------------------------------------------------------===//
+//
+// 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-localization
+
+// TODO FMT This test should not require std::to_chars(floating-point)
+// XFAIL: availability-fp_to_chars-missing
+
+// XFAIL: libcpp-has-no-incomplete-tzdb
+
+// <chrono>
+
+// template<class charT, class traits>
+//   basic_ostream<charT, traits>&
+//     operator<<(basic_ostream<charT, traits>& os, const local_info& r);
+
+// [time.zone.info.local]
+//   7 Effects: Streams out the local_info object r in an unspecified format.
+//   8 Returns: os.
+//
+// Tests the output produced by this function.
+
+#include <cassert>
+#include <chrono>
+#include <memory>
+#include <sstream>
+
+#include "assert_macros.h"
+#include "test_macros.h"
+#include "make_string.h"
+#include "concat_macros.h"
+
+#define SV(S) MAKE_STRING_VIEW(CharT, S)
+
+template <class CharT>
+static void test(std::basic_string_view<CharT> expected, std::chrono::local_info&& info) {
+  std::basic_stringstream<CharT> sstr;
+  sstr << info;
+  std::basic_string<CharT> output = sstr.str();
+
+  TEST_REQUIRE(expected == output,
+               TEST_WRITE_CONCATENATED("\nExpected output ", expected, "\nActual output   ", output, '\n'));
+}
+
+template <class CharT>
+static void test() {
+  using namespace std::literals::chrono_literals;
+  namespace tz = std::chrono;
+  // result values matching the "known" results
+  test(SV("unique: "
+          "{[-10484-10-16 15:30:08, 14423-03-17 15:30:07) 00:00:00 0min TZ, "
+          "[1970-01-01 00:00:00, 1970-01-01 00:00:00) 00:00:00 0min }"),
+       tz::local_info{tz::local_info::unique,
+                      tz::sys_info{tz::sys_seconds::min(), tz::sys_seconds::max(), 0s, 0min, "TZ"},
+                      tz::sys_info{}});
+
+  test(SV("non-existent: "
+          "{[1970-01-01 00:00:00, 2038-12-31 00:00:00) 12:23:45 -67min NEG, "
+          "[1970-01-01 00:00:00, 2038-12-31 00:00:00) -12:23:45 67min POS}"),
+       tz::local_info{
+           tz::local_info::nonexistent,
+           tz::sys_info{static_cast<tz::sys_days>(tz::year_month_day{1970y, tz::January, 1d}),
+                        static_cast<tz::sys_days>(tz::year_month_day{2038y, tz::December, 31d}),
+                        12h + 23min + 45s,
+                        -67min,
+                        "NEG"},
+           tz::sys_info{static_cast<tz::sys_days>(tz::year_month_day{1970y, tz::January, 1d}),
+                        static_cast<tz::sys_days>(tz::year_month_day{2038y, tz::December, 31d}),
+                        -(12h + 23min + 45s),
+                        67min,
+                        "POS"}});
+
+  test(SV("ambiguous: "
+          "{[1970-01-01 00:00:00, 2038-12-31 00:00:00) 12:23:45 -67min NEG, "
+          "[1970-01-01 00:00:00, 2038-12-31 00:00:00) -12:23:45 67min POS}"),
+       tz::local_info{
+           tz::local_info::ambiguous,
+           tz::sys_info{static_cast<tz::sys_days>(tz::year_month_day{1970y, tz::January, 1d}),
+                        static_cast<tz::sys_days>(tz::year_month_day{2038y, tz::December, 31d}),
+                        12h + 23min + 45s,
+                        -67min,
+                        "NEG"},
+           tz::sys_info{static_cast<tz::sys_days>(tz::year_month_day{1970y, tz::January, 1d}),
+                        static_cast<tz::sys_days>(tz::year_month_day{2038y, tz::December, 31d}),
+                        -(12h + 23min + 45s),
+                        67min,
+                        "POS"}});
+
+  // result values not matching the "known" results
+  test(
+      SV("unspecified result (-1): "
+         "{[-10484-10-16 15:30:08, 14423-03-17 15:30:07) 00:00:00 0min TZ, "
+         "[1970-01-01 00:00:00, 1970-01-01 00:00:00) 00:00:00 0min }"),
+      tz::local_info{-1, tz::sys_info{tz::sys_seconds::min(), tz::sys_seconds::max(), 0s, 0min, "TZ"}, tz::sys_info{}});
+  test(SV("unspecified result (3): "
+          "{[-10484-10-16 15:30:08, 14423-03-17 15:30:07) 00:00:00 0min TZ, "
+          "[1970-01-01 00:00:00, 1970-01-01 00:00:00) 00:00:00 0min }"),
+       tz::local_info{3, tz::sys_info{tz::sys_seconds::min(), tz::sys_seconds::max(), 0s, 0min, "TZ"}, tz::sys_info{}});
+}
+
+int main(int, const char**) {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+
+  return 0;
+}
diff --git a/libcxx/test/std/time/time.syn/formatter.local_info.pass.cpp b/libcxx/test/std/time/time.syn/formatter.local_info.pass.cpp
new file mode 100644
index 00000000000000..4ae70dc6a4ecb0
--- /dev/null
+++ b/libcxx/test/std/time/time.syn/formatter.local_info.pass.cpp
@@ -0,0 +1,126 @@
+//===----------------------------------------------------------------------===//
+// 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-localization
+// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
+
+// TODO FMT This test should not require std::to_chars(floating-point)
+// XFAIL: availability-fp_to_chars-missing
+
+// XFAIL: libcpp-has-no-incomplete-tzdb
+
+// REQUIRES: locale.fr_FR.UTF-8
+
+// <chrono>
+//
+// template<class charT> struct formatter<chrono::local_info, charT>;
+
+#include <chrono>
+#include <format>
+
+#include <cassert>
+#include <concepts>
+#include <locale>
+#include <iostream>
+#include <type_traits>
+
+#include "formatter_tests.h"
+#include "make_string.h"
+#include "platform_support.h" // locale name macros
+#include "test_macros.h"
+
+template <class CharT>
+static void test_no_chrono_specs() {
+// This test libc++ specific due to
+// [time.zone.info.local]/3
+//   Effects: Streams out the local_info object r in an unspecified format.
+#ifdef _LIBCPP_VERSION
+  using namespace std::literals::chrono_literals;
+  namespace tz = std::chrono;
+
+  std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
+
+  // Non localized output
+
+  // result values matching the "known" results
+  check(SV("unique: "
+           "{[-10484-10-16 15:30:08, 14423-03-17 15:30:07) 00:00:00 0min TZ, "
+           "[1970-01-01 00:00:00, 1970-01-01 00:00:00) 00:00:00 0min }"),
+        SV("{}"),
+        tz::local_info{tz::local_info::unique,
+                       tz::sys_info{tz::sys_seconds::min(), tz::sys_seconds::max(), 0s, 0min, "TZ"},
+                       tz::sys_info{}});
+
+  check(SV("non-existent: "
+           "{[1970-01-01 00:00:00, 2038-12-31 00:00:00) 12:23:45 -67min NEG, "
+           "[1970-01-01 00:00:00, 2038-12-31 00:00:00) -12:23:45 67min POS}"),
+        SV("{}"),
+        tz::local_info{
+            tz::local_info::nonexistent,
+            tz::sys_info{static_cast<tz::sys_days>(tz::year_month_day{1970y, tz::January, 1d}),
+                         static_cast<tz::sys_days>(tz::year_month_day{2038y, tz::December, 31d}),
+                         12h + 23min + 45s,
+                         -67min,
+                         "NEG"},
+            tz::sys_info{static_cast<tz::sys_days>(tz::year_month_day{1970y, tz::January, 1d}),
+                         static_cast<tz::sys_days>(tz::year_month_day{2038y, tz::December, 31d}),
+                         -(12h + 23min + 45s),
+                         67min,
+                         "POS"}});
+
+  check(SV("ambiguous: "
+           "{[1970-01-01 00:00:00, 2038-12-31 00:00:00) 12:23:45 -67min NEG, "
+           "[1970-01-01 00:00:00, 2038-12-31 00:00:00) -12:23:45 67min POS}"),
+        SV("{}"),
+        tz::local_info{
+            tz::local_info::ambiguous,
+            tz::sys_info{static_cast<tz::sys_days>(tz::year_month_day{1970y, tz::January, 1d}),
+                         static_cast<tz::sys_days>(tz::year_month_day{2038y, tz::December, 31d}),
+                         12h + 23min + 45s,
+                         -67min,
+                         "NEG"},
+            tz::sys_info{static_cast<tz::sys_days>(tz::year_month_day{1970y, tz::January, 1d}),
+                         static_cast<tz::sys_days>(tz::year_month_day{2038y, tz::December, 31d}),
+                         -(12h + 23min + 45s),
+                         67min,
+                         "POS"}});
+
+  // result values not matching the "known" results
+  check(
+      SV("unspecified result (-1): "
+         "{[-10484-10-16 15:30:08, 14423-03-17 15:30:07) 00:00:00 0min TZ, "
+         "[1970-01-01 00:00:00, 1970-01-01 00:00:00) 00:00:00 0min }"),
+      SV("{}"),
+      tz::local_info{-1, tz::sys_info{tz::sys_seconds::min(), tz::sys_seconds::max(), 0s, 0min, "TZ"}, tz::sys_info{}});
+  check(
+      SV("unspecified result (3): "
+  ...
[truncated]

@mordante mordante force-pushed the users/mordante/adds_formatter_local_info branch 2 times, most recently from 358347b to 601338a Compare March 22, 2024 11:17
@mordante mordante force-pushed the users/mordante/adds_formatter_sys_info branch 3 times, most recently from e6ae1f0 to 96bc907 Compare April 13, 2024 11:44
@mordante mordante force-pushed the users/mordante/adds_formatter_local_info branch 2 times, most recently from 42728d0 to 73d01a3 Compare April 13, 2024 17:41
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 small comments.

@mordante mordante force-pushed the users/mordante/adds_formatter_sys_info branch from 96bc907 to c75ae7b Compare April 17, 2024 15:04
Base automatically changed from users/mordante/adds_formatter_sys_info to main April 17, 2024 18:55
Note the code using a local_info object will be done in a separate
commit.

Implements parts of:
- P0355 Extending to Calendars and Time Zones
- P1361 Integration of chrono with text formatting
@mordante mordante force-pushed the users/mordante/adds_formatter_local_info branch from 73d01a3 to 40cf6d9 Compare April 17, 2024 18:57
@mordante mordante merged commit 8a21d59 into main Apr 18, 2024
51 of 52 checks passed
@mordante mordante deleted the users/mordante/adds_formatter_local_info branch April 18, 2024 15:23
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.

None yet

3 participants