diff options
Diffstat (limited to 'libcxx/include/__chrono')
21 files changed, 1775 insertions, 312 deletions
diff --git a/libcxx/include/__chrono/convert_to_timespec.h b/libcxx/include/__chrono/convert_to_timespec.h index e8631d135fee..fab07f2567d4 100644 --- a/libcxx/include/__chrono/convert_to_timespec.h +++ b/libcxx/include/__chrono/convert_to_timespec.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___CHRONO_CONVERT_TO_TIMESPEC_H #define _LIBCPP___CHRONO_CONVERT_TO_TIMESPEC_H diff --git a/libcxx/include/__chrono/convert_to_tm.h b/libcxx/include/__chrono/convert_to_tm.h new file mode 100644 index 000000000000..36846b3f7140 --- /dev/null +++ b/libcxx/include/__chrono/convert_to_tm.h @@ -0,0 +1,127 @@ +// -*- 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_CONVERT_TO_TM_H +#define _LIBCPP___CHRONO_CONVERT_TO_TM_H + +#include <__chrono/day.h> +#include <__chrono/duration.h> +#include <__chrono/hh_mm_ss.h> +#include <__chrono/month.h> +#include <__chrono/month_weekday.h> +#include <__chrono/monthday.h> +#include <__chrono/statically_widen.h> +#include <__chrono/system_clock.h> +#include <__chrono/time_point.h> +#include <__chrono/weekday.h> +#include <__chrono/year.h> +#include <__chrono/year_month.h> +#include <__chrono/year_month_day.h> +#include <__chrono/year_month_weekday.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__memory/addressof.h> +#include <cstdint> +#include <ctime> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// Conerts a chrono date and weekday to a given _Tm type. +// +// This is an implementation detail for the function +// template <class _Tm, class _ChronoT> +// _Tm __convert_to_tm(const _ChronoT& __value) +// +// This manually converts the two values to the proper type. It is possible to +// convert from sys_days to time_t and then to _Tm. But this leads to the Y2K +// bug when time_t is a 32-bit signed integer. Chrono considers years beyond +// the year 2038 valid, so instead do the transformation manually. +template <class _Tm, class _Date> + requires(same_as<_Date, chrono::year_month_day> || same_as<_Date, chrono::year_month_day_last>) +_LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _Date& __date, chrono::weekday __weekday) { + _Tm __result = {}; +# ifdef __GLIBC__ + __result.tm_zone = "UTC"; +# endif + __result.tm_year = static_cast<int>(__date.year()) - 1900; + __result.tm_mon = static_cast<unsigned>(__date.month()) - 1; + __result.tm_mday = static_cast<unsigned>(__date.day()); + __result.tm_wday = static_cast<unsigned>(__weekday.c_encoding()); + __result.tm_yday = + (static_cast<chrono::sys_days>(__date) - + static_cast<chrono::sys_days>(chrono::year_month_day{__date.year(), chrono::January, chrono::day{1}})) + .count(); + + return __result; +} + +// Convert a chrono (calendar) time point, or dururation to the given _Tm type, +// which must have the same properties as std::tm. +template <class _Tm, class _ChronoT> +_LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoT& __value) { + _Tm __result = {}; +# ifdef __GLIBC__ + __result.tm_zone = "UTC"; +# endif + + if constexpr (chrono::__is_duration<_ChronoT>::value) { + // [time.format]/6 + // ... However, if a flag refers to a "time of day" (e.g. %H, %I, %p, + // etc.), then a specialization of duration is interpreted as the time of + // day elapsed since midnight. + uint64_t __sec = chrono::duration_cast<chrono::seconds>(__value).count(); + __sec %= 24 * 3600; + __result.tm_hour = __sec / 3600; + __sec %= 3600; + __result.tm_min = __sec / 60; + __result.tm_sec = __sec % 60; + } else if constexpr (same_as<_ChronoT, chrono::day>) + __result.tm_mday = static_cast<unsigned>(__value); + else if constexpr (same_as<_ChronoT, chrono::month>) + __result.tm_mon = static_cast<unsigned>(__value) - 1; + else if constexpr (same_as<_ChronoT, chrono::year>) + __result.tm_year = static_cast<int>(__value) - 1900; + else if constexpr (same_as<_ChronoT, chrono::weekday>) + __result.tm_wday = __value.c_encoding(); + else if constexpr (same_as<_ChronoT, chrono::weekday_indexed> || same_as<_ChronoT, chrono::weekday_last>) + __result.tm_wday = __value.weekday().c_encoding(); + else if constexpr (same_as<_ChronoT, chrono::month_day>) { + __result.tm_mday = static_cast<unsigned>(__value.day()); + __result.tm_mon = static_cast<unsigned>(__value.month()) - 1; + } else if constexpr (same_as<_ChronoT, chrono::month_day_last>) { + __result.tm_mon = static_cast<unsigned>(__value.month()) - 1; + } else if constexpr (same_as<_ChronoT, chrono::month_weekday> || same_as<_ChronoT, chrono::month_weekday_last>) { + __result.tm_wday = __value.weekday_indexed().weekday().c_encoding(); + __result.tm_mon = static_cast<unsigned>(__value.month()) - 1; + } else if constexpr (same_as<_ChronoT, chrono::year_month>) { + __result.tm_year = static_cast<int>(__value.year()) - 1900; + __result.tm_mon = static_cast<unsigned>(__value.month()) - 1; + } else if constexpr (same_as<_ChronoT, chrono::year_month_day> || same_as<_ChronoT, chrono::year_month_day_last>) { + return std::__convert_to_tm<_Tm>( + chrono::year_month_day{__value}, chrono::weekday{static_cast<chrono::sys_days>(__value)}); + } else if constexpr (same_as<_ChronoT, chrono::year_month_weekday> || + same_as<_ChronoT, chrono::year_month_weekday_last>) { + return std::__convert_to_tm<_Tm>(chrono::year_month_day{static_cast<chrono::sys_days>(__value)}, __value.weekday()); + } else + static_assert(sizeof(_ChronoT) == 0, "Add the missing type specialization"); + + return __result; +} + +#endif //if _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_CONVERT_TO_TM_H diff --git a/libcxx/include/__chrono/day.h b/libcxx/include/__chrono/day.h index d9fa4ffbc45e..35ecfcf9e5bd 100644 --- a/libcxx/include/__chrono/day.h +++ b/libcxx/include/__chrono/day.h @@ -27,18 +27,18 @@ namespace chrono class day { private: - unsigned char __d; + unsigned char __d_; public: _LIBCPP_HIDE_FROM_ABI day() = default; - _LIBCPP_HIDE_FROM_ABI explicit inline constexpr day(unsigned __val) noexcept : __d(static_cast<unsigned char>(__val)) {} - _LIBCPP_HIDE_FROM_ABI inline constexpr day& operator++() noexcept { ++__d; return *this; } + _LIBCPP_HIDE_FROM_ABI explicit inline constexpr day(unsigned __val) noexcept : __d_(static_cast<unsigned char>(__val)) {} + _LIBCPP_HIDE_FROM_ABI inline constexpr day& operator++() noexcept { ++__d_; return *this; } _LIBCPP_HIDE_FROM_ABI inline constexpr day operator++(int) noexcept { day __tmp = *this; ++(*this); return __tmp; } - _LIBCPP_HIDE_FROM_ABI inline constexpr day& operator--() noexcept { --__d; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr day& operator--() noexcept { --__d_; return *this; } _LIBCPP_HIDE_FROM_ABI inline constexpr day operator--(int) noexcept { day __tmp = *this; --(*this); return __tmp; } _LIBCPP_HIDE_FROM_ABI constexpr day& operator+=(const days& __dd) noexcept; _LIBCPP_HIDE_FROM_ABI constexpr day& operator-=(const days& __dd) noexcept; - _LIBCPP_HIDE_FROM_ABI explicit inline constexpr operator unsigned() const noexcept { return __d; } - _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __d >= 1 && __d <= 31; } + _LIBCPP_HIDE_FROM_ABI explicit inline constexpr operator unsigned() const noexcept { return __d_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __d_ >= 1 && __d_ <= 31; } }; diff --git a/libcxx/include/__chrono/duration.h b/libcxx/include/__chrono/duration.h index c502574fb267..afcc38b5cfc0 100644 --- a/libcxx/include/__chrono/duration.h +++ b/libcxx/include/__chrono/duration.h @@ -11,9 +11,12 @@ #define _LIBCPP___CHRONO_DURATION_H #include <__config> +#include <__type_traits/common_type.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_floating_point.h> #include <limits> #include <ratio> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -151,7 +154,7 @@ typename enable_if >::type floor(const duration<_Rep, _Period>& __d) { - _ToDuration __t = duration_cast<_ToDuration>(__d); + _ToDuration __t = chrono::duration_cast<_ToDuration>(__d); if (__t > __d) __t = __t - _ToDuration{1}; return __t; @@ -166,7 +169,7 @@ typename enable_if >::type ceil(const duration<_Rep, _Period>& __d) { - _ToDuration __t = duration_cast<_ToDuration>(__d); + _ToDuration __t = chrono::duration_cast<_ToDuration>(__d); if (__t < __d) __t = __t + _ToDuration{1}; return __t; @@ -181,7 +184,7 @@ typename enable_if >::type round(const duration<_Rep, _Period>& __d) { - _ToDuration __lower = floor<_ToDuration>(__d); + _ToDuration __lower = chrono::floor<_ToDuration>(__d); _ToDuration __upper = __lower + _ToDuration{1}; auto __lowerDiff = __d - __lower; auto __upperDiff = __upper - __d; @@ -278,18 +281,18 @@ public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename common_type<duration>::type operator+() const {return typename common_type<duration>::type(*this);} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename common_type<duration>::type operator-() const {return typename common_type<duration>::type(-__rep_);} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration& operator++() {++__rep_; return *this;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration operator++(int) {return duration(__rep_++);} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration& operator--() {--__rep_; return *this;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration operator--(int) {return duration(__rep_--);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator++() {++__rep_; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration operator++(int) {return duration(__rep_++);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator--() {--__rep_; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration operator--(int) {return duration(__rep_--);} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration& operator+=(const duration& __d) {__rep_ += __d.count(); return *this;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration& operator-=(const duration& __d) {__rep_ -= __d.count(); return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator+=(const duration& __d) {__rep_ += __d.count(); return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator-=(const duration& __d) {__rep_ -= __d.count(); return *this;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration& operator*=(const rep& __rhs) {__rep_ *= __rhs; return *this;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration& operator/=(const rep& __rhs) {__rep_ /= __rhs; return *this;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration& operator%=(const rep& __rhs) {__rep_ %= __rhs; return *this;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration& operator%=(const duration& __rhs) {__rep_ %= __rhs.count(); return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator*=(const rep& __rhs) {__rep_ *= __rhs; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator/=(const rep& __rhs) {__rep_ /= __rhs; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator%=(const rep& __rhs) {__rep_ %= __rhs; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator%=(const duration& __rhs) {__rep_ %= __rhs.count(); return *this;} // special values @@ -534,67 +537,67 @@ inline namespace literals inline namespace chrono_literals { - constexpr chrono::hours operator""h(unsigned long long __h) + _LIBCPP_HIDE_FROM_ABI constexpr chrono::hours operator""h(unsigned long long __h) { return chrono::hours(static_cast<chrono::hours::rep>(__h)); } - constexpr chrono::duration<long double, ratio<3600,1>> operator""h(long double __h) + _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, ratio<3600,1>> operator""h(long double __h) { return chrono::duration<long double, ratio<3600,1>>(__h); } - constexpr chrono::minutes operator""min(unsigned long long __m) + _LIBCPP_HIDE_FROM_ABI constexpr chrono::minutes operator""min(unsigned long long __m) { return chrono::minutes(static_cast<chrono::minutes::rep>(__m)); } - constexpr chrono::duration<long double, ratio<60,1>> operator""min(long double __m) + _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, ratio<60,1>> operator""min(long double __m) { return chrono::duration<long double, ratio<60,1>> (__m); } - constexpr chrono::seconds operator""s(unsigned long long __s) + _LIBCPP_HIDE_FROM_ABI constexpr chrono::seconds operator""s(unsigned long long __s) { return chrono::seconds(static_cast<chrono::seconds::rep>(__s)); } - constexpr chrono::duration<long double> operator""s(long double __s) + _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double> operator""s(long double __s) { return chrono::duration<long double> (__s); } - constexpr chrono::milliseconds operator""ms(unsigned long long __ms) + _LIBCPP_HIDE_FROM_ABI constexpr chrono::milliseconds operator""ms(unsigned long long __ms) { return chrono::milliseconds(static_cast<chrono::milliseconds::rep>(__ms)); } - constexpr chrono::duration<long double, milli> operator""ms(long double __ms) + _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, milli> operator""ms(long double __ms) { return chrono::duration<long double, milli>(__ms); } - constexpr chrono::microseconds operator""us(unsigned long long __us) + _LIBCPP_HIDE_FROM_ABI constexpr chrono::microseconds operator""us(unsigned long long __us) { return chrono::microseconds(static_cast<chrono::microseconds::rep>(__us)); } - constexpr chrono::duration<long double, micro> operator""us(long double __us) + _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, micro> operator""us(long double __us) { return chrono::duration<long double, micro> (__us); } - constexpr chrono::nanoseconds operator""ns(unsigned long long __ns) + _LIBCPP_HIDE_FROM_ABI constexpr chrono::nanoseconds operator""ns(unsigned long long __ns) { return chrono::nanoseconds(static_cast<chrono::nanoseconds::rep>(__ns)); } - constexpr chrono::duration<long double, nano> operator""ns(long double __ns) + _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, nano> operator""ns(long double __ns) { return chrono::duration<long double, nano> (__ns); } @@ -612,4 +615,8 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <type_traits> +#endif + #endif // _LIBCPP___CHRONO_DURATION_H diff --git a/libcxx/include/__chrono/file_clock.h b/libcxx/include/__chrono/file_clock.h index b8e08e78ba72..ef62b8329599 100644 --- a/libcxx/include/__chrono/file_clock.h +++ b/libcxx/include/__chrono/file_clock.h @@ -61,7 +61,7 @@ struct _FilesystemClock { typedef chrono::time_point<_FilesystemClock> time_point; _LIBCPP_EXPORTED_FROM_ABI - static _LIBCPP_CONSTEXPR_AFTER_CXX11 const bool is_steady = false; + static _LIBCPP_CONSTEXPR_SINCE_CXX14 const bool is_steady = false; _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_FUNC_VIS static time_point now() noexcept; diff --git a/libcxx/include/__chrono/formatter.h b/libcxx/include/__chrono/formatter.h new file mode 100644 index 000000000000..2015783acbbb --- /dev/null +++ b/libcxx/include/__chrono/formatter.h @@ -0,0 +1,716 @@ +// -*- 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_FORMATTER_H +#define _LIBCPP___CHRONO_FORMATTER_H + +#include <__chrono/calendar.h> +#include <__chrono/convert_to_tm.h> +#include <__chrono/day.h> +#include <__chrono/duration.h> +#include <__chrono/hh_mm_ss.h> +#include <__chrono/month.h> +#include <__chrono/month_weekday.h> +#include <__chrono/monthday.h> +#include <__chrono/ostream.h> +#include <__chrono/parser_std_format_spec.h> +#include <__chrono/statically_widen.h> +#include <__chrono/time_point.h> +#include <__chrono/weekday.h> +#include <__chrono/year.h> +#include <__chrono/year_month.h> +#include <__chrono/year_month_day.h> +#include <__chrono/year_month_weekday.h> +#include <__concepts/arithmetic.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__format/concepts.h> +#include <__format/format_error.h> +#include <__format/format_functions.h> +#include <__format/format_parse_context.h> +#include <__format/formatter.h> +#include <__format/formatter_output.h> +#include <__format/parser_std_format_spec.h> +#include <__memory/addressof.h> +#include <cmath> +#include <ctime> +#include <sstream> +#include <string> +#include <string_view> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) + +namespace __formatter { + +/// Formats a time based on a tm struct. +/// +/// This formatter passes the formatting to time_put which uses strftime. When +/// the value is outside the valid range it's unspecified what strftime will +/// output. For example weekday 8 can print 1 when the day is processed modulo +/// 7 since that handles the Sunday for 0-based weekday. It can also print 8 if +/// 7 is handled as a special case. +/// +/// The Standard doesn't specify what to do in this case so the result depends +/// on the result of the underlying code. +/// +/// \pre When the (abbreviated) weekday or month name are used, the caller +/// validates whether the value is valid. So the caller handles that +/// requirement of Table 97: Meaning of conversion specifiers +/// [tab:time.format.spec]. +/// +/// When no chrono-specs are provided it uses the stream formatter. + +// For tiny ratios it's not possible to convert a duration to a hh_mm_ss. This +// fails compile-time due to the limited precision of the ratio (64-bit is too +// small). Therefore a duration uses its own conversion. +template <class _CharT, class _Tp> + requires(chrono::__is_duration<_Tp>::value) +_LIBCPP_HIDE_FROM_ABI void __format_sub_seconds(const _Tp& __value, basic_stringstream<_CharT>& __sstr) { + __sstr << std::use_facet<numpunct<_CharT>>(__sstr.getloc()).decimal_point(); + + auto __fraction = __value - chrono::duration_cast<chrono::seconds>(__value); + if constexpr (chrono::treat_as_floating_point_v<typename _Tp::rep>) + // When the floating-point value has digits itself they are ignored based + // on the wording in [tab:time.format.spec] + // If the precision of the input cannot be exactly represented with + // seconds, then the format is a decimal floating-point number with a + // fixed format and a precision matching that of the precision of the + // input (or to a microseconds precision if the conversion to + // floating-point decimal seconds cannot be made within 18 fractional + // digits). + // + // This matches the behaviour of MSVC STL, fmtlib interprets this + // differently and uses 3 decimals. + // https://godbolt.org/z/6dsbnW8ba + std::format_to(std::ostreambuf_iterator<_CharT>{__sstr}, + _LIBCPP_STATICALLY_WIDEN(_CharT, "{:0{}.0f}"), + __fraction.count(), + chrono::hh_mm_ss<_Tp>::fractional_width); + else + std::format_to(std::ostreambuf_iterator<_CharT>{__sstr}, + _LIBCPP_STATICALLY_WIDEN(_CharT, "{:0{}}"), + __fraction.count(), + chrono::hh_mm_ss<_Tp>::fractional_width); +} + +template <class _Tp> +consteval bool __use_fraction() { + if constexpr (chrono::__is_duration<_Tp>::value) + return chrono::hh_mm_ss<_Tp>::fractional_width; + else + return false; +} + +template <class _CharT> +_LIBCPP_HIDE_FROM_ABI void __format_year(int __year, basic_stringstream<_CharT>& __sstr) { + if (__year < 0) { + __sstr << _CharT('-'); + __year = -__year; + } + + // TODO FMT Write an issue + // If the result has less than four digits it is zero-padded with 0 to two digits. + // is less -> has less + // left-padded -> zero-padded, otherwise the proper value would be 000-0. + + // Note according to the wording it should be left padded, which is odd. + __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:04}"), __year); +} + +template <class _CharT> +_LIBCPP_HIDE_FROM_ABI void __format_century(int __year, basic_stringstream<_CharT>& __sstr) { + // TODO FMT Write an issue + // [tab:time.format.spec] + // %C The year divided by 100 using floored division. If the result is a + // single decimal digit, it is prefixed with 0. + + bool __negative = __year < 0; + int __century = (__year - (99 * __negative)) / 100; // floored division + __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02}"), __century); +} + +template <class _CharT, class _Tp> +_LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( + const _Tp& __value, basic_stringstream<_CharT>& __sstr, basic_string_view<_CharT> __chrono_specs) { + tm __t = std::__convert_to_tm<tm>(__value); + const auto& __facet = std::use_facet<time_put<_CharT>>(__sstr.getloc()); + for (auto __it = __chrono_specs.begin(); __it != __chrono_specs.end(); ++__it) { + if (*__it == _CharT('%')) { + auto __s = __it; + ++__it; + // We only handle the types that can't be directly handled by time_put. + // (as an optimization n, t, and % are also handled directly.) + switch (*__it) { + case _CharT('n'): + __sstr << _CharT('\n'); + break; + case _CharT('t'): + __sstr << _CharT('\t'); + break; + case _CharT('%'): + __sstr << *__it; + break; + + case _CharT('C'): { + // strftime's output is only defined in the range [00, 99]. + int __year = __t.tm_year + 1900; + if (__year < 1000 || __year > 9999) + __formatter::__format_century(__year, __sstr); + else + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + } break; + + case _CharT('j'): + if constexpr (chrono::__is_duration<_Tp>::value) + // Converting a duration where the period has a small ratio to days + // may fail to compile. This due to loss of precision in the + // conversion. In order to avoid that issue convert to seconds as + // an intemediate step. + __sstr << chrono::duration_cast<chrono::days>(chrono::duration_cast<chrono::seconds>(__value)).count(); + else + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + break; + + case _CharT('q'): + if constexpr (chrono::__is_duration<_Tp>::value) { + __sstr << chrono::__units_suffix<_CharT, typename _Tp::period>(); + break; + } + __builtin_unreachable(); + + case _CharT('Q'): + // TODO FMT Determine the proper ideas + // - Should it honour the precision? + // - Shoult it honour the locale setting for the separators? + // The wording for Q doesn't use the word locale and the effect of + // precision is unspecified. + // + // MSVC STL ignores precision but uses separator + // FMT honours precision and has a bug for separator + // https://godbolt.org/z/78b7sMxns + if constexpr (chrono::__is_duration<_Tp>::value) { + __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{}"), __value.count()); + break; + } + __builtin_unreachable(); + + case _CharT('S'): + case _CharT('T'): + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + if constexpr (__use_fraction<_Tp>()) + __formatter::__format_sub_seconds(__value, __sstr); + break; + + // Unlike time_put and strftime the formatting library requires %Y + // + // [tab:time.format.spec] + // The year as a decimal number. If the result is less than four digits + // it is left-padded with 0 to four digits. + // + // This means years in the range (-1000, 1000) need manual formatting. + // It's unclear whether %EY needs the same treatment. For example the + // Japanese EY contains the era name and year. This is zero-padded to 2 + // digits in time_put (note that older glibc versions didn't do + // padding.) However most eras won't reach 100 years, let alone 1000. + // So padding to 4 digits seems unwanted for Japanese. + // + // The same applies to %Ex since that too depends on the era. + // + // %x the locale's date representation is currently doesn't handle the + // zero-padding too. + // + // The 4 digits can be implemented better at a later time. On POSIX + // systems the required information can be extracted by nl_langinfo + // https://man7.org/linux/man-pages/man3/nl_langinfo.3.html + // + // Note since year < -1000 is expected to be rare it uses the more + // expensive year routine. + // + // TODO FMT evaluate the comment above. + +# if defined(__GLIBC__) || defined(_AIX) + case _CharT('y'): + // Glibc fails for negative values, AIX for positive values too. + __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02}"), (std::abs(__t.tm_year + 1900)) % 100); + break; +# endif // defined(__GLIBC__) || defined(_AIX) + + case _CharT('Y'): { + int __year = __t.tm_year + 1900; + if (__year < 1000) + __formatter::__format_year(__year, __sstr); + else + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + } break; + + case _CharT('F'): { + int __year = __t.tm_year + 1900; + if (__year < 1000) { + __formatter::__format_year(__year, __sstr); + __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "-{:02}-{:02}"), __t.tm_mon + 1, __t.tm_mday); + } else + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + } break; + + case _CharT('O'): + if constexpr (__use_fraction<_Tp>()) { + // Handle OS using the normal representation for the non-fractional + // part. There seems to be no locale information regarding how the + // fractional part should be formatted. + if (*(__it + 1) == 'S') { + ++__it; + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + __formatter::__format_sub_seconds(__value, __sstr); + break; + } + } + [[fallthrough]]; + case _CharT('E'): + ++__it; + [[fallthrough]]; + default: + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + break; + } + } else { + __sstr << *__it; + } + } +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_ok(const _Tp& __value) { + if constexpr (same_as<_Tp, chrono::day>) + return true; + else if constexpr (same_as<_Tp, chrono::month>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday_indexed>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_weekday>) + return true; + else if constexpr (same_as<_Tp, chrono::month_weekday_last>) + return true; + else if constexpr (same_as<_Tp, chrono::year_month>) + return true; + else if constexpr (same_as<_Tp, chrono::year_month_day>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_day_last>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday>) + return __value.weekday().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) + return __value.weekday().ok(); + else + static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_name_ok(const _Tp& __value) { + if constexpr (same_as<_Tp, chrono::day>) + return true; + else if constexpr (same_as<_Tp, chrono::month>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::weekday_indexed>) + return __value.weekday().ok(); + else if constexpr (same_as<_Tp, chrono::weekday_last>) + return __value.weekday().ok(); + else if constexpr (same_as<_Tp, chrono::month_day>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_weekday>) + return __value.weekday_indexed().ok(); + else if constexpr (same_as<_Tp, chrono::month_weekday_last>) + return __value.weekday_indexed().ok(); + else if constexpr (same_as<_Tp, chrono::year_month>) + return true; + else if constexpr (same_as<_Tp, chrono::year_month_day>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_day_last>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday>) + return __value.weekday().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) + return __value.weekday().ok(); + else + static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr bool __date_ok(const _Tp& __value) { + if constexpr (same_as<_Tp, chrono::day>) + return true; + else if constexpr (same_as<_Tp, chrono::month>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday_indexed>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_weekday>) + return true; + else if constexpr (same_as<_Tp, chrono::month_weekday_last>) + return true; + else if constexpr (same_as<_Tp, chrono::year_month>) + return true; + else if constexpr (same_as<_Tp, chrono::year_month_day>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_day_last>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) + return __value.ok(); + else + static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr bool __month_name_ok(const _Tp& __value) { + if constexpr (same_as<_Tp, chrono::day>) + return true; + else if constexpr (same_as<_Tp, chrono::month>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday_indexed>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::month_day_last>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::month_weekday>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::month_weekday_last>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::year_month>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_day>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_day_last>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) + return __value.month().ok(); + else + static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); +} + +template <class _CharT, class _Tp> +_LIBCPP_HIDE_FROM_ABI auto +__format_chrono(const _Tp& __value, + auto& __ctx, + __format_spec::__parsed_specifications<_CharT> __specs, + basic_string_view<_CharT> __chrono_specs) -> decltype(__ctx.out()) { + basic_stringstream<_CharT> __sstr; + // [time.format]/2 + // 2.1 - the "C" locale if the L option is not present in chrono-format-spec, otherwise + // 2.2 - the locale passed to the formatting function if any, otherwise + // 2.3 - the global locale. + // Note that the __ctx's locale() call does 2.2 and 2.3. + if (__specs.__chrono_.__locale_specific_form_) + __sstr.imbue(__ctx.locale()); + else + __sstr.imbue(locale::classic()); + + if (__chrono_specs.empty()) + __sstr << __value; + else { + if constexpr (chrono::__is_duration<_Tp>::value) { + if (__value < __value.zero()) + __sstr << _CharT('-'); + __formatter::__format_chrono_using_chrono_specs(chrono::abs(__value), __sstr, __chrono_specs); + // TODO FMT When keeping the precision it will truncate the string. + // Note that the behaviour what the precision does isn't specified. + __specs.__precision_ = -1; + } else { + // Test __weekday_name_ before __weekday_ to give a better error. + if (__specs.__chrono_.__weekday_name_ && !__formatter::__weekday_name_ok(__value)) + std::__throw_format_error("formatting a weekday name needs a valid weekday"); + + if (__specs.__chrono_.__weekday_ && !__formatter::__weekday_ok(__value)) + std::__throw_format_error("formatting a weekday needs a valid weekday"); + + if (__specs.__chrono_.__day_of_year_ && !__formatter::__date_ok(__value)) + std::__throw_format_error("formatting a day of year needs a valid date"); + + if (__specs.__chrono_.__week_of_year_ && !__formatter::__date_ok(__value)) + std::__throw_format_error("formatting a week of year needs a valid date"); + + if (__specs.__chrono_.__month_name_ && !__formatter::__month_name_ok(__value)) + std::__throw_format_error("formatting a month name from an invalid month number"); + + __formatter::__format_chrono_using_chrono_specs(__value, __sstr, __chrono_specs); + } + } + + // TODO FMT Use the stringstream's view after P0408R7 has been implemented. + basic_string<_CharT> __str = __sstr.str(); + return __formatter::__write_string(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); +} + +} // namespace __formatter + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_chrono { +public: + _LIBCPP_HIDE_FROM_ABI constexpr auto __parse( + basic_format_parse_context<_CharT>& __parse_ctx, __format_spec::__fields __fields, __format_spec::__flags __flags) + -> decltype(__parse_ctx.begin()) { + return __parser_.__parse(__parse_ctx, __fields, __flags); + } + + template <class _Tp> + _LIBCPP_HIDE_FROM_ABI auto format(const _Tp& __value, auto& __ctx) const -> decltype(__ctx.out()) const { + return __formatter::__format_chrono( + __value, __ctx, __parser_.__parser_.__get_parsed_chrono_specifications(__ctx), __parser_.__chrono_specs_); + } + + __format_spec::__parser_chrono<_CharT> __parser_; +}; + +template <class _Rep, class _Period, __fmt_char_type _CharT> +struct formatter<chrono::duration<_Rep, _Period>, _CharT> : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + // [time.format]/1 + // Giving a precision specification in the chrono-format-spec is valid only + // for std::chrono::duration types where the representation type Rep is a + // floating-point type. For all other Rep types, an exception of type + // format_error is thrown if the chrono-format-spec contains a precision + // specification. + // + // Note this doesn't refer to chrono::treat_as_floating_point_v<_Rep>. + if constexpr (std::floating_point<_Rep>) + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono_fractional, __format_spec::__flags::__duration); + else + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__duration); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::day, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__day); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__year); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::weekday, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::weekday_indexed, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::weekday_last, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month_day, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_day); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month_day_last, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month_weekday, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_weekday); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month_weekday_last, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_weekday); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__year_month); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month_day, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month_day_last, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month_weekday, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month_weekday_last, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + } +}; + +#endif // if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_FORMATTER_H diff --git a/libcxx/include/__chrono/hh_mm_ss.h b/libcxx/include/__chrono/hh_mm_ss.h index 6b3c5c09e68e..fd61cbe8f845 100644 --- a/libcxx/include/__chrono/hh_mm_ss.h +++ b/libcxx/include/__chrono/hh_mm_ss.h @@ -57,33 +57,33 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr hh_mm_ss() noexcept : hh_mm_ss{_Duration::zero()} {} _LIBCPP_HIDE_FROM_ABI constexpr explicit hh_mm_ss(_Duration __d) noexcept : - __is_neg(__d < _Duration(0)), - __h(duration_cast<chrono::hours> (abs(__d))), - __m(duration_cast<chrono::minutes>(abs(__d) - hours())), - __s(duration_cast<chrono::seconds>(abs(__d) - hours() - minutes())), - __f(duration_cast<precision> (abs(__d) - hours() - minutes() - seconds())) + __is_neg_(__d < _Duration(0)), + __h_(chrono::duration_cast<chrono::hours> (chrono::abs(__d))), + __m_(chrono::duration_cast<chrono::minutes>(chrono::abs(__d) - hours())), + __s_(chrono::duration_cast<chrono::seconds>(chrono::abs(__d) - hours() - minutes())), + __f_(chrono::duration_cast<precision> (chrono::abs(__d) - hours() - minutes() - seconds())) {} - _LIBCPP_HIDE_FROM_ABI constexpr bool is_negative() const noexcept { return __is_neg; } - _LIBCPP_HIDE_FROM_ABI constexpr chrono::hours hours() const noexcept { return __h; } - _LIBCPP_HIDE_FROM_ABI constexpr chrono::minutes minutes() const noexcept { return __m; } - _LIBCPP_HIDE_FROM_ABI constexpr chrono::seconds seconds() const noexcept { return __s; } - _LIBCPP_HIDE_FROM_ABI constexpr precision subseconds() const noexcept { return __f; } + _LIBCPP_HIDE_FROM_ABI constexpr bool is_negative() const noexcept { return __is_neg_; } + _LIBCPP_HIDE_FROM_ABI constexpr chrono::hours hours() const noexcept { return __h_; } + _LIBCPP_HIDE_FROM_ABI constexpr chrono::minutes minutes() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI constexpr chrono::seconds seconds() const noexcept { return __s_; } + _LIBCPP_HIDE_FROM_ABI constexpr precision subseconds() const noexcept { return __f_; } _LIBCPP_HIDE_FROM_ABI constexpr precision to_duration() const noexcept { - auto __dur = __h + __m + __s + __f; - return __is_neg ? -__dur : __dur; + auto __dur = __h_ + __m_ + __s_ + __f_; + return __is_neg_ ? -__dur : __dur; } _LIBCPP_HIDE_FROM_ABI constexpr explicit operator precision() const noexcept { return to_duration(); } private: - bool __is_neg; - chrono::hours __h; - chrono::minutes __m; - chrono::seconds __s; - precision __f; + bool __is_neg_; + chrono::hours __h_; + chrono::minutes __m_; + chrono::seconds __s_; + precision __f_; }; _LIBCPP_HIDE_FROM_ABI constexpr bool is_am(const hours& __h) noexcept { return __h >= hours( 0) && __h < hours(12); } diff --git a/libcxx/include/__chrono/month.h b/libcxx/include/__chrono/month.h index 5aeb5b397182..e929f248842e 100644 --- a/libcxx/include/__chrono/month.h +++ b/libcxx/include/__chrono/month.h @@ -12,6 +12,7 @@ #include <__chrono/duration.h> #include <__config> +#include <compare> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -26,18 +27,18 @@ namespace chrono class month { private: - unsigned char __m; + unsigned char __m_; public: _LIBCPP_HIDE_FROM_ABI month() = default; - _LIBCPP_HIDE_FROM_ABI explicit inline constexpr month(unsigned __val) noexcept : __m(static_cast<unsigned char>(__val)) {} - _LIBCPP_HIDE_FROM_ABI inline constexpr month& operator++() noexcept { ++__m; return *this; } + _LIBCPP_HIDE_FROM_ABI explicit inline constexpr month(unsigned __val) noexcept : __m_(static_cast<unsigned char>(__val)) {} + _LIBCPP_HIDE_FROM_ABI inline constexpr month& operator++() noexcept { ++__m_; return *this; } _LIBCPP_HIDE_FROM_ABI inline constexpr month operator++(int) noexcept { month __tmp = *this; ++(*this); return __tmp; } - _LIBCPP_HIDE_FROM_ABI inline constexpr month& operator--() noexcept { --__m; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr month& operator--() noexcept { --__m_; return *this; } _LIBCPP_HIDE_FROM_ABI inline constexpr month operator--(int) noexcept { month __tmp = *this; --(*this); return __tmp; } _LIBCPP_HIDE_FROM_ABI constexpr month& operator+=(const months& __m1) noexcept; _LIBCPP_HIDE_FROM_ABI constexpr month& operator-=(const months& __m1) noexcept; - _LIBCPP_HIDE_FROM_ABI explicit inline constexpr operator unsigned() const noexcept { return __m; } - _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __m >= 1 && __m <= 12; } + _LIBCPP_HIDE_FROM_ABI explicit inline constexpr operator unsigned() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __m_ >= 1 && __m_ <= 12; } }; @@ -45,25 +46,9 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(const month& __lhs, const month& __rhs) noexcept { return static_cast<unsigned>(__lhs) == static_cast<unsigned>(__rhs); } -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const month& __lhs, const month& __rhs) noexcept -{ return !(__lhs == __rhs); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator< (const month& __lhs, const month& __rhs) noexcept -{ return static_cast<unsigned>(__lhs) < static_cast<unsigned>(__rhs); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator> (const month& __lhs, const month& __rhs) noexcept -{ return __rhs < __lhs; } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator<=(const month& __lhs, const month& __rhs) noexcept -{ return !(__rhs < __lhs); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator>=(const month& __lhs, const month& __rhs) noexcept -{ return !(__lhs < __rhs); } +_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const month& __lhs, const month& __rhs) noexcept { + return static_cast<unsigned>(__lhs) <=> static_cast<unsigned>(__rhs); +} _LIBCPP_HIDE_FROM_ABI inline constexpr month operator+ (const month& __lhs, const months& __rhs) noexcept diff --git a/libcxx/include/__chrono/month_weekday.h b/libcxx/include/__chrono/month_weekday.h index 270051397017..01cdf76d84bb 100644 --- a/libcxx/include/__chrono/month_weekday.h +++ b/libcxx/include/__chrono/month_weekday.h @@ -27,14 +27,14 @@ namespace chrono class month_weekday { private: - chrono::month __m; - chrono::weekday_indexed __wdi; + chrono::month __m_; + chrono::weekday_indexed __wdi_; public: _LIBCPP_HIDE_FROM_ABI constexpr month_weekday(const chrono::month& __mval, const chrono::weekday_indexed& __wdival) noexcept - : __m{__mval}, __wdi{__wdival} {} - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m; } - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday_indexed weekday_indexed() const noexcept { return __wdi; } - _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __m.ok() && __wdi.ok(); } + : __m_{__mval}, __wdi_{__wdival} {} + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday_indexed weekday_indexed() const noexcept { return __wdi_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __m_.ok() && __wdi_.ok(); } }; _LIBCPP_HIDE_FROM_ABI inline constexpr @@ -63,14 +63,14 @@ month_weekday operator/(const weekday_indexed& __lhs, int __rhs) noexcept class month_weekday_last { - chrono::month __m; - chrono::weekday_last __wdl; + chrono::month __m_; + chrono::weekday_last __wdl_; public: _LIBCPP_HIDE_FROM_ABI constexpr month_weekday_last(const chrono::month& __mval, const chrono::weekday_last& __wdlval) noexcept - : __m{__mval}, __wdl{__wdlval} {} - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m; } - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday_last weekday_last() const noexcept { return __wdl; } - _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __m.ok() && __wdl.ok(); } + : __m_{__mval}, __wdl_{__wdlval} {} + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday_last weekday_last() const noexcept { return __wdl_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __m_.ok() && __wdl_.ok(); } }; _LIBCPP_HIDE_FROM_ABI inline constexpr diff --git a/libcxx/include/__chrono/monthday.h b/libcxx/include/__chrono/monthday.h index 485f0d4299b5..c0ee3e4a94fd 100644 --- a/libcxx/include/__chrono/monthday.h +++ b/libcxx/include/__chrono/monthday.h @@ -14,6 +14,7 @@ #include <__chrono/day.h> #include <__chrono/month.h> #include <__config> +#include <compare> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -28,26 +29,26 @@ namespace chrono class month_day { private: - chrono::month __m; - chrono::day __d; + chrono::month __m_; + chrono::day __d_; public: _LIBCPP_HIDE_FROM_ABI month_day() = default; _LIBCPP_HIDE_FROM_ABI constexpr month_day(const chrono::month& __mval, const chrono::day& __dval) noexcept - : __m{__mval}, __d{__dval} {} - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m; } - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::day day() const noexcept { return __d; } + : __m_{__mval}, __d_{__dval} {} + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::day day() const noexcept { return __d_; } _LIBCPP_HIDE_FROM_ABI constexpr bool ok() const noexcept; }; _LIBCPP_HIDE_FROM_ABI inline constexpr bool month_day::ok() const noexcept { - if (!__m.ok()) return false; - const unsigned __dval = static_cast<unsigned>(__d); + if (!__m_.ok()) return false; + const unsigned __dval = static_cast<unsigned>(__d_); if (__dval < 1 || __dval > 31) return false; if (__dval <= 29) return true; // Now we've got either 30 or 31 - const unsigned __mval = static_cast<unsigned>(__m); + const unsigned __mval = static_cast<unsigned>(__m_); if (__mval == 2) return false; if (__mval == 4 || __mval == 6 || __mval == 9 || __mval == 11) return __dval == 30; @@ -58,9 +59,11 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(const month_day& __lhs, const month_day& __rhs) noexcept { return __lhs.month() == __rhs.month() && __lhs.day() == __rhs.day(); } -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const month_day& __lhs, const month_day& __rhs) noexcept -{ return !(__lhs == __rhs); } +_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const month_day& __lhs, const month_day& __rhs) noexcept { + if (auto __c = __lhs.month() <=> __rhs.month(); __c != 0) + return __c; + return __lhs.day() <=> __rhs.day(); +} _LIBCPP_HIDE_FROM_ABI inline constexpr month_day operator/(const month& __lhs, const day& __rhs) noexcept @@ -82,58 +85,24 @@ _LIBCPP_HIDE_FROM_ABI constexpr month_day operator/(const day& __lhs, int __rhs) noexcept { return month(__rhs) / __lhs; } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator< (const month_day& __lhs, const month_day& __rhs) noexcept -{ return __lhs.month() != __rhs.month() ? __lhs.month() < __rhs.month() : __lhs.day() < __rhs.day(); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator> (const month_day& __lhs, const month_day& __rhs) noexcept -{ return __rhs < __lhs; } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator<=(const month_day& __lhs, const month_day& __rhs) noexcept -{ return !(__rhs < __lhs);} - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator>=(const month_day& __lhs, const month_day& __rhs) noexcept -{ return !(__lhs < __rhs); } - - - class month_day_last { private: - chrono::month __m; + chrono::month __m_; public: _LIBCPP_HIDE_FROM_ABI explicit constexpr month_day_last(const chrono::month& __val) noexcept - : __m{__val} {} - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m; } - _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __m.ok(); } + : __m_{__val} {} + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __m_.ok(); } }; _LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(const month_day_last& __lhs, const month_day_last& __rhs) noexcept { return __lhs.month() == __rhs.month(); } -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const month_day_last& __lhs, const month_day_last& __rhs) noexcept -{ return !(__lhs == __rhs); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator< (const month_day_last& __lhs, const month_day_last& __rhs) noexcept -{ return __lhs.month() < __rhs.month(); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator> (const month_day_last& __lhs, const month_day_last& __rhs) noexcept -{ return __rhs < __lhs; } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator<=(const month_day_last& __lhs, const month_day_last& __rhs) noexcept -{ return !(__rhs < __lhs);} - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator>=(const month_day_last& __lhs, const month_day_last& __rhs) noexcept -{ return !(__lhs < __rhs); } +_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering +operator<=>(const month_day_last& __lhs, const month_day_last& __rhs) noexcept { + return __lhs.month() <=> __rhs.month(); +} _LIBCPP_HIDE_FROM_ABI inline constexpr month_day_last operator/(const month& __lhs, last_spec) noexcept diff --git a/libcxx/include/__chrono/ostream.h b/libcxx/include/__chrono/ostream.h new file mode 100644 index 000000000000..30a04bd2658b --- /dev/null +++ b/libcxx/include/__chrono/ostream.h @@ -0,0 +1,238 @@ +// -*- 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_OSTREAM_H +#define _LIBCPP___CHRONO_OSTREAM_H + +#include <__chrono/day.h> +#include <__chrono/duration.h> +#include <__chrono/month.h> +#include <__chrono/month_weekday.h> +#include <__chrono/monthday.h> +#include <__chrono/statically_widen.h> +#include <__chrono/weekday.h> +#include <__chrono/year.h> +#include <__chrono/year_month.h> +#include <__chrono/year_month_day.h> +#include <__chrono/year_month_weekday.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__format/format_functions.h> +#include <ostream> +#include <ratio> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) + +namespace chrono { + +// Depending on the type the return is a const _CharT* or a basic_string<_CharT> +template <class _CharT, class _Period> +_LIBCPP_HIDE_FROM_ABI auto __units_suffix() { + // TODO FMT LWG issue the suffixes are always char and not STATICALLY-WIDEN'ed. + if constexpr (same_as<typename _Period::type, atto>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "as"); + else if constexpr (same_as<typename _Period::type, femto>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "fs"); + else if constexpr (same_as<typename _Period::type, pico>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "ps"); + else if constexpr (same_as<typename _Period::type, nano>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "ns"); + else if constexpr (same_as<typename _Period::type, micro>) +# ifndef _LIBCPP_HAS_NO_UNICODE + return _LIBCPP_STATICALLY_WIDEN(_CharT, "\u00b5s"); +# else + return _LIBCPP_STATICALLY_WIDEN(_CharT, "us"); +# endif + else if constexpr (same_as<typename _Period::type, milli>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "ms"); + else if constexpr (same_as<typename _Period::type, centi>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "cs"); + else if constexpr (same_as<typename _Period::type, deci>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "ds"); + else if constexpr (same_as<typename _Period::type, ratio<1>>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "s"); + else if constexpr (same_as<typename _Period::type, deca>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "das"); + else if constexpr (same_as<typename _Period::type, hecto>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "hs"); + else if constexpr (same_as<typename _Period::type, kilo>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "ks"); + else if constexpr (same_as<typename _Period::type, mega>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "Ms"); + else if constexpr (same_as<typename _Period::type, giga>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "Gs"); + else if constexpr (same_as<typename _Period::type, tera>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "Ts"); + else if constexpr (same_as<typename _Period::type, peta>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "Ps"); + else if constexpr (same_as<typename _Period::type, exa>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "Es"); + else if constexpr (same_as<typename _Period::type, ratio<60>>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "min"); + else if constexpr (same_as<typename _Period::type, ratio<3600>>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "h"); + else if constexpr (same_as<typename _Period::type, ratio<86400>>) + return _LIBCPP_STATICALLY_WIDEN(_CharT, "d"); + else if constexpr (_Period::den == 1) + return std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "[{}]s"), _Period::num); + else + return std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "[{}/{}]s"), _Period::num, _Period::den); +} + +template <class _CharT, class _Traits, class _Rep, class _Period> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const duration<_Rep, _Period>& __d) { + basic_ostringstream<_CharT, _Traits> __s; + __s.flags(__os.flags()); + __s.imbue(__os.getloc()); + __s.precision(__os.precision()); + __s << __d.count() << chrono::__units_suffix<_CharT, _Period>(); + return __os << __s.str(); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const day& __d) { + return __os + << (__d.ok() + ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%d}"), __d) + // Note this error differs from the wording of the Standard. The + // Standard wording doesn't work well on AIX or Windows. There + // the formatted day seems to be either modulo 100 or completely + // omitted. Judging by the wording this is valid. + // TODO FMT Write a paper of file an LWG issue. + : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02} is not a valid day"), static_cast<unsigned>(__d))); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const month& __m) { + return __os << (__m.ok() ? std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%b}"), __m) + : std::format(__os.getloc(), + _LIBCPP_STATICALLY_WIDEN(_CharT, "{} is not a valid month"), + static_cast<unsigned>(__m))); // TODO FMT Standard mandated locale isn't used. +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const year& __y) { + return __os << (__y.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%Y}"), __y) + : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%Y} is not a valid year"), __y)); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday& __wd) { + return __os << (__wd.ok() ? std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%a}"), __wd) + : std::format(__os.getloc(), // TODO FMT Standard mandated locale isn't used. + _LIBCPP_STATICALLY_WIDEN(_CharT, "{} is not a valid weekday"), + static_cast<unsigned>(__wd.c_encoding()))); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday_indexed& __wdi) { + auto __i = __wdi.index(); + return __os << (__i >= 1 && __i <= 5 + ? std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}[{}]"), __wdi.weekday(), __i) + : std::format(__os.getloc(), + _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}[{} is not a valid index]"), + __wdi.weekday(), + __i)); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday_last& __wdl) { + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}[last]"), __wdl.weekday()); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day& __md) { + // TODO FMT The Standard allows 30th of February to be printed. + // It would be nice to show an error message instead. + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/{}"), __md.month(), __md.day()); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day_last& __mdl) { + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/last"), __mdl.month()); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const month_weekday& __mwd) { + return __os << std::format( + __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/{:L}"), __mwd.month(), __mwd.weekday_indexed()); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const month_weekday_last& __mwdl) { + return __os << std::format( + __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/{:L}"), __mwdl.month(), __mwdl.weekday_last()); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month& __ym) { + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}"), __ym.year(), __ym.month()); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_day& __ymd) { + return __os << (__ymd.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%F}"), __ymd) + : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%F} is not a valid date"), __ymd)); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_day_last& __ymdl) { + return __os << std::format( + __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}"), __ymdl.year(), __ymdl.month_day_last()); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_weekday& __ymwd) { + return __os << std::format( + __os.getloc(), + _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}/{:L}"), + __ymwd.year(), + __ymwd.month(), + __ymwd.weekday_indexed()); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_weekday_last& __ymwdl) { + return __os << std::format( + __os.getloc(), + _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}/{:L}"), + __ymwdl.year(), + __ymwdl.month(), + __ymwdl.weekday_last()); +} + +} // namespace chrono + +#endif //if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_OSTREAM_H diff --git a/libcxx/include/__chrono/parser_std_format_spec.h b/libcxx/include/__chrono/parser_std_format_spec.h new file mode 100644 index 000000000000..dbcfe6da608a --- /dev/null +++ b/libcxx/include/__chrono/parser_std_format_spec.h @@ -0,0 +1,410 @@ +// -*- 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_PARSER_STD_FORMAT_SPEC_H +#define _LIBCPP___CHRONO_PARSER_STD_FORMAT_SPEC_H + +#include <__config> +#include <__format/concepts.h> +#include <__format/format_error.h> +#include <__format/format_parse_context.h> +#include <__format/formatter_string.h> +#include <__format/parser_std_format_spec.h> +#include <string_view> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) + +namespace __format_spec { + +// By not placing this constant in the formatter class it's not duplicated for char and wchar_t +inline constexpr __fields __fields_chrono_fractional{ + .__precision_ = true, .__locale_specific_form_ = true, .__type_ = false}; +inline constexpr __fields __fields_chrono{.__locale_specific_form_ = true, .__type_ = false}; + +/// Flags available or required in a chrono type. +/// +/// The caller of the chrono formatter lists the types it has available and the +/// validation tests whether the requested type spec (e.g. %M) is available in +/// the formatter. +/// When the type in the chrono-format-spec isn't present in the data a +/// \ref format_error is thrown. +enum class __flags { + __second = 0x1, + __minute = 0x2, + __hour = 0x4, + __time = __hour | __minute | __second, + + __day = 0x8, + __month = 0x10, + __year = 0x20, + + __weekday = 0x40, + + __month_day = __day | __month, + __month_weekday = __weekday | __month, + __year_month = __month | __year, + __date = __day | __month | __year | __weekday, + + __date_time = __date | __time, + + __duration = 0x80 | __time, + + __time_zone = 0x100, + + __clock = __date_time | __time_zone +}; + +_LIBCPP_HIDE_FROM_ABI constexpr __flags operator&(__flags __lhs, __flags __rhs) { + return static_cast<__flags>(static_cast<unsigned>(__lhs) & static_cast<unsigned>(__rhs)); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_second(__flags __flags) { + if ((__flags & __flags::__second) != __flags::__second) + std::__throw_format_error("The supplied date time doesn't contain a second"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_minute(__flags __flags) { + if ((__flags & __flags::__minute) != __flags::__minute) + std::__throw_format_error("The supplied date time doesn't contain a minute"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_hour(__flags __flags) { + if ((__flags & __flags::__hour) != __flags::__hour) + std::__throw_format_error("The supplied date time doesn't contain an hour"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_time(__flags __flags) { + if ((__flags & __flags::__time) != __flags::__time) + std::__throw_format_error("The supplied date time doesn't contain a time"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_day(__flags __flags) { + if ((__flags & __flags::__day) != __flags::__day) + std::__throw_format_error("The supplied date time doesn't contain a day"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_month(__flags __flags) { + if ((__flags & __flags::__month) != __flags::__month) + std::__throw_format_error("The supplied date time doesn't contain a month"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_year(__flags __flags) { + if ((__flags & __flags::__year) != __flags::__year) + std::__throw_format_error("The supplied date time doesn't contain a year"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_date(__flags __flags) { + if ((__flags & __flags::__date) != __flags::__date) + std::__throw_format_error("The supplied date time doesn't contain a date"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_date_or_duration(__flags __flags) { + if (((__flags & __flags::__date) != __flags::__date) && ((__flags & __flags::__duration) != __flags::__duration)) + std::__throw_format_error("The supplied date time doesn't contain a date or duration"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_date_time(__flags __flags) { + if ((__flags & __flags::__date_time) != __flags::__date_time) + std::__throw_format_error("The supplied date time doesn't contain a date and time"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_weekday(__flags __flags) { + if ((__flags & __flags::__weekday) != __flags::__weekday) + std::__throw_format_error("The supplied date time doesn't contain a weekday"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_duration(__flags __flags) { + if ((__flags & __flags::__duration) != __flags::__duration) + std::__throw_format_error("The supplied date time doesn't contain a duration"); +} + +_LIBCPP_HIDE_FROM_ABI constexpr void __validate_time_zone(__flags __flags) { + if ((__flags & __flags::__time_zone) != __flags::__time_zone) + std::__throw_format_error("The supplied date time doesn't contain a time zone"); +} + +template <class _CharT> +class _LIBCPP_TEMPLATE_VIS __parser_chrono { +public: + _LIBCPP_HIDE_FROM_ABI constexpr auto + __parse(basic_format_parse_context<_CharT>& __parse_ctx, __fields __fields, __flags __flags) + -> decltype(__parse_ctx.begin()) { + const _CharT* __begin = __parser_.__parse(__parse_ctx, __fields); + const _CharT* __end = __parse_ctx.end(); + if (__begin == __end) + return __begin; + + const _CharT* __last = __parse_chrono_specs(__begin, __end, __flags); + __chrono_specs_ = basic_string_view<_CharT>{__begin, __last}; + + return __last; + } + + __parser<_CharT> __parser_; + basic_string_view<_CharT> __chrono_specs_; + +private: + _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* + __parse_chrono_specs(const _CharT* __begin, const _CharT* __end, __flags __flags) { + _LIBCPP_ASSERT(__begin != __end, + "When called with an empty input the function will cause " + "undefined behavior by evaluating data not in the input"); + + if (*__begin != _CharT('%') && *__begin != _CharT('}')) + std::__throw_format_error("Expected '%' or '}' in the chrono format-string"); + + do { + switch (*__begin) { + case _CharT('{'): + std::__throw_format_error("The chrono-specs contains a '{'"); + + case _CharT('}'): + return __begin; + + case _CharT('%'): + __parse_conversion_spec(__begin, __end, __flags); + [[fallthrough]]; + + default: + // All other literals + ++__begin; + } + + } while (__begin != __end && *__begin != _CharT('}')); + + return __begin; + } + + /// \pre *__begin == '%' + /// \post __begin points at the end parsed conversion-spec + _LIBCPP_HIDE_FROM_ABI constexpr void + __parse_conversion_spec(const _CharT*& __begin, const _CharT* __end, __flags __flags) { + ++__begin; + if (__begin == __end) + std::__throw_format_error("End of input while parsing the modifier chrono conversion-spec"); + + switch (*__begin) { + case _CharT('n'): + case _CharT('t'): + case _CharT('%'): + break; + + case _CharT('S'): + __format_spec::__validate_second(__flags); + break; + + case _CharT('M'): + __format_spec::__validate_minute(__flags); + break; + + case _CharT('p'): // TODO FMT does the formater require an hour or a time? + case _CharT('H'): + case _CharT('I'): + __validate_hour(__flags); + break; + + case _CharT('r'): + case _CharT('R'): + case _CharT('T'): + case _CharT('X'): + __format_spec::__validate_time(__flags); + break; + + case _CharT('d'): + case _CharT('e'): + __format_spec::__validate_day(__flags); + break; + + case _CharT('b'): + case _CharT('h'): + case _CharT('B'): + __parser_.__month_name_ = true; + [[fallthrough]]; + case _CharT('m'): + __format_spec::__validate_month(__flags); + break; + + case _CharT('y'): + case _CharT('C'): + case _CharT('Y'): + __format_spec::__validate_year(__flags); + break; + + case _CharT('j'): + __parser_.__day_of_year_ = true; + __format_spec::__validate_date_or_duration(__flags); + break; + + case _CharT('g'): + case _CharT('G'): + case _CharT('U'): + case _CharT('V'): + case _CharT('W'): + __parser_.__week_of_year_ = true; + [[fallthrough]]; + case _CharT('x'): + case _CharT('D'): + case _CharT('F'): + __format_spec::__validate_date(__flags); + break; + + case _CharT('c'): + __format_spec::__validate_date_time(__flags); + break; + + case _CharT('a'): + case _CharT('A'): + __parser_.__weekday_name_ = true; + [[fallthrough]]; + case _CharT('u'): + case _CharT('w'): + __parser_.__weekday_ = true; + __validate_weekday(__flags); + __format_spec::__validate_weekday(__flags); + break; + + case _CharT('q'): + case _CharT('Q'): + __format_spec::__validate_duration(__flags); + break; + + case _CharT('E'): + __parse_modifier_E(__begin, __end, __flags); + break; + + case _CharT('O'): + __parse_modifier_O(__begin, __end, __flags); + break; + + case _CharT('z'): + case _CharT('Z'): + // Currently there's no time zone information. However some clocks have a + // hard-coded "time zone", for these clocks the information can be used. + // TODO FMT implement time zones. + __format_spec::__validate_time_zone(__flags); + break; + + default: // unknown type; + std::__throw_format_error("The date time type specifier is invalid"); + } + } + + /// \pre *__begin == 'E' + /// \post __begin is incremented by one. + _LIBCPP_HIDE_FROM_ABI constexpr void + __parse_modifier_E(const _CharT*& __begin, const _CharT* __end, __flags __flags) { + ++__begin; + if (__begin == __end) + std::__throw_format_error("End of input while parsing the modifier E"); + + switch (*__begin) { + case _CharT('X'): + __format_spec::__validate_time(__flags); + break; + + case _CharT('y'): + case _CharT('C'): + case _CharT('Y'): + __format_spec::__validate_year(__flags); + break; + + case _CharT('x'): + __format_spec::__validate_date(__flags); + break; + + case _CharT('c'): + __format_spec::__validate_date_time(__flags); + break; + + case _CharT('z'): + // Currently there's no time zone information. However some clocks have a + // hard-coded "time zone", for these clocks the information can be used. + // TODO FMT implement time zones. + __format_spec::__validate_time_zone(__flags); + break; + + default: + std::__throw_format_error("The date time type specifier for modifier E is invalid"); + } + } + + /// \pre *__begin == 'O' + /// \post __begin is incremented by one. + _LIBCPP_HIDE_FROM_ABI constexpr void + __parse_modifier_O(const _CharT*& __begin, const _CharT* __end, __flags __flags) { + ++__begin; + if (__begin == __end) + std::__throw_format_error("End of input while parsing the modifier O"); + + switch (*__begin) { + case _CharT('S'): + __format_spec::__validate_second(__flags); + break; + + case _CharT('M'): + __format_spec::__validate_minute(__flags); + break; + + case _CharT('I'): + case _CharT('H'): + __format_spec::__validate_hour(__flags); + break; + + case _CharT('d'): + case _CharT('e'): + __format_spec::__validate_day(__flags); + break; + + case _CharT('m'): + __format_spec::__validate_month(__flags); + break; + + case _CharT('y'): + __format_spec::__validate_year(__flags); + break; + + case _CharT('U'): + case _CharT('V'): + case _CharT('W'): + __parser_.__week_of_year_ = true; + __format_spec::__validate_date(__flags); + break; + + case _CharT('u'): + case _CharT('w'): + __parser_.__weekday_ = true; + __format_spec::__validate_weekday(__flags); + break; + + case _CharT('z'): + // Currently there's no time zone information. However some clocks have a + // hard-coded "time zone", for these clocks the information can be used. + // TODO FMT implement time zones. + __format_spec::__validate_time_zone(__flags); + break; + + default: + std::__throw_format_error("The date time type specifier for modifier O is invalid"); + } + } +}; + +} // namespace __format_spec + +#endif //_LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_PARSER_STD_FORMAT_SPEC_H diff --git a/libcxx/include/__chrono/statically_widen.h b/libcxx/include/__chrono/statically_widen.h new file mode 100644 index 000000000000..360b6c2c7d57 --- /dev/null +++ b/libcxx/include/__chrono/statically_widen.h @@ -0,0 +1,52 @@ +// -*- 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_STATICALLY_WIDEN_H +#define _LIBCPP___CHRONO_STATICALLY_WIDEN_H + +// Implements the STATICALLY-WIDEN exposition-only function. ([time.general]/2) + +#include <__concepts/same_as.h> +#include <__config> +#include <__format/concepts.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <__fmt_char_type _CharT> +_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __statically_widen(const char* __str, const wchar_t* __wstr) { + if constexpr (same_as<_CharT, char>) + return __str; + else + return __wstr; +} +# define _LIBCPP_STATICALLY_WIDEN(_CharT, __str) ::std::__statically_widen<_CharT>(__str, L##__str) +# else // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +// Without this indirection the unit test test/libcxx/modules_include.sh.cpp +// fails for the CI build "No wide characters". This seems like a bug. +// TODO FMT investigate why this is needed. +template <__fmt_char_type _CharT> +_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __statically_widen(const char* __str) { + return __str; +} +# define _LIBCPP_STATICALLY_WIDEN(_CharT, __str) ::std::__statically_widen<_CharT>(__str) +# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_STATICALLY_WIDEN_H diff --git a/libcxx/include/__chrono/steady_clock.h b/libcxx/include/__chrono/steady_clock.h index 657e5eef6c37..ba83351738dd 100644 --- a/libcxx/include/__chrono/steady_clock.h +++ b/libcxx/include/__chrono/steady_clock.h @@ -31,7 +31,7 @@ public: typedef duration::rep rep; typedef duration::period period; typedef chrono::time_point<steady_clock, duration> time_point; - static _LIBCPP_CONSTEXPR_AFTER_CXX11 const bool is_steady = true; + static _LIBCPP_CONSTEXPR_SINCE_CXX14 const bool is_steady = true; static time_point now() _NOEXCEPT; }; diff --git a/libcxx/include/__chrono/system_clock.h b/libcxx/include/__chrono/system_clock.h index 2922b78a74cb..331db468013c 100644 --- a/libcxx/include/__chrono/system_clock.h +++ b/libcxx/include/__chrono/system_clock.h @@ -31,7 +31,7 @@ public: typedef duration::rep rep; typedef duration::period period; typedef chrono::time_point<system_clock> time_point; - static _LIBCPP_CONSTEXPR_AFTER_CXX11 const bool is_steady = false; + static _LIBCPP_CONSTEXPR_SINCE_CXX14 const bool is_steady = false; static time_point now() _NOEXCEPT; static time_t to_time_t (const time_point& __t) _NOEXCEPT; diff --git a/libcxx/include/__chrono/time_point.h b/libcxx/include/__chrono/time_point.h index 63d67d77dd05..8a8fa2176d6c 100644 --- a/libcxx/include/__chrono/time_point.h +++ b/libcxx/include/__chrono/time_point.h @@ -12,8 +12,10 @@ #include <__chrono/duration.h> #include <__config> +#include <__type_traits/common_type.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_convertible.h> #include <limits> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -41,12 +43,12 @@ private: duration __d_; public: - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 time_point() : __d_(duration::zero()) {} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 explicit time_point(const duration& __d) : __d_(__d) {} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point() : __d_(duration::zero()) {} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit time_point(const duration& __d) : __d_(__d) {} // conversions template <class _Duration2> - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point(const time_point<clock, _Duration2>& __t, typename enable_if < @@ -56,12 +58,12 @@ public: // observer - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 duration time_since_epoch() const {return __d_;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 duration time_since_epoch() const {return __d_;} // arithmetic - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 time_point& operator+=(const duration& __d) {__d_ += __d; return *this;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 time_point& operator-=(const duration& __d) {__d_ -= __d; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 time_point& operator+=(const duration& __d) {__d_ += __d; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 time_point& operator-=(const duration& __d) {__d_ -= __d; return *this;} // special values @@ -81,7 +83,7 @@ struct _LIBCPP_TEMPLATE_VIS common_type<chrono::time_point<_Clock, _Duration1>, namespace chrono { template <class _ToDuration, class _Clock, class _Duration> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, _ToDuration> time_point_cast(const time_point<_Clock, _Duration>& __t) { @@ -98,7 +100,7 @@ typename enable_if >::type floor(const time_point<_Clock, _Duration>& __t) { - return time_point<_Clock, _ToDuration>{floor<_ToDuration>(__t.time_since_epoch())}; + return time_point<_Clock, _ToDuration>{chrono::floor<_ToDuration>(__t.time_since_epoch())}; } template <class _ToDuration, class _Clock, class _Duration> @@ -110,7 +112,7 @@ typename enable_if >::type ceil(const time_point<_Clock, _Duration>& __t) { - return time_point<_Clock, _ToDuration>{ceil<_ToDuration>(__t.time_since_epoch())}; + return time_point<_Clock, _ToDuration>{chrono::ceil<_ToDuration>(__t.time_since_epoch())}; } template <class _ToDuration, class _Clock, class _Duration> @@ -122,7 +124,7 @@ typename enable_if >::type round(const time_point<_Clock, _Duration>& __t) { - return time_point<_Clock, _ToDuration>{round<_ToDuration>(__t.time_since_epoch())}; + return time_point<_Clock, _ToDuration>{chrono::round<_ToDuration>(__t.time_since_epoch())}; } template <class _Rep, class _Period> @@ -141,7 +143,7 @@ abs(duration<_Rep, _Period> __d) // time_point == template <class _Clock, class _Duration1, class _Duration2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator==(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) { @@ -151,7 +153,7 @@ operator==(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, // time_point != template <class _Clock, class _Duration1, class _Duration2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator!=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) { @@ -161,7 +163,7 @@ operator!=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, // time_point < template <class _Clock, class _Duration1, class _Duration2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator<(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) { @@ -171,7 +173,7 @@ operator<(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, // time_point > template <class _Clock, class _Duration1, class _Duration2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator>(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) { @@ -181,7 +183,7 @@ operator>(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, // time_point <= template <class _Clock, class _Duration1, class _Duration2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator<=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) { @@ -191,7 +193,7 @@ operator<=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, // time_point >= template <class _Clock, class _Duration1, class _Duration2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator>=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) { @@ -201,7 +203,7 @@ operator>=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, // time_point operator+(time_point x, duration y); template <class _Clock, class _Duration1, class _Rep2, class _Period2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> operator+(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { @@ -212,7 +214,7 @@ operator+(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Pe // time_point operator+(duration x, time_point y); template <class _Rep1, class _Period1, class _Clock, class _Duration2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type<duration<_Rep1, _Period1>, _Duration2>::type> operator+(const duration<_Rep1, _Period1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) { @@ -222,7 +224,7 @@ operator+(const duration<_Rep1, _Period1>& __lhs, const time_point<_Clock, _Dura // time_point operator-(time_point x, duration y); template <class _Clock, class _Duration1, class _Rep2, class _Period2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> operator-(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { @@ -233,7 +235,7 @@ operator-(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Pe // duration operator-(time_point x, time_point y); template <class _Clock, class _Duration1, class _Duration2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 typename common_type<_Duration1, _Duration2>::type operator-(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) { diff --git a/libcxx/include/__chrono/weekday.h b/libcxx/include/__chrono/weekday.h index bad6781110f1..e0bc8a4cae2b 100644 --- a/libcxx/include/__chrono/weekday.h +++ b/libcxx/include/__chrono/weekday.h @@ -32,25 +32,25 @@ class weekday_last; class weekday { private: - unsigned char __wd; + unsigned char __wd_; _LIBCPP_HIDE_FROM_ABI static constexpr unsigned char __weekday_from_days(int __days) noexcept; public: _LIBCPP_HIDE_FROM_ABI weekday() = default; - _LIBCPP_HIDE_FROM_ABI inline explicit constexpr weekday(unsigned __val) noexcept : __wd(static_cast<unsigned char>(__val == 7 ? 0 : __val)) {} + _LIBCPP_HIDE_FROM_ABI inline explicit constexpr weekday(unsigned __val) noexcept : __wd_(static_cast<unsigned char>(__val == 7 ? 0 : __val)) {} _LIBCPP_HIDE_FROM_ABI inline constexpr weekday(const sys_days& __sysd) noexcept - : __wd(__weekday_from_days(__sysd.time_since_epoch().count())) {} + : __wd_(__weekday_from_days(__sysd.time_since_epoch().count())) {} _LIBCPP_HIDE_FROM_ABI inline explicit constexpr weekday(const local_days& __locd) noexcept - : __wd(__weekday_from_days(__locd.time_since_epoch().count())) {} + : __wd_(__weekday_from_days(__locd.time_since_epoch().count())) {} - _LIBCPP_HIDE_FROM_ABI inline constexpr weekday& operator++() noexcept { __wd = (__wd == 6 ? 0 : __wd + 1); return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr weekday& operator++() noexcept { __wd_ = (__wd_ == 6 ? 0 : __wd_ + 1); return *this; } _LIBCPP_HIDE_FROM_ABI inline constexpr weekday operator++(int) noexcept { weekday __tmp = *this; ++(*this); return __tmp; } - _LIBCPP_HIDE_FROM_ABI inline constexpr weekday& operator--() noexcept { __wd = (__wd == 0 ? 6 : __wd - 1); return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr weekday& operator--() noexcept { __wd_ = (__wd_ == 0 ? 6 : __wd_ - 1); return *this; } _LIBCPP_HIDE_FROM_ABI inline constexpr weekday operator--(int) noexcept { weekday __tmp = *this; --(*this); return __tmp; } _LIBCPP_HIDE_FROM_ABI constexpr weekday& operator+=(const days& __dd) noexcept; _LIBCPP_HIDE_FROM_ABI constexpr weekday& operator-=(const days& __dd) noexcept; - _LIBCPP_HIDE_FROM_ABI inline constexpr unsigned c_encoding() const noexcept { return __wd; } - _LIBCPP_HIDE_FROM_ABI inline constexpr unsigned iso_encoding() const noexcept { return __wd == 0u ? 7 : __wd; } - _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __wd <= 6; } + _LIBCPP_HIDE_FROM_ABI inline constexpr unsigned c_encoding() const noexcept { return __wd_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr unsigned iso_encoding() const noexcept { return __wd_ == 0u ? 7 : __wd_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __wd_ <= 6; } _LIBCPP_HIDE_FROM_ABI constexpr weekday_indexed operator[](unsigned __index) const noexcept; _LIBCPP_HIDE_FROM_ABI constexpr weekday_last operator[](last_spec) const noexcept; }; @@ -123,15 +123,15 @@ weekday& weekday::operator-=(const days& __dd) noexcept class weekday_indexed { private: - chrono::weekday __wd; - unsigned char __idx; + chrono::weekday __wd_; + unsigned char __idx_; public: _LIBCPP_HIDE_FROM_ABI weekday_indexed() = default; _LIBCPP_HIDE_FROM_ABI inline constexpr weekday_indexed(const chrono::weekday& __wdval, unsigned __idxval) noexcept - : __wd{__wdval}, __idx(__idxval) {} - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday weekday() const noexcept { return __wd; } - _LIBCPP_HIDE_FROM_ABI inline constexpr unsigned index() const noexcept { return __idx; } - _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __wd.ok() && __idx >= 1 && __idx <= 5; } + : __wd_{__wdval}, __idx_(__idxval) {} + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday weekday() const noexcept { return __wd_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr unsigned index() const noexcept { return __idx_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __wd_.ok() && __idx_ >= 1 && __idx_ <= 5; } }; _LIBCPP_HIDE_FROM_ABI inline constexpr @@ -145,12 +145,12 @@ bool operator!=(const weekday_indexed& __lhs, const weekday_indexed& __rhs) noex class weekday_last { private: - chrono::weekday __wd; + chrono::weekday __wd_; public: _LIBCPP_HIDE_FROM_ABI explicit constexpr weekday_last(const chrono::weekday& __val) noexcept - : __wd{__val} {} - _LIBCPP_HIDE_FROM_ABI constexpr chrono::weekday weekday() const noexcept { return __wd; } - _LIBCPP_HIDE_FROM_ABI constexpr bool ok() const noexcept { return __wd.ok(); } + : __wd_{__val} {} + _LIBCPP_HIDE_FROM_ABI constexpr chrono::weekday weekday() const noexcept { return __wd_; } + _LIBCPP_HIDE_FROM_ABI constexpr bool ok() const noexcept { return __wd_.ok(); } }; _LIBCPP_HIDE_FROM_ABI inline constexpr diff --git a/libcxx/include/__chrono/year.h b/libcxx/include/__chrono/year.h index c7f0027eba7b..79ee8a02b8fb 100644 --- a/libcxx/include/__chrono/year.h +++ b/libcxx/include/__chrono/year.h @@ -12,6 +12,7 @@ #include <__chrono/duration.h> #include <__config> +#include <compare> #include <limits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -30,22 +31,22 @@ namespace chrono class year { private: - short __y; + short __y_; public: _LIBCPP_HIDE_FROM_ABI year() = default; - _LIBCPP_HIDE_FROM_ABI explicit inline constexpr year(int __val) noexcept : __y(static_cast<short>(__val)) {} + _LIBCPP_HIDE_FROM_ABI explicit inline constexpr year(int __val) noexcept : __y_(static_cast<short>(__val)) {} - _LIBCPP_HIDE_FROM_ABI inline constexpr year& operator++() noexcept { ++__y; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr year& operator++() noexcept { ++__y_; return *this; } _LIBCPP_HIDE_FROM_ABI inline constexpr year operator++(int) noexcept { year __tmp = *this; ++(*this); return __tmp; } - _LIBCPP_HIDE_FROM_ABI inline constexpr year& operator--() noexcept { --__y; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr year& operator--() noexcept { --__y_; return *this; } _LIBCPP_HIDE_FROM_ABI inline constexpr year operator--(int) noexcept { year __tmp = *this; --(*this); return __tmp; } _LIBCPP_HIDE_FROM_ABI constexpr year& operator+=(const years& __dy) noexcept; _LIBCPP_HIDE_FROM_ABI constexpr year& operator-=(const years& __dy) noexcept; _LIBCPP_HIDE_FROM_ABI inline constexpr year operator+() const noexcept { return *this; } - _LIBCPP_HIDE_FROM_ABI inline constexpr year operator-() const noexcept { return year{-__y}; } + _LIBCPP_HIDE_FROM_ABI inline constexpr year operator-() const noexcept { return year{-__y_}; } - _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_leap() const noexcept { return __y % 4 == 0 && (__y % 100 != 0 || __y % 400 == 0); } - _LIBCPP_HIDE_FROM_ABI explicit inline constexpr operator int() const noexcept { return __y; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_leap() const noexcept { return __y_ % 4 == 0 && (__y_ % 100 != 0 || __y_ % 400 == 0); } + _LIBCPP_HIDE_FROM_ABI explicit inline constexpr operator int() const noexcept { return __y_; } _LIBCPP_HIDE_FROM_ABI constexpr bool ok() const noexcept; _LIBCPP_HIDE_FROM_ABI static inline constexpr year min() noexcept { return year{-32767}; } _LIBCPP_HIDE_FROM_ABI static inline constexpr year max() noexcept { return year{ 32767}; } @@ -56,25 +57,9 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(const year& __lhs, const year& __rhs) noexcept { return static_cast<int>(__lhs) == static_cast<int>(__rhs); } -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const year& __lhs, const year& __rhs) noexcept -{ return !(__lhs == __rhs); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator< (const year& __lhs, const year& __rhs) noexcept -{ return static_cast<int>(__lhs) < static_cast<int>(__rhs); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator> (const year& __lhs, const year& __rhs) noexcept -{ return __rhs < __lhs; } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator<=(const year& __lhs, const year& __rhs) noexcept -{ return !(__rhs < __lhs); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator>=(const year& __lhs, const year& __rhs) noexcept -{ return !(__lhs < __rhs); } +_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const year& __lhs, const year& __rhs) noexcept { + return static_cast<int>(__lhs) <=> static_cast<int>(__rhs); +} _LIBCPP_HIDE_FROM_ABI inline constexpr year operator+ (const year& __lhs, const years& __rhs) noexcept @@ -102,8 +87,8 @@ year& year::operator-=(const years& __dy) noexcept { *this = *this - __dy; return *this; } _LIBCPP_HIDE_FROM_ABI constexpr bool year::ok() const noexcept { - static_assert(static_cast<int>(std::numeric_limits<decltype(__y)>::max()) == static_cast<int>(max())); - return static_cast<int>(min()) <= __y; + static_assert(static_cast<int>(std::numeric_limits<decltype(__y_)>::max()) == static_cast<int>(max())); + return static_cast<int>(min()) <= __y_; } } // namespace chrono diff --git a/libcxx/include/__chrono/year_month.h b/libcxx/include/__chrono/year_month.h index 51b19caa1124..9f1e65c8c83d 100644 --- a/libcxx/include/__chrono/year_month.h +++ b/libcxx/include/__chrono/year_month.h @@ -14,6 +14,7 @@ #include <__chrono/month.h> #include <__chrono/year.h> #include <__config> +#include <compare> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -27,19 +28,19 @@ namespace chrono { class year_month { - chrono::year __y; - chrono::month __m; + chrono::year __y_; + chrono::month __m_; public: _LIBCPP_HIDE_FROM_ABI year_month() = default; _LIBCPP_HIDE_FROM_ABI constexpr year_month(const chrono::year& __yval, const chrono::month& __mval) noexcept - : __y{__yval}, __m{__mval} {} - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y; } - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m; } - _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator+=(const months& __dm) noexcept { this->__m += __dm; return *this; } - _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator-=(const months& __dm) noexcept { this->__m -= __dm; return *this; } - _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator+=(const years& __dy) noexcept { this->__y += __dy; return *this; } - _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator-=(const years& __dy) noexcept { this->__y -= __dy; return *this; } - _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __y.ok() && __m.ok(); } + : __y_{__yval}, __m_{__mval} {} + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator+=(const months& __dm) noexcept { this->__m_ += __dm; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator-=(const months& __dm) noexcept { this->__m_ -= __dm; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator+=(const years& __dy) noexcept { this->__y_ += __dy; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator-=(const years& __dy) noexcept { this->__y_ -= __dy; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __y_.ok() && __m_.ok(); } }; _LIBCPP_HIDE_FROM_ABI inline constexpr @@ -52,25 +53,11 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(const year_month& __lhs, const year_month& __rhs) noexcept { return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month(); } -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const year_month& __lhs, const year_month& __rhs) noexcept -{ return !(__lhs == __rhs); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator< (const year_month& __lhs, const year_month& __rhs) noexcept -{ return __lhs.year() != __rhs.year() ? __lhs.year() < __rhs.year() : __lhs.month() < __rhs.month(); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator> (const year_month& __lhs, const year_month& __rhs) noexcept -{ return __rhs < __lhs; } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator<=(const year_month& __lhs, const year_month& __rhs) noexcept -{ return !(__rhs < __lhs);} - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator>=(const year_month& __lhs, const year_month& __rhs) noexcept -{ return !(__lhs < __rhs); } +_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const year_month& __lhs, const year_month& __rhs) noexcept { + if (auto __c = __lhs.year() <=> __rhs.year(); __c != 0) + return __c; + return __lhs.month() <=> __rhs.month(); +} _LIBCPP_HIDE_FROM_ABI constexpr year_month operator+(const year_month& __lhs, const months& __rhs) noexcept diff --git a/libcxx/include/__chrono/year_month_day.h b/libcxx/include/__chrono/year_month_day.h index 957716aab690..b74901470c66 100644 --- a/libcxx/include/__chrono/year_month_day.h +++ b/libcxx/include/__chrono/year_month_day.h @@ -20,6 +20,7 @@ #include <__chrono/year.h> #include <__chrono/year_month.h> #include <__config> +#include <compare> #include <limits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -37,14 +38,14 @@ class year_month_day_last; class year_month_day { private: - chrono::year __y; - chrono::month __m; - chrono::day __d; + chrono::year __y_; + chrono::month __m_; + chrono::day __d_; public: _LIBCPP_HIDE_FROM_ABI year_month_day() = default; _LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day( const chrono::year& __yval, const chrono::month& __mval, const chrono::day& __dval) noexcept - : __y{__yval}, __m{__mval}, __d{__dval} {} + : __y_{__yval}, __m_{__mval}, __d_{__dval} {} _LIBCPP_HIDE_FROM_ABI constexpr year_month_day(const year_month_day_last& __ymdl) noexcept; _LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day(const sys_days& __sysd) noexcept : year_month_day(__from_days(__sysd.time_since_epoch())) {} @@ -56,9 +57,9 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr year_month_day& operator+=(const years& __dy) noexcept; _LIBCPP_HIDE_FROM_ABI constexpr year_month_day& operator-=(const years& __dy) noexcept; - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y; } - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m; } - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::day day() const noexcept { return __d; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::day day() const noexcept { return __d_; } _LIBCPP_HIDE_FROM_ABI inline constexpr operator sys_days() const noexcept { return sys_days{__to_days()}; } _LIBCPP_HIDE_FROM_ABI inline explicit constexpr operator local_days() const noexcept { return local_days{__to_days()}; } @@ -94,9 +95,9 @@ days year_month_day::__to_days() const noexcept static_assert(numeric_limits<unsigned>::digits >= 18, ""); static_assert(numeric_limits<int>::digits >= 20 , ""); - const int __yr = static_cast<int>(__y) - (__m <= February); - const unsigned __mth = static_cast<unsigned>(__m); - const unsigned __dy = static_cast<unsigned>(__d); + const int __yr = static_cast<int>(__y_) - (__m_ <= February); + const unsigned __mth = static_cast<unsigned>(__m_); + const unsigned __dy = static_cast<unsigned>(__d_); const int __era = (__yr >= 0 ? __yr : __yr - 399) / 400; const unsigned __yoe = static_cast<unsigned>(__yr - __era * 400); // [0, 399] @@ -109,33 +110,16 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(const year_month_day& __lhs, const year_month_day& __rhs) noexcept { return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.day() == __rhs.day(); } -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const year_month_day& __lhs, const year_month_day& __rhs) noexcept -{ return !(__lhs == __rhs); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator< (const year_month_day& __lhs, const year_month_day& __rhs) noexcept -{ - if (__lhs.year() < __rhs.year()) return true; - if (__lhs.year() > __rhs.year()) return false; - if (__lhs.month() < __rhs.month()) return true; - if (__lhs.month() > __rhs.month()) return false; - return __lhs.day() < __rhs.day(); +_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering +operator<=>(const year_month_day& __lhs, const year_month_day& __rhs) noexcept { + if (auto __c = __lhs.year() <=> __rhs.year(); __c != 0) + return __c; + if (auto __c = __lhs.month() <=> __rhs.month(); __c != 0) + return __c; + return __lhs.day() <=> __rhs.day(); } _LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator> (const year_month_day& __lhs, const year_month_day& __rhs) noexcept -{ return __rhs < __lhs; } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator<=(const year_month_day& __lhs, const year_month_day& __rhs) noexcept -{ return !(__rhs < __lhs);} - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator>=(const year_month_day& __lhs, const year_month_day& __rhs) noexcept -{ return !(__lhs < __rhs); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day operator/(const year_month& __lhs, const day& __rhs) noexcept { return year_month_day{__lhs.year(), __lhs.month(), __rhs}; } @@ -191,24 +175,24 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day& year_month_day::operator- class year_month_day_last { private: - chrono::year __y; - chrono::month_day_last __mdl; + chrono::year __y_; + chrono::month_day_last __mdl_; public: _LIBCPP_HIDE_FROM_ABI constexpr year_month_day_last(const year& __yval, const month_day_last& __mdlval) noexcept - : __y{__yval}, __mdl{__mdlval} {} + : __y_{__yval}, __mdl_{__mdlval} {} _LIBCPP_HIDE_FROM_ABI constexpr year_month_day_last& operator+=(const months& __m) noexcept; _LIBCPP_HIDE_FROM_ABI constexpr year_month_day_last& operator-=(const months& __m) noexcept; _LIBCPP_HIDE_FROM_ABI constexpr year_month_day_last& operator+=(const years& __y) noexcept; _LIBCPP_HIDE_FROM_ABI constexpr year_month_day_last& operator-=(const years& __y) noexcept; - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y; } - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __mdl.month(); } - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month_day_last month_day_last() const noexcept { return __mdl; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __mdl_.month(); } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month_day_last month_day_last() const noexcept { return __mdl_; } _LIBCPP_HIDE_FROM_ABI constexpr chrono::day day() const noexcept; _LIBCPP_HIDE_FROM_ABI inline constexpr operator sys_days() const noexcept { return sys_days{year()/month()/day()}; } _LIBCPP_HIDE_FROM_ABI inline explicit constexpr operator local_days() const noexcept { return local_days{year()/month()/day()}; } - _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __y.ok() && __mdl.ok(); } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __y_.ok() && __mdl_.ok(); } }; _LIBCPP_HIDE_FROM_ABI inline constexpr @@ -221,7 +205,7 @@ chrono::day year_month_day_last::day() const noexcept chrono::day(31), chrono::day(31), chrono::day(30), chrono::day(31), chrono::day(30), chrono::day(31) }; - return (month() != February || !__y.is_leap()) && month().ok() ? + return (month() != February || !__y_.is_leap()) && month().ok() ? __d[static_cast<unsigned>(month()) - 1] : chrono::day{29}; } @@ -305,13 +289,13 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day_last& year_month_day_last: _LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day::year_month_day(const year_month_day_last& __ymdl) noexcept - : __y{__ymdl.year()}, __m{__ymdl.month()}, __d{__ymdl.day()} {} + : __y_{__ymdl.year()}, __m_{__ymdl.month()}, __d_{__ymdl.day()} {} _LIBCPP_HIDE_FROM_ABI inline constexpr bool year_month_day::ok() const noexcept { - if (!__y.ok() || !__m.ok()) return false; - return chrono::day{1} <= __d && __d <= (__y / __m / last).day(); + if (!__y_.ok() || !__m_.ok()) return false; + return chrono::day{1} <= __d_ && __d_ <= (__y_ / __m_ / last).day(); } } // namespace chrono diff --git a/libcxx/include/__chrono/year_month_weekday.h b/libcxx/include/__chrono/year_month_weekday.h index b69b77152fb1..6604deaf12cd 100644 --- a/libcxx/include/__chrono/year_month_weekday.h +++ b/libcxx/include/__chrono/year_month_weekday.h @@ -35,14 +35,14 @@ namespace chrono { class year_month_weekday { - chrono::year __y; - chrono::month __m; - chrono::weekday_indexed __wdi; + chrono::year __y_; + chrono::month __m_; + chrono::weekday_indexed __wdi_; public: _LIBCPP_HIDE_FROM_ABI year_month_weekday() = default; _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday(const chrono::year& __yval, const chrono::month& __mval, const chrono::weekday_indexed& __wdival) noexcept - : __y{__yval}, __m{__mval}, __wdi{__wdival} {} + : __y_{__yval}, __m_{__mval}, __wdi_{__wdival} {} _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday(const sys_days& __sysd) noexcept : year_month_weekday(__from_days(__sysd.time_since_epoch())) {} _LIBCPP_HIDE_FROM_ABI inline explicit constexpr year_month_weekday(const local_days& __locd) noexcept @@ -52,24 +52,24 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday& operator+=(const years&) noexcept; _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday& operator-=(const years&) noexcept; - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y; } - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m; } - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday weekday() const noexcept { return __wdi.weekday(); } - _LIBCPP_HIDE_FROM_ABI inline constexpr unsigned index() const noexcept { return __wdi.index(); } - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday_indexed weekday_indexed() const noexcept { return __wdi; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday weekday() const noexcept { return __wdi_.weekday(); } + _LIBCPP_HIDE_FROM_ABI inline constexpr unsigned index() const noexcept { return __wdi_.index(); } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday_indexed weekday_indexed() const noexcept { return __wdi_; } _LIBCPP_HIDE_FROM_ABI inline constexpr operator sys_days() const noexcept { return sys_days{__to_days()}; } _LIBCPP_HIDE_FROM_ABI inline explicit constexpr operator local_days() const noexcept { return local_days{__to_days()}; } _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { - if (!__y.ok() || !__m.ok() || !__wdi.ok()) return false; - if (__wdi.index() <= 4) return true; + if (!__y_.ok() || !__m_.ok() || !__wdi_.ok()) return false; + if (__wdi_.index() <= 4) return true; auto __nth_weekday_day = - __wdi.weekday() - - chrono::weekday{static_cast<sys_days>(__y / __m / 1)} + - days{(__wdi.index() - 1) * 7 + 1}; + __wdi_.weekday() - + chrono::weekday{static_cast<sys_days>(__y_ / __m_ / 1)} + + days{(__wdi_.index() - 1) * 7 + 1}; return static_cast<unsigned>(__nth_weekday_day.count()) <= - static_cast<unsigned>((__y / __m / last).day()); + static_cast<unsigned>((__y_ / __m_ / last).day()); } _LIBCPP_HIDE_FROM_ABI static constexpr year_month_weekday __from_days(days __d) noexcept; @@ -89,8 +89,8 @@ year_month_weekday year_month_weekday::__from_days(days __d) noexcept _LIBCPP_HIDE_FROM_ABI inline constexpr days year_month_weekday::__to_days() const noexcept { - const sys_days __sysd = sys_days(__y/__m/1); - return (__sysd + (__wdi.weekday() - chrono::weekday(__sysd) + days{(__wdi.index()-1)*7})) + const sys_days __sysd = sys_days(__y_/__m_/1); + return (__sysd + (__wdi_.weekday() - chrono::weekday(__sysd) + days{(__wdi_.index()-1)*7})) .time_since_epoch(); } @@ -155,25 +155,25 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr year_month_weekday& year_month_weekday::o class year_month_weekday_last { private: - chrono::year __y; - chrono::month __m; - chrono::weekday_last __wdl; + chrono::year __y_; + chrono::month __m_; + chrono::weekday_last __wdl_; public: _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday_last(const chrono::year& __yval, const chrono::month& __mval, const chrono::weekday_last& __wdlval) noexcept - : __y{__yval}, __m{__mval}, __wdl{__wdlval} {} + : __y_{__yval}, __m_{__mval}, __wdl_{__wdlval} {} _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday_last& operator+=(const months& __dm) noexcept; _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday_last& operator-=(const months& __dm) noexcept; _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday_last& operator+=(const years& __dy) noexcept; _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday_last& operator-=(const years& __dy) noexcept; - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y; } - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m; } - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday weekday() const noexcept { return __wdl.weekday(); } - _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday_last weekday_last() const noexcept { return __wdl; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday weekday() const noexcept { return __wdl_.weekday(); } + _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday_last weekday_last() const noexcept { return __wdl_; } _LIBCPP_HIDE_FROM_ABI inline constexpr operator sys_days() const noexcept { return sys_days{__to_days()}; } _LIBCPP_HIDE_FROM_ABI inline explicit constexpr operator local_days() const noexcept { return local_days{__to_days()}; } - _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __y.ok() && __m.ok() && __wdl.ok(); } + _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __y_.ok() && __m_.ok() && __wdl_.ok(); } _LIBCPP_HIDE_FROM_ABI constexpr days __to_days() const noexcept; @@ -182,8 +182,8 @@ public: _LIBCPP_HIDE_FROM_ABI inline constexpr days year_month_weekday_last::__to_days() const noexcept { - const sys_days __last = sys_days{__y/__m/last}; - return (__last - (chrono::weekday{__last} - __wdl.weekday())).time_since_epoch(); + const sys_days __last = sys_days{__y_/__m_/last}; + return (__last - (chrono::weekday{__last} - __wdl_.weekday())).time_since_epoch(); } |
