[libcxx-commits] [libcxx] [libc++][chrono] implements TAI clock. (PR #125550)
via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Feb 3 10:09:45 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Mark de Wever (mordante)
<details>
<summary>Changes</summary>
Implements parts of:
- P0355 Extending <chrono> to Calendars and Time Zones
- P1361 Integration of chrono with text formatting
- LWG3359 <chrono> leap second support should allow for negative leap seconds
---
Patch is 78.95 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/125550.diff
17 Files Affected:
- (modified) libcxx/docs/Status/FormatPaper.csv (+1-1)
- (modified) libcxx/include/CMakeLists.txt (+1)
- (modified) libcxx/include/__chrono/convert_to_tm.h (+13)
- (modified) libcxx/include/__chrono/formatter.h (+14)
- (modified) libcxx/include/__chrono/ostream.h (+7)
- (added) libcxx/include/__chrono/tai_clock.h (+98)
- (modified) libcxx/include/chrono (+31)
- (modified) libcxx/include/module.modulemap (+4)
- (modified) libcxx/modules/std/chrono.inc (+1-1)
- (modified) libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp (+11)
- (added) libcxx/test/std/time/time.clock/time.clock.tai/tai_time.ostream.pass.cpp (+164)
- (added) libcxx/test/std/time/time.clock/time.clock.tai/time.clock.tai.members/from_utc.pass.cpp (+159)
- (added) libcxx/test/std/time/time.clock/time.clock.tai/time.clock.tai.members/now.pass.cpp (+30)
- (added) libcxx/test/std/time/time.clock/time.clock.tai/time.clock.tai.members/to_utc.pass.cpp (+161)
- (added) libcxx/test/std/time/time.clock/time.clock.tai/types.compile.pass.cpp (+59)
- (added) libcxx/test/std/time/time.syn/formatter.tai_time.pass.cpp (+998)
- (modified) libcxx/test/support/concat_macros.h (+5)
``````````diff
diff --git a/libcxx/docs/Status/FormatPaper.csv b/libcxx/docs/Status/FormatPaper.csv
index 343fa62f135654..de64e9c25a7771 100644
--- a/libcxx/docs/Status/FormatPaper.csv
+++ b/libcxx/docs/Status/FormatPaper.csv
@@ -3,7 +3,7 @@ Section,Description,Dependencies,Assignee,Status,First released version
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::duration<Rep, Period>``",,Mark de Wever,|Complete|,16
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::sys_time<Duration>``",,Mark de Wever,|Complete|,17
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::utc_time<Duration>``",A ``<chrono>`` implementation,Mark de Wever,|Complete|,20
-`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::tai_time<Duration>``",A ``<chrono>`` implementation,Mark de Wever,,,
++`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::tai_time<Duration>``",,Mark de Wever,|Complete|,21
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::gps_time<Duration>``",A ``<chrono>`` implementation,Mark de Wever,,,
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::file_time<Duration>``",,Mark de Wever,|Complete|,17
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::local_time<Duration>``",,Mark de Wever,|Complete|,17
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 8dac823503d73f..ce805b4eb7b8b4 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -270,6 +270,7 @@ set(files
__chrono/steady_clock.h
__chrono/sys_info.h
__chrono/system_clock.h
+ __chrono/tai_clock.h
__chrono/time_point.h
__chrono/time_zone.h
__chrono/time_zone_link.h
diff --git a/libcxx/include/__chrono/convert_to_tm.h b/libcxx/include/__chrono/convert_to_tm.h
index 7d06a38d87f26d..934293ce382345 100644
--- a/libcxx/include/__chrono/convert_to_tm.h
+++ b/libcxx/include/__chrono/convert_to_tm.h
@@ -23,6 +23,7 @@
#include <__chrono/statically_widen.h>
#include <__chrono/sys_info.h>
#include <__chrono/system_clock.h>
+#include <__chrono/tai_clock.h>
#include <__chrono/time_point.h>
#include <__chrono/utc_clock.h>
#include <__chrono/weekday.h>
@@ -112,6 +113,16 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(chrono::utc_time<_Duration> __tp) {
return __result;
}
+template <class _Tm, class _Duration>
+_LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(chrono::tai_time<_Duration> __tp) {
+ using _Rp = common_type_t<_Duration, chrono::seconds>;
+ // The time between the TAI epoch (1958-01-01) and UNIX epoch (1970-01-01).
+ // This avoids leap second conversion when going from TAI to UTC.
+ // (It also avoids issues when the date is before the UTC epoch.)
+ constexpr chrono::seconds __offset{4383 * 24 * 60 * 60};
+ return std::__convert_to_tm<_Tm>(chrono::sys_time<_Rp>{__tp.time_since_epoch() - __offset});
+}
+
# endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
@@ -131,6 +142,8 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoT& __value) {
# if _LIBCPP_HAS_EXPERIMENTAL_TZDB
else if constexpr (same_as<typename _ChronoT::clock, chrono::utc_clock>)
return std::__convert_to_tm<_Tm>(__value);
+ else if constexpr (same_as<typename _ChronoT::clock, chrono::tai_clock>)
+ return std::__convert_to_tm<_Tm>(__value);
# endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
else if constexpr (same_as<typename _ChronoT::clock, chrono::file_clock>)
diff --git a/libcxx/include/__chrono/formatter.h b/libcxx/include/__chrono/formatter.h
index d17acd274e4cda..753a824a3c50d7 100644
--- a/libcxx/include/__chrono/formatter.h
+++ b/libcxx/include/__chrono/formatter.h
@@ -31,6 +31,7 @@
# include <__chrono/statically_widen.h>
# include <__chrono/sys_info.h>
# include <__chrono/system_clock.h>
+# include <__chrono/tai_clock.h>
# include <__chrono/time_point.h>
# include <__chrono/utc_clock.h>
# include <__chrono/weekday.h>
@@ -231,6 +232,8 @@ _LIBCPP_HIDE_FROM_ABI __time_zone __convert_to_time_zone([[maybe_unused]] const
# if _LIBCPP_HAS_EXPERIMENTAL_TZDB
if constexpr (same_as<_Tp, chrono::sys_info>)
return {__value.abbrev, __value.offset};
+ else if constexpr (__is_time_point<_Tp> && requires { requires same_as<typename _Tp::clock, chrono::tai_clock>; })
+ return {"TAI", chrono::seconds{0}};
# if _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
else if constexpr (__is_specialization_v<_Tp, chrono::zoned_time>)
return __formatter::__convert_to_time_zone(__value.get_info());
@@ -734,6 +737,17 @@ struct _LIBCPP_TEMPLATE_VIS formatter<chrono::utc_time<_Duration>, _CharT> : pub
}
};
+template <class _Duration, __fmt_char_type _CharT>
+struct _LIBCPP_TEMPLATE_VIS formatter<chrono::tai_time<_Duration>, _CharT> : public __formatter_chrono<_CharT> {
+public:
+ using _Base _LIBCPP_NODEBUG = __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::__clock);
+ }
+};
+
# endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
diff --git a/libcxx/include/__chrono/ostream.h b/libcxx/include/__chrono/ostream.h
index ed9ad8e346ba94..b8cd6a4680662b 100644
--- a/libcxx/include/__chrono/ostream.h
+++ b/libcxx/include/__chrono/ostream.h
@@ -26,6 +26,7 @@
# include <__chrono/statically_widen.h>
# include <__chrono/sys_info.h>
# include <__chrono/system_clock.h>
+# include <__chrono/tai_clock.h>
# include <__chrono/utc_clock.h>
# include <__chrono/weekday.h>
# include <__chrono/year.h>
@@ -71,6 +72,12 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const utc_time<_Duration>& __tp
return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp);
}
+template <class _CharT, class _Traits, class _Duration>
+_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
+operator<<(basic_ostream<_CharT, _Traits>& __os, const tai_time<_Duration>& __tp) {
+ return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp);
+}
+
# endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
diff --git a/libcxx/include/__chrono/tai_clock.h b/libcxx/include/__chrono/tai_clock.h
new file mode 100644
index 00000000000000..18ba329b7b8fb4
--- /dev/null
+++ b/libcxx/include/__chrono/tai_clock.h
@@ -0,0 +1,98 @@
+// -*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___CHRONO_TAI_CLOCK_H
+#define _LIBCPP___CHRONO_TAI_CLOCK_H
+
+#include <version>
+// Enable the contents of the header only when libc++ was built with experimental features enabled.
+#if _LIBCPP_HAS_EXPERIMENTAL_TZDB
+
+# include <__chrono/duration.h>
+# include <__chrono/time_point.h>
+# include <__chrono/utc_clock.h>
+# include <__config>
+# include <__type_traits/common_type.h>
+
+# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+# endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+# if _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
+
+namespace chrono {
+
+class tai_clock;
+
+template <class _Duration>
+using tai_time = time_point<tai_clock, _Duration>;
+using tai_seconds = tai_time<seconds>;
+
+// [time.clock.tai.overview]/1
+// The clock tai_clock measures seconds since 1958-01-01 00:00:00 and is
+// offset 10s ahead of UTC at this date. That is, 1958-01-01 00:00:00 TAI is
+// equivalent to 1957-12-31 23:59:50 UTC. Leap seconds are not inserted into
+// TAI. Therefore every time a leap second is inserted into UTC, UTC shifts
+// another second with respect to TAI. For example by 2000-01-01 there had
+// been 22 positive and 0 negative leap seconds inserted so 2000-01-01
+// 00:00:00 UTC is equivalent to 2000-01-01 00:00:32 TAI (22s plus the
+// initial 10s offset).
+//
+// Note this does not specify what the UTC offset before 1958-01-01 00:00:00
+// TAI is. However the member functions are fully specified in the standard.
+// https://koka-lang.github.io/koka/doc/std_time_utc.html contains more
+// information and references.
+class tai_clock {
+public:
+ using rep = utc_clock::rep;
+ using period = utc_clock::period;
+ using duration = chrono::duration<rep, period>;
+ using time_point = chrono::time_point<tai_clock>;
+ static constexpr bool is_steady = false; // The utc_clock is not steady.
+
+ // The static difference between UTC and TAI time.
+ static constexpr chrono::seconds __offset{378691210};
+
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static time_point now() { return from_utc(utc_clock::now()); }
+
+ template <class _Duration>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static utc_time<common_type_t<_Duration, seconds>>
+ to_utc(const tai_time<_Duration>& __time) noexcept {
+ using _Rp = common_type_t<_Duration, seconds>;
+ _Duration __time_since_epoch = __time.time_since_epoch();
+ _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__time_since_epoch >= utc_time<_Rp>::min().time_since_epoch() + __offset,
+ "the TAI to UTC conversion would underflow");
+
+ return utc_time<_Rp>{__time_since_epoch - __offset};
+ }
+
+ template <class _Duration>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static tai_time<common_type_t<_Duration, seconds>>
+ from_utc(const utc_time<_Duration>& __time) noexcept {
+ using _Rp = common_type_t<_Duration, seconds>;
+ _Duration __time_since_epoch = __time.time_since_epoch();
+ _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__time_since_epoch <= utc_time<_Rp>::max().time_since_epoch() - __offset,
+ "the UTC to TAI conversion would overflow");
+
+ return tai_time<_Rp>{__time_since_epoch + __offset};
+ }
+};
+
+} // namespace chrono
+
+# endif // _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM &&
+ // _LIBCPP_HAS_LOCALIZATION
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
+
+#endif // _LIBCPP___CHRONO_TAI_CLOCK_H
diff --git a/libcxx/include/chrono b/libcxx/include/chrono
index 10695eea649fb7..bd4c98600440c4 100644
--- a/libcxx/include/chrono
+++ b/libcxx/include/chrono
@@ -335,6 +335,34 @@ struct leap_second_info { // C++20
template<class Duration> // C++20
leap_second_info get_leap_second_info(const utc_time<Duration>& ut);
+
+// [time.clock.tai], class tai_clock
+class tai_clock { // C++20
+public:
+ using rep = a signed arithmetic type;
+ using period = ratio<unspecified, unspecified>;
+ using duration = chrono::duration<rep, period>;
+ using time_point = chrono::time_point<tai_clock>;
+ static constexpr bool is_steady = unspecified;
+
+ static time_point now();
+
+ template<class Duration>
+ static utc_time<common_type_t<Duration, seconds>>
+ to_utc(const tai_time<Duration>& t);
+ template<class Duration>
+ static tai_time<common_type_t<Duration, seconds>>
+ from_utc(const utc_time<Duration>& t);
+};
+
+template<class Duration>
+using tai_time = time_point<tai_clock, Duration>; // C++20
+using tai_seconds = tai_time<seconds>; // C++20
+
+template<class charT, class traits, class Duration> // C++20
+ basic_ostream<charT, traits>&
+ operator<<(basic_ostream<charT, traits>& os, const tai_time<Duration>& t);
+
class file_clock // C++20
{
public:
@@ -898,6 +926,8 @@ namespace std {
struct formatter<chrono::sys_time<Duration>, charT>; // C++20
template<class Duration, class charT>
struct formatter<chrono::utc_time<Duration>, charT>; // C++20
+ template<class Duration, class charT>
+ struct formatter<chrono::tai_time<Duration>, charT>; // C++20
template<class Duration, class charT>
struct formatter<chrono::filetime<Duration>, charT>; // C++20
template<class Duration, class charT>
@@ -1014,6 +1044,7 @@ constexpr chrono::year operator ""y(unsigned lo
# if _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
# include <__chrono/leap_second.h>
+# include <__chrono/tai_clock.h>
# include <__chrono/time_zone.h>
# include <__chrono/time_zone_link.h>
# include <__chrono/tzdb.h>
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 4bae02137b37b2..fd39c946b992a4 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -967,6 +967,10 @@ module std [system] {
header "__chrono/system_clock.h"
export std.chrono.time_point
}
+ module tai_clock {
+ header "__chrono/tai_clock.h"
+ export std.chrono.time_point
+ }
module time_point { header "__chrono/time_point.h" }
module time_zone_link { header "__chrono/time_zone_link.h" }
module time_zone { header "__chrono/time_zone.h" }
diff --git a/libcxx/modules/std/chrono.inc b/libcxx/modules/std/chrono.inc
index 98f14f716c2078..43e8da36e90448 100644
--- a/libcxx/modules/std/chrono.inc
+++ b/libcxx/modules/std/chrono.inc
@@ -97,13 +97,13 @@ export namespace std {
using std::chrono::get_leap_second_info;
-# if 0
// [time.clock.tai], class tai_clock
using std::chrono::tai_clock;
using std::chrono::tai_seconds;
using std::chrono::tai_time;
+# if 0
// [time.clock.gps], class gps_clock
using std::chrono::gps_clock;
diff --git a/libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp b/libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp
index 644c5b598c018d..bb40e0cfc4e1b8 100644
--- a/libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp
@@ -102,4 +102,15 @@ void test(std::chrono::time_zone tz, std::chrono::time_zone_link link, std::chro
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}}
}
+
+ { // [time.clock.tai]
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::chrono::tai_clock::now();
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::chrono::tai_clock::to_utc(std::chrono::tai_seconds{});
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::chrono::tai_clock::from_utc(std::chrono::utc_seconds{});
+ }
}
diff --git a/libcxx/test/std/time/time.clock/time.clock.tai/tai_time.ostream.pass.cpp b/libcxx/test/std/time/time.clock/time.clock.tai/tai_time.ostream.pass.cpp
new file mode 100644
index 00000000000000..3508ceb8b2d3f6
--- /dev/null
+++ b/libcxx/test/std/time/time.clock/time.clock.tai/tai_time.ostream.pass.cpp
@@ -0,0 +1,164 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
+// 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
+// XFAIL: availability-tzdb-missing
+
+// REQUIRES: locale.fr_FR.UTF-8
+// REQUIRES: locale.ja_JP.UTF-8
+
+// <chrono>
+
+// class taitem_clock;
+
+// template<class charT, class traits, class Duration>
+// basic_ostream<charT, traits>&
+// operator<<(basic_ostream<charT, traits>& os, const tai_time<Duration>& tp);
+
+#include <chrono>
+#include <cassert>
+#include <ratio>
+#include <sstream>
+
+#include "make_string.h"
+#include "platform_support.h" // locale name macros
+#include "test_macros.h"
+
+#define SV(S) MAKE_STRING_VIEW(CharT, S)
+
+template <class CharT, class Duration>
+static std::basic_string<CharT> stream_c_locale(std::chrono::tai_time<Duration> time_point) {
+ std::basic_stringstream<CharT> sstr;
+ sstr << std::fixed << time_point;
+ return sstr.str();
+}
+
+template <class CharT, class Duration>
+static std::basic_string<CharT> stream_fr_FR_locale(std::chrono::tai_time<Duration> time_point) {
+ std::basic_stringstream<CharT> sstr;
+ const std::locale locale(LOCALE_fr_FR_UTF_8);
+ sstr.imbue(locale);
+ sstr << std::fixed << time_point;
+ return sstr.str();
+}
+
+template <class CharT, class Duration>
+static std::basic_string<CharT> stream_ja_JP_locale(std::chrono::tai_time<Duration> time_point) {
+ std::basic_stringstream<CharT> sstr;
+ const std::locale locale(LOCALE_ja_JP_UTF_8);
+ sstr.imbue(locale);
+ sstr << std::fixed << time_point;
+ return sstr.str();
+}
+
+template <class CharT>
+static void test_c() {
+ using namespace std::literals::chrono_literals;
+ namespace cr = std::chrono;
+
+ assert(stream_c_locale<CharT>(cr::tai_time<cr::nanoseconds>{946'688'523'123'456'789ns}) ==
+ SV("1988-01-01 01:02:03.123456789"));
+ assert(stream_c_locale<CharT>(cr::tai_time<cr::microseconds>{946'688'523'123'456us}) ==
+ SV("1988-01-01 01:02:03.123456"));
+
+ assert(stream_c_locale<CharT>(cr::tai_time<cr::milliseconds>{946'684'822'123ms}) == SV("1988-01-01 00:00:22.123"));
+ assert(stream_c_locale<CharT>(cr::tai_seconds{1'234'567'890s}) == SV("1997-02-13 23:31:30"));
+ assert(stream_c_locale<CharT>(cr::tai_time<cr::minutes>{20'576'131min}) == SV("1997-02-13 23:31:00"));
+ assert(stream_c_locale<CharT>(cr::tai_time<cr::hours>{342'935h}) == SV("1997-02-13 23:00:00"));
+
+ assert(stream_c_locale<CharT>(cr::tai_time<cr::duration<signed char, std::ratio<2, 1>>>{
+ cr::duration<signed char, std::ratio<2, 1>>{60}}) == SV("1958-01-01 00:02:00"));
+ assert(stream_c_locale<CharT>(cr::tai_time<cr::duration<short, std::ratio<1, 2>>>{
+ cr::duration<short, std::ratio<1, 2>>{3600}}) == SV("1958-01-01 00:30:00.0"));
+ assert(stream_c_locale<CharT>(cr::tai_time<cr::duration<int, std::ratio<1, 4>>>{
+ cr::duration<int, std::ratio<1, 4>>{3600}}) == SV("1958-01-01 00:15:00.00"));
+ assert(stream_c_locale<CharT>(cr::tai_time<cr::duration<long, std::ratio<1, 10>>>{
+ cr::duration<long, std::ratio<1, 10>>{36611}}) == SV("1958-01-01 01:01:01.1"));
+ assert(stream_c_locale<CharT>(cr::tai_time<cr::duration<long long, std::ratio<1, 100>>>{
+ cr::duration<long long, std::ratio<1, 100>>{12'345'678'9010}}) == SV("1997-02-13 23:31:30.10"));
+}
+
+template <class CharT>
+static void test_fr_FR() {
+ using namespace std::literals::chrono_literals;
+ namespace cr = std::chrono;
+
+ assert(stream_fr_FR_locale<CharT>(cr::tai_time<cr::nanoseconds>{946'688'523'123'456'789ns}) ==
+ SV("1988-01-01 01:02:03,123456789"));
+ assert(stream_fr_FR_locale<CharT>(cr::tai_time<cr::microseconds>{946'688'523'123'456us}) ==
+ SV("1988-01-01 01:02:03,123456"));
+
+ assert(stream_fr_FR_locale<CharT>(cr::tai_time<cr::milliseconds>{946'684'822'123ms}) ==
+ SV("1988-01-01 00:00:22,123"));
+ assert(str...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/125550
More information about the libcxx-commits
mailing list