[libc++][chrono] Add sys_time formatter.
Partially implements: - P1361 Integration of chrono with text formatting - P2372 Fixing locale handling in chrono formatters Reviewed By: ldionne, #libc Differential Revision: https://reviews.llvm.org/D144739
This commit is contained in:
parent
9b43aedeb3
commit
2c1d79596f
@ -1,7 +1,7 @@
|
||||
Section,Description,Dependencies,Assignee,Status,First released version
|
||||
`P1361 <https://wg21.link/P1361>`__ `P2372 <https://wg21.link/P2372>`__,"Formatting chrono"
|
||||
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::duration<Rep, Period>``",,Mark de Wever,|Complete|, Clang 16
|
||||
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::sys_time<Duration>``",,Mark de Wever,|In Progress|,
|
||||
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::sys_time<Duration>``",,Mark de Wever,|Complete|, Clang 17
|
||||
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::utc_time<Duration>``",A ``<chrono>`` implementation,Not assigned,,,
|
||||
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::tai_time<Duration>``",A ``<chrono>`` implementation,Not assigned,,,
|
||||
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::gps_time<Duration>``",A ``<chrono>`` implementation,Not assigned,,,
|
||||
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
@ -11,6 +11,7 @@
|
||||
#define _LIBCPP___CHRONO_CONCEPTS_H
|
||||
|
||||
#include <__chrono/hh_mm_ss.h>
|
||||
#include <__chrono/time_point.h>
|
||||
#include <__config>
|
||||
#include <__type_traits/is_specialization.h>
|
||||
|
||||
@ -25,6 +26,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
||||
template <class _Tp>
|
||||
concept __is_hh_mm_ss = __is_specialization_v<_Tp, chrono::hh_mm_ss>;
|
||||
|
||||
template <class _Tp>
|
||||
concept __is_time_point = __is_specialization_v<_Tp, chrono::time_point>;
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
@ -82,7 +82,25 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoT& __value) {
|
||||
__result.tm_zone = "UTC";
|
||||
# endif
|
||||
|
||||
if constexpr (chrono::__is_duration<_ChronoT>::value) {
|
||||
if constexpr (__is_time_point<_ChronoT>) {
|
||||
if constexpr (same_as<typename _ChronoT::clock, chrono::system_clock>) {
|
||||
chrono::sys_days __days = chrono::time_point_cast<chrono::days>(__value);
|
||||
chrono::year_month_day __ymd{__days};
|
||||
|
||||
__result = std::__convert_to_tm<_Tm>(chrono::year_month_day{__ymd}, chrono::weekday{__days});
|
||||
|
||||
// TODO FMT D138826 has improvements for this part.
|
||||
// TODO FMT Since this is identical for duration and system time it would be good to avoid code duplication.
|
||||
uint64_t __sec =
|
||||
chrono::duration_cast<chrono::seconds>(__value - chrono::time_point_cast<chrono::seconds>(__days)).count();
|
||||
__sec %= 24 * 3600;
|
||||
__result.tm_hour = __sec / 3600;
|
||||
__sec %= 3600;
|
||||
__result.tm_min = __sec / 60;
|
||||
__result.tm_sec = __sec % 60;
|
||||
} else
|
||||
static_assert(sizeof(_ChronoT) == 0, "TODO: Add the missing clock specialization");
|
||||
} else 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
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
#include <__chrono/ostream.h>
|
||||
#include <__chrono/parser_std_format_spec.h>
|
||||
#include <__chrono/statically_widen.h>
|
||||
#include <__chrono/system_clock.h>
|
||||
#include <__chrono/time_point.h>
|
||||
#include <__chrono/weekday.h>
|
||||
#include <__chrono/year.h>
|
||||
@ -108,6 +109,11 @@ __format_sub_seconds(const chrono::duration<_Rep, _Period>& __value, basic_strin
|
||||
chrono::hh_mm_ss<__duration>::fractional_width);
|
||||
}
|
||||
|
||||
template <class _CharT, __is_time_point _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI void __format_sub_seconds(const _Tp& __value, basic_stringstream<_CharT>& __sstr) {
|
||||
__formatter::__format_sub_seconds(__value.time_since_epoch(), __sstr);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI void
|
||||
__format_sub_seconds(const chrono::hh_mm_ss<_Duration>& __value, basic_stringstream<_CharT>& __sstr) {
|
||||
@ -126,7 +132,9 @@ __format_sub_seconds(const chrono::hh_mm_ss<_Duration>& __value, basic_stringstr
|
||||
|
||||
template <class _Tp>
|
||||
consteval bool __use_fraction() {
|
||||
if constexpr (chrono::__is_duration<_Tp>::value)
|
||||
if constexpr (__is_time_point<_Tp>)
|
||||
return chrono::hh_mm_ss<typename _Tp::duration>::fractional_width;
|
||||
else if constexpr (chrono::__is_duration<_Tp>::value)
|
||||
return chrono::hh_mm_ss<_Tp>::fractional_width;
|
||||
else if constexpr (__is_hh_mm_ss<_Tp>)
|
||||
return _Tp::fractional_width;
|
||||
@ -285,6 +293,11 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs(
|
||||
__facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1));
|
||||
} break;
|
||||
|
||||
case _CharT('Z'):
|
||||
// TODO FMT Add proper timezone support.
|
||||
__sstr << _LIBCPP_STATICALLY_WIDEN(_CharT, "UTC");
|
||||
break;
|
||||
|
||||
case _CharT('O'):
|
||||
if constexpr (__use_fraction<_Tp>()) {
|
||||
// Handle OS using the normal representation for the non-fractional
|
||||
@ -313,7 +326,9 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs(
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_ok(const _Tp& __value) {
|
||||
if constexpr (same_as<_Tp, chrono::day>)
|
||||
if constexpr (__is_time_point<_Tp>)
|
||||
return true;
|
||||
else if constexpr (same_as<_Tp, chrono::day>)
|
||||
return true;
|
||||
else if constexpr (same_as<_Tp, chrono::month>)
|
||||
return __value.ok();
|
||||
@ -351,7 +366,9 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_ok(const _Tp& __value) {
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_name_ok(const _Tp& __value) {
|
||||
if constexpr (same_as<_Tp, chrono::day>)
|
||||
if constexpr (__is_time_point<_Tp>)
|
||||
return true;
|
||||
else if constexpr (same_as<_Tp, chrono::day>)
|
||||
return true;
|
||||
else if constexpr (same_as<_Tp, chrono::month>)
|
||||
return __value.ok();
|
||||
@ -389,7 +406,9 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_name_ok(const _Tp& __value) {
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool __date_ok(const _Tp& __value) {
|
||||
if constexpr (same_as<_Tp, chrono::day>)
|
||||
if constexpr (__is_time_point<_Tp>)
|
||||
return true;
|
||||
else if constexpr (same_as<_Tp, chrono::day>)
|
||||
return true;
|
||||
else if constexpr (same_as<_Tp, chrono::month>)
|
||||
return __value.ok();
|
||||
@ -427,7 +446,9 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __date_ok(const _Tp& __value) {
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool __month_name_ok(const _Tp& __value) {
|
||||
if constexpr (same_as<_Tp, chrono::day>)
|
||||
if constexpr (__is_time_point<_Tp>)
|
||||
return true;
|
||||
else if constexpr (same_as<_Tp, chrono::day>)
|
||||
return true;
|
||||
else if constexpr (same_as<_Tp, chrono::month>)
|
||||
return __value.ok();
|
||||
@ -559,6 +580,17 @@ public:
|
||||
__format_spec::__parser_chrono<_CharT> __parser_;
|
||||
};
|
||||
|
||||
template <class _Duration, __fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::sys_time<_Duration>, _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::__clock);
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Rep, class _Period, __fmt_char_type _CharT>
|
||||
struct formatter<chrono::duration<_Rep, _Period>, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
#include <__chrono/month_weekday.h>
|
||||
#include <__chrono/monthday.h>
|
||||
#include <__chrono/statically_widen.h>
|
||||
#include <__chrono/system_clock.h>
|
||||
#include <__chrono/weekday.h>
|
||||
#include <__chrono/year.h>
|
||||
#include <__chrono/year_month.h>
|
||||
@ -38,6 +39,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
namespace chrono {
|
||||
|
||||
template <class _CharT, class _Traits, class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
|
||||
operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_time<_Duration> __tp) {
|
||||
return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp);
|
||||
}
|
||||
|
||||
// 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() {
|
||||
|
||||
@ -286,6 +286,10 @@ template <class Duration>
|
||||
using sys_seconds = sys_time<seconds>; // C++20
|
||||
using sys_days = sys_time<days>; // C++20
|
||||
|
||||
template<class charT, class traits, class Duration> // C++20
|
||||
basic_ostream<charT, traits>&
|
||||
operator<<(basic_ostream<charT, traits>& os, const sys_time<Duration>& tp);
|
||||
|
||||
class file_clock // C++20
|
||||
{
|
||||
public:
|
||||
@ -682,6 +686,8 @@ bool operator>=(const time_zone& x, const time_zone& y) noexcept;
|
||||
} // chrono
|
||||
|
||||
namespace std {
|
||||
template<class Duration, class charT>
|
||||
struct formatter<chrono::sys_time<Duration>, charT>; // C++20
|
||||
template<class Rep, class Period, class charT>
|
||||
struct formatter<chrono::duration<Rep, Period>, charT>; // C++20
|
||||
template<class charT> struct formatter<chrono::day, charT>; // C++20
|
||||
|
||||
@ -0,0 +1,197 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: no-localization
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// TODO FMT Investigate Windows issues.
|
||||
// UNSUPPORTED msvc, target={{.+}}-windows-gnu
|
||||
// TODO FMT It seems GCC uses too much memory in the CI and fails.
|
||||
// UNSUPPORTED: gcc-12
|
||||
|
||||
// TODO FMT This test should not require std::to_chars(floating-point)
|
||||
// XFAIL: availability-fp_to_chars-missing
|
||||
|
||||
// REQUIRES: locale.fr_FR.UTF-8
|
||||
// REQUIRES: locale.ja_JP.UTF-8
|
||||
|
||||
// <chrono>
|
||||
|
||||
// class system_clock;
|
||||
|
||||
// template<class charT, class traits, class Duration>
|
||||
// basic_ostream<charT, traits>&
|
||||
// operator<<(basic_ostream<charT, traits>& os, const sys_time<Duration>& tp);
|
||||
|
||||
#include <chrono>
|
||||
#include <cassert>
|
||||
#include <ratio>
|
||||
#include <sstream>
|
||||
|
||||
#include "make_string.h"
|
||||
#include "platform_support.h" // locale name macros
|
||||
#include "test_macros.h"
|
||||
|
||||
#define SV(S) MAKE_STRING_VIEW(CharT, S)
|
||||
|
||||
template <class CharT, class Duration>
|
||||
static std::basic_string<CharT> stream_c_locale(std::chrono::sys_time<Duration> time_point) {
|
||||
std::basic_stringstream<CharT> sstr;
|
||||
sstr << std::fixed << time_point;
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
template <class CharT, class Duration>
|
||||
static std::basic_string<CharT> stream_fr_FR_locale(std::chrono::sys_time<Duration> time_point) {
|
||||
std::basic_stringstream<CharT> sstr;
|
||||
const std::locale locale(LOCALE_fr_FR_UTF_8);
|
||||
sstr.imbue(locale);
|
||||
sstr << std::fixed << time_point;
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
template <class CharT, class Duration>
|
||||
static std::basic_string<CharT> stream_ja_JP_locale(std::chrono::sys_time<Duration> time_point) {
|
||||
std::basic_stringstream<CharT> sstr;
|
||||
const std::locale locale(LOCALE_ja_JP_UTF_8);
|
||||
sstr.imbue(locale);
|
||||
sstr << std::fixed << time_point;
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test_c() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
assert(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::nanoseconds>{946'688'523'123'456'789ns}) ==
|
||||
SV("2000-01-01 01:02:03.123456789"));
|
||||
assert(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::microseconds>{946'688'523'123'456us}) ==
|
||||
SV("2000-01-01 01:02:03.123456"));
|
||||
|
||||
assert(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::milliseconds>{946'684'800'123ms}) ==
|
||||
SV("2000-01-01 00:00:00.123"));
|
||||
assert(stream_c_locale<CharT>(std::chrono::sys_seconds{1'234'567'890s}) == SV("2009-02-13 23:31:30"));
|
||||
assert(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::minutes>{20'576'131min}) ==
|
||||
SV("2009-02-13 23:31:00"));
|
||||
assert(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::hours>{342'935h}) == SV("2009-02-13 23:00:00"));
|
||||
assert(stream_c_locale<CharT>(std::chrono::sys_days{std::chrono::days{14'288}}) == SV("2009-02-13 00:00:00"));
|
||||
assert(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::weeks>{std::chrono::weeks{2041}}) ==
|
||||
SV("2009-02-12 00:00:00"));
|
||||
|
||||
assert(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::duration<signed char, std::ratio<2, 1>>>{
|
||||
std::chrono::duration<signed char, std::ratio<2, 1>>{60}}) == SV("1970-01-01 00:02:00"));
|
||||
assert(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::duration<short, std::ratio<1, 2>>>{
|
||||
std::chrono::duration<short, std::ratio<1, 2>>{3600}}) == SV("1970-01-01 00:30:00.0"));
|
||||
assert(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::duration<int, std::ratio<1, 4>>>{
|
||||
std::chrono::duration<int, std::ratio<1, 4>>{3600}}) == SV("1970-01-01 00:15:00.00"));
|
||||
assert(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::duration<long, std::ratio<1, 10>>>{
|
||||
std::chrono::duration<long, std::ratio<1, 10>>{36611}}) == SV("1970-01-01 01:01:01.1"));
|
||||
assert(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::duration<long long, std::ratio<1, 100>>>{
|
||||
std::chrono::duration<long long, std::ratio<1, 100>>{12'345'678'9010}}) == SV("2009-02-13 23:31:30.10"));
|
||||
|
||||
assert(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::duration<float, std::ratio<1, 1>>>{
|
||||
std::chrono::duration<float, std::ratio<1, 1>>{123.456}}) == SV("1970-01-01 00:02:03"));
|
||||
assert(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::duration<double, std::ratio<1, 10>>>{
|
||||
std::chrono::duration<double, std::ratio<1, 10>>{123.456}}) == SV("1970-01-01 00:00:12.3"));
|
||||
assert(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::duration<long double, std::ratio<1, 100>>>{
|
||||
std::chrono::duration<long double, std::ratio<1, 100>>{123.456}}) == SV("1970-01-01 00:00:01.23"));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test_fr_FR() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
assert(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::nanoseconds>{946'688'523'123'456'789ns}) ==
|
||||
SV("2000-01-01 01:02:03,123456789"));
|
||||
assert(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::microseconds>{946'688'523'123'456us}) ==
|
||||
SV("2000-01-01 01:02:03,123456"));
|
||||
|
||||
assert(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::milliseconds>{946'684'800'123ms}) ==
|
||||
SV("2000-01-01 00:00:00,123"));
|
||||
assert(stream_fr_FR_locale<CharT>(std::chrono::sys_seconds{1'234'567'890s}) == SV("2009-02-13 23:31:30"));
|
||||
assert(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::minutes>{20'576'131min}) ==
|
||||
SV("2009-02-13 23:31:00"));
|
||||
assert(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::hours>{342'935h}) == SV("2009-02-13 23:00:00"));
|
||||
assert(stream_fr_FR_locale<CharT>(std::chrono::sys_days{std::chrono::days{14'288}}) == SV("2009-02-13 00:00:00"));
|
||||
assert(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::weeks>{std::chrono::weeks{2041}}) ==
|
||||
SV("2009-02-12 00:00:00"));
|
||||
|
||||
assert(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::duration<signed char, std::ratio<2, 1>>>{
|
||||
std::chrono::duration<signed char, std::ratio<2, 1>>{60}}) == SV("1970-01-01 00:02:00"));
|
||||
assert(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::duration<short, std::ratio<1, 2>>>{
|
||||
std::chrono::duration<short, std::ratio<1, 2>>{3600}}) == SV("1970-01-01 00:30:00,0"));
|
||||
assert(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::duration<int, std::ratio<1, 4>>>{
|
||||
std::chrono::duration<int, std::ratio<1, 4>>{3600}}) == SV("1970-01-01 00:15:00,00"));
|
||||
assert(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::duration<long, std::ratio<1, 10>>>{
|
||||
std::chrono::duration<long, std::ratio<1, 10>>{36611}}) == SV("1970-01-01 01:01:01,1"));
|
||||
assert(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::duration<long long, std::ratio<1, 100>>>{
|
||||
std::chrono::duration<long long, std::ratio<1, 100>>{12'345'678'9010}}) == SV("2009-02-13 23:31:30,10"));
|
||||
|
||||
assert(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::duration<float, std::ratio<1, 1>>>{
|
||||
std::chrono::duration<float, std::ratio<1, 1>>{123.456}}) == SV("1970-01-01 00:02:03"));
|
||||
assert(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::duration<double, std::ratio<1, 10>>>{
|
||||
std::chrono::duration<double, std::ratio<1, 10>>{123.456}}) == SV("1970-01-01 00:00:12,3"));
|
||||
assert(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::duration<long double, std::ratio<1, 100>>>{
|
||||
std::chrono::duration<long double, std::ratio<1, 100>>{123.456}}) == SV("1970-01-01 00:00:01,23"));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test_ja_JP() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
assert(stream_ja_JP_locale<CharT>(std::chrono::sys_time<std::chrono::nanoseconds>{946'688'523'123'456'789ns}) ==
|
||||
SV("2000-01-01 01:02:03.123456789"));
|
||||
assert(stream_ja_JP_locale<CharT>(std::chrono::sys_time<std::chrono::microseconds>{946'688'523'123'456us}) ==
|
||||
SV("2000-01-01 01:02:03.123456"));
|
||||
|
||||
assert(stream_ja_JP_locale<CharT>(std::chrono::sys_time<std::chrono::milliseconds>{946'684'800'123ms}) ==
|
||||
SV("2000-01-01 00:00:00.123"));
|
||||
assert(stream_ja_JP_locale<CharT>(std::chrono::sys_seconds{1'234'567'890s}) == SV("2009-02-13 23:31:30"));
|
||||
assert(stream_ja_JP_locale<CharT>(std::chrono::sys_time<std::chrono::minutes>{20'576'131min}) ==
|
||||
SV("2009-02-13 23:31:00"));
|
||||
assert(stream_ja_JP_locale<CharT>(std::chrono::sys_time<std::chrono::hours>{342'935h}) == SV("2009-02-13 23:00:00"));
|
||||
assert(stream_ja_JP_locale<CharT>(std::chrono::sys_days{std::chrono::days{14'288}}) == SV("2009-02-13 00:00:00"));
|
||||
assert(stream_ja_JP_locale<CharT>(std::chrono::sys_time<std::chrono::weeks>{std::chrono::weeks{2041}}) ==
|
||||
SV("2009-02-12 00:00:00"));
|
||||
|
||||
assert(stream_ja_JP_locale<CharT>(std::chrono::sys_time<std::chrono::duration<signed char, std::ratio<2, 1>>>{
|
||||
std::chrono::duration<signed char, std::ratio<2, 1>>{60}}) == SV("1970-01-01 00:02:00"));
|
||||
assert(stream_ja_JP_locale<CharT>(std::chrono::sys_time<std::chrono::duration<short, std::ratio<1, 2>>>{
|
||||
std::chrono::duration<short, std::ratio<1, 2>>{3600}}) == SV("1970-01-01 00:30:00.0"));
|
||||
assert(stream_ja_JP_locale<CharT>(std::chrono::sys_time<std::chrono::duration<int, std::ratio<1, 4>>>{
|
||||
std::chrono::duration<int, std::ratio<1, 4>>{3600}}) == SV("1970-01-01 00:15:00.00"));
|
||||
assert(stream_ja_JP_locale<CharT>(std::chrono::sys_time<std::chrono::duration<long, std::ratio<1, 10>>>{
|
||||
std::chrono::duration<long, std::ratio<1, 10>>{36611}}) == SV("1970-01-01 01:01:01.1"));
|
||||
assert(stream_ja_JP_locale<CharT>(std::chrono::sys_time<std::chrono::duration<long long, std::ratio<1, 100>>>{
|
||||
std::chrono::duration<long long, std::ratio<1, 100>>{12'345'678'9010}}) == SV("2009-02-13 23:31:30.10"));
|
||||
|
||||
assert(stream_ja_JP_locale<CharT>(std::chrono::sys_time<std::chrono::duration<float, std::ratio<1, 1>>>{
|
||||
std::chrono::duration<float, std::ratio<1, 1>>{123.456}}) == SV("1970-01-01 00:02:03"));
|
||||
assert(stream_ja_JP_locale<CharT>(std::chrono::sys_time<std::chrono::duration<double, std::ratio<1, 10>>>{
|
||||
std::chrono::duration<double, std::ratio<1, 10>>{123.456}}) == SV("1970-01-01 00:00:12.3"));
|
||||
assert(stream_ja_JP_locale<CharT>(std::chrono::sys_time<std::chrono::duration<long double, std::ratio<1, 100>>>{
|
||||
std::chrono::duration<long double, std::ratio<1, 100>>{123.456}}) == SV("1970-01-01 00:00:01.23"));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test() {
|
||||
test_c<CharT>();
|
||||
test_fr_FR<CharT>();
|
||||
test_ja_JP<CharT>();
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test<char>();
|
||||
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
test<wchar_t>();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
940
libcxx/test/std/time/time.syn/formatter.sys_time.pass.cpp
Normal file
940
libcxx/test/std/time/time.syn/formatter.sys_time.pass.cpp
Normal file
@ -0,0 +1,940 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: no-localization
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// XFAIL: LIBCXX-FREEBSD-FIXME
|
||||
|
||||
// TODO FMT This test should not require std::to_chars(floating-point)
|
||||
// XFAIL: availability-fp_to_chars-missing
|
||||
|
||||
// TODO FMT Investigate Windows issues.
|
||||
// UNSUPPORTED: msvc, target={{.+}}-windows-gnu
|
||||
// TODO FMT It seems GCC uses too much memory in the CI and fails.
|
||||
// UNSUPPORTED: gcc-12
|
||||
|
||||
// REQUIRES: locale.fr_FR.UTF-8
|
||||
// REQUIRES: locale.ja_JP.UTF-8
|
||||
|
||||
// <chrono>
|
||||
//
|
||||
// template<class charT> struct formatter<chrono::day, charT>;
|
||||
|
||||
#include <chrono>
|
||||
#include <format>
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <locale>
|
||||
#include <iostream>
|
||||
#include <type_traits>
|
||||
|
||||
#include "formatter_tests.h"
|
||||
#include "make_string.h"
|
||||
#include "platform_support.h" // locale name macros
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class CharT>
|
||||
static void test_no_chrono_specs() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||
|
||||
// Non localized output
|
||||
check(SV("1970-01-01 00:00:00"), SV("{}"), std::chrono::sys_seconds(0s));
|
||||
check(SV("2000-01-01 00:00:00"), SV("{}"), std::chrono::sys_seconds(946'684'800s));
|
||||
check(SV("2000-01-01 01:02:03"), SV("{}"), std::chrono::sys_seconds(946'688'523s));
|
||||
|
||||
check(SV("2000-01-01 01:02:03.123"), SV("{}"), std::chrono::sys_time<std::chrono::milliseconds>(946'688'523'123ms));
|
||||
|
||||
std::locale::global(std::locale::classic());
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test_valid_values_year() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
constexpr std::basic_string_view<CharT> fmt =
|
||||
SV("{:%%C='%C'%t%%EC='%EC'%t%%y='%y'%t%%Oy='%Oy'%t%%Ey='%Ey'%t%%Y='%Y'%t%%EY='%EY'%n}");
|
||||
constexpr std::basic_string_view<CharT> lfmt =
|
||||
SV("{:L%%C='%C'%t%%EC='%EC'%t%%y='%y'%t%%Oy='%Oy'%t%%Ey='%Ey'%t%%Y='%Y'%t%%EY='%EY'%n}");
|
||||
|
||||
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||
|
||||
// Non localized output using C-locale
|
||||
check(SV("%C='19'\t%EC='19'\t%y='70'\t%Oy='70'\t%Ey='70'\t%Y='1970'\t%EY='1970'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
|
||||
// Use the global locale (fr_FR)
|
||||
check(SV("%C='19'\t%EC='19'\t%y='70'\t%Oy='70'\t%Ey='70'\t%Y='1970'\t%EY='1970'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
|
||||
// Use supplied locale (ja_JP). This locale has a different alternate.
|
||||
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX)
|
||||
check(loc,
|
||||
SV("%C='19'\t%EC='19'\t%y='70'\t%Oy='70'\t%Ey='70'\t%Y='1970'\t%EY='1970'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)
|
||||
check(loc,
|
||||
SV("%C='19'\t%EC='昭和'\t%y='70'\t%Oy='七十'\t%Ey='45'\t%Y='1970'\t%EY='昭和45年'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%C='20'\t%EC='平成'\t%y='09'\t%Oy='九'\t%Ey='21'\t%Y='2009'\t%EY='平成21年'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)
|
||||
|
||||
std::locale::global(std::locale::classic());
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test_valid_values_month() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
constexpr std::basic_string_view<CharT> fmt = SV("{:%%b='%b'%t%%h='%h'%t%%B='%B'%t%%m='%m'%t%%Om='%Om'%n}");
|
||||
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%b='%b'%t%%h='%h'%t%%B='%B'%t%%m='%m'%t%%Om='%Om'%n}");
|
||||
|
||||
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||
|
||||
// Non localized output using C-locale
|
||||
check(SV("%b='Jan'\t%h='Jan'\t%B='January'\t%m='01'\t%Om='01'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%b='May'\t%h='May'\t%B='May'\t%m='05'\t%Om='05'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
|
||||
|
||||
// Use the global locale (fr_FR)
|
||||
#if defined(__APPLE__)
|
||||
check(SV("%b='jan'\t%h='jan'\t%B='janvier'\t%m='01'\t%Om='01'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
#else
|
||||
check(SV("%b='janv.'\t%h='janv.'\t%B='janvier'\t%m='01'\t%Om='01'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
#endif
|
||||
|
||||
check(SV("%b='mai'\t%h='mai'\t%B='mai'\t%m='05'\t%Om='05'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
|
||||
|
||||
// Use supplied locale (ja_JP). This locale has a different alternate.
|
||||
#ifdef _WIN32
|
||||
check(loc,
|
||||
SV("%b='1'\t%h='1'\t%B='1月'\t%m='01'\t%Om='01'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%b='5'\t%h='5'\t%B='5月'\t%m='05'\t%Om='05'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
|
||||
#elif defined(_AIX) // _WIN32
|
||||
check(loc,
|
||||
SV("%b='1月'\t%h='1月'\t%B='1月'\t%m='01'\t%Om='01'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%b='5月'\t%h='5月'\t%B='5月'\t%m='05'\t%Om='05'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
|
||||
#elif defined(__APPLE__) // _WIN32
|
||||
check(loc,
|
||||
SV("%b=' 1'\t%h=' 1'\t%B='1月'\t%m='01'\t%Om='01'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%b=' 5'\t%h=' 5'\t%B='5月'\t%m='05'\t%Om='05'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
|
||||
#else // _WIN32
|
||||
check(loc,
|
||||
SV("%b=' 1月'\t%h=' 1月'\t%B='1月'\t%m='01'\t%Om='一'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%b=' 5月'\t%h=' 5月'\t%B='5月'\t%m='05'\t%Om='五'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
|
||||
#endif // _WIN32
|
||||
|
||||
std::locale::global(std::locale::classic());
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test_valid_values_day() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
constexpr std::basic_string_view<CharT> fmt = SV("{:%%d='%d'%t%%Od='%Od'%t%%e='%e'%t%%Oe='%Oe'%n}");
|
||||
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%d='%d'%t%%Od='%Od'%t%%e='%e'%t%%Oe='%Oe'%n}");
|
||||
|
||||
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||
|
||||
// Non localized output using C-locale
|
||||
check(SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
|
||||
// Use the global locale (fr_FR)
|
||||
check(SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
|
||||
// Use supplied locale (ja_JP). This locale has a different alternate.
|
||||
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX)
|
||||
check(loc,
|
||||
SV("%d='01'\t%Od='01'\t%e=' 1'\t%Oe=' 1'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
#else // _WIN32
|
||||
check(loc,
|
||||
SV("%d='01'\t%Od='一'\t%e=' 1'\t%Oe='一'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%d='13'\t%Od='十三'\t%e='13'\t%Oe='十三'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
std::locale::global(std::locale::classic());
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test_valid_values_weekday() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
constexpr std::basic_string_view<CharT> fmt =
|
||||
SV("{:%%a='%a'%t%%A='%A'%t%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");
|
||||
constexpr std::basic_string_view<CharT> lfmt =
|
||||
SV("{:L%%a='%a'%t%%A='%A'%t%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");
|
||||
|
||||
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||
|
||||
// Non localized output using C-locale
|
||||
check(SV("%a='Thu'\t%A='Thursday'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%a='Sun'\t%A='Sunday'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106
|
||||
|
||||
// Use the global locale (fr_FR)
|
||||
#if defined(__APPLE__)
|
||||
check(SV("%a='Jeu'\t%A='Jeudi'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%a='Dim'\t%A='Dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106
|
||||
#else
|
||||
check(SV("%a='jeu.'\t%A='jeudi'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%a='dim.'\t%A='dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106
|
||||
#endif
|
||||
|
||||
// Use supplied locale (ja_JP).
|
||||
// This locale has a different alternate, but not on all platforms
|
||||
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX)
|
||||
check(loc,
|
||||
SV("%a='木'\t%A='木曜日'\t%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106
|
||||
#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)
|
||||
check(loc,
|
||||
SV("%a='木'\t%A='木曜日'\t%u='4'\t%Ou='四'\t%w='4'\t%Ow='四'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='七'\t%w='0'\t%Ow='〇'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(4'294'967'295s)); // 06:28:15 UTC on Sunday, 7 February 2106
|
||||
#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)
|
||||
|
||||
std::locale::global(std::locale::classic());
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test_valid_values_day_of_year() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
constexpr std::basic_string_view<CharT> fmt = SV("{:%%j='%j'%n}");
|
||||
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%j='%j'%n}");
|
||||
|
||||
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||
|
||||
// Non localized output using C-locale
|
||||
check(SV("%j='001'\n"), fmt, std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
check(SV("%j='138'\n"), fmt, std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
|
||||
|
||||
// Use the global locale (fr_FR)
|
||||
check(SV("%j='001'\n"), lfmt, std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
check(SV("%j='138'\n"), lfmt, std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
|
||||
|
||||
// Use supplied locale (ja_JP). This locale has a different alternate.
|
||||
check(loc, SV("%j='001'\n"), lfmt, std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(
|
||||
loc, SV("%j='138'\n"), lfmt, std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
|
||||
|
||||
std::locale::global(std::locale::classic());
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test_valid_values_week() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
constexpr std::basic_string_view<CharT> fmt = SV("{:%%U='%U'%t%%OU='%OU'%t%%W='%W'%t%%OW='%OW'%n}");
|
||||
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%U='%U'%t%%OU='%OU'%t%%W='%W'%t%%OW='%OW'%n}");
|
||||
|
||||
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||
|
||||
// Non localized output using C-locale
|
||||
check(SV("%U='00'\t%OU='00'\t%W='00'\t%OW='00'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
|
||||
|
||||
// Use the global locale (fr_FR)
|
||||
check(SV("%U='00'\t%OU='00'\t%W='00'\t%OW='00'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
|
||||
|
||||
// Use supplied locale (ja_JP). This locale has a different alternate.
|
||||
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX)
|
||||
check(loc,
|
||||
SV("%U='00'\t%OU='00'\t%W='00'\t%OW='00'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
|
||||
#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)
|
||||
check(loc,
|
||||
SV("%U='00'\t%OU='〇'\t%W='00'\t%OW='〇'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%U='20'\t%OU='二十'\t%W='20'\t%OW='二十'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(2'000'000'000s)); // 03:33:20 UTC on Wednesday, 18 May 2033
|
||||
#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)
|
||||
std::locale::global(std::locale::classic());
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test_valid_values_iso_8601_week() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
constexpr std::basic_string_view<CharT> fmt = SV("{:%%g='%g'%t%%G='%G'%t%%V='%V'%t%%OV='%OV'%n}");
|
||||
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%g='%g'%t%%G='%G'%t%%V='%V'%t%%OV='%OV'%n}");
|
||||
|
||||
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||
|
||||
// Non localized output using C-locale
|
||||
check(SV("%g='70'\t%G='1970'\t%V='01'\t%OV='01'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
|
||||
// Use the global locale (fr_FR)
|
||||
check(SV("%g='70'\t%G='1970'\t%V='01'\t%OV='01'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
|
||||
// Use supplied locale (ja_JP). This locale has a different alternate.
|
||||
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX)
|
||||
check(loc,
|
||||
SV("%g='70'\t%G='1970'\t%V='01'\t%OV='01'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)
|
||||
check(loc,
|
||||
SV("%g='70'\t%G='1970'\t%V='01'\t%OV='一'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%g='09'\t%G='2009'\t%V='07'\t%OV='七'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)
|
||||
|
||||
std::locale::global(std::locale::classic());
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test_valid_values_date() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
constexpr std::basic_string_view<CharT> fmt = SV("{:%%D='%D'%t%%F='%F'%t%%x='%x'%t%%Ex='%Ex'%n}");
|
||||
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%D='%D'%t%%F='%F'%t%%x='%x'%t%%Ex='%Ex'%n}");
|
||||
|
||||
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||
|
||||
// Non localized output using C-locale
|
||||
check(SV("%D='01/01/70'\t%F='1970-01-01'\t%x='01/01/70'\t%Ex='01/01/70'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='02/13/09'\t%Ex='02/13/09'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
|
||||
// Use the global locale (fr_FR)
|
||||
#if defined(__APPLE__)
|
||||
check(SV("%D='01/01/70'\t%F='1970-01-01'\t%x='01.01.1970'\t%Ex='01.01.1970'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='13.02.2009'\t%Ex='13.02.2009'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
#else
|
||||
check(SV("%D='01/01/70'\t%F='1970-01-01'\t%x='01/01/1970'\t%Ex='01/01/1970'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='13/02/2009'\t%Ex='13/02/2009'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
#endif
|
||||
|
||||
// Use supplied locale (ja_JP). This locale has a different alternate.
|
||||
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX)
|
||||
check(loc,
|
||||
SV("%D='01/01/70'\t%F='1970-01-01'\t%x='1970/01/01'\t%Ex='1970/01/01'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%D='02/13/09'\t%F='2009-02-13'\t%x='2009/02/13'\t%Ex='2009/02/13'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)
|
||||
check(loc,
|
||||
SV("%D='01/01/70'\t%F='1970-01-01'\t%x='1970年01月01日'\t%Ex='昭和45年01月01日'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%D='02/13/09'\t%F='2009-02-13'\t%x='2009年02月13日'\t%Ex='平成21年02月13日'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)
|
||||
|
||||
std::locale::global(std::locale::classic());
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test_valid_values_time() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
constexpr std::basic_string_view<CharT> fmt = SV(
|
||||
"{:"
|
||||
"%%H='%H'%t"
|
||||
"%%OH='%OH'%t"
|
||||
"%%I='%I'%t"
|
||||
"%%OI='%OI'%t"
|
||||
"%%M='%M'%t"
|
||||
"%%OM='%OM'%t"
|
||||
"%%S='%S'%t"
|
||||
"%%OS='%OS'%t"
|
||||
"%%p='%p'%t"
|
||||
"%%R='%R'%t"
|
||||
"%%T='%T'%t"
|
||||
"%%r='%r'%t"
|
||||
"%%X='%X'%t"
|
||||
"%%EX='%EX'%t"
|
||||
"%n}");
|
||||
constexpr std::basic_string_view<CharT> lfmt = SV(
|
||||
"{:L"
|
||||
"%%H='%H'%t"
|
||||
"%%OH='%OH'%t"
|
||||
"%%I='%I'%t"
|
||||
"%%OI='%OI'%t"
|
||||
"%%M='%M'%t"
|
||||
"%%OM='%OM'%t"
|
||||
"%%S='%S'%t"
|
||||
"%%OS='%OS'%t"
|
||||
"%%p='%p'%t"
|
||||
"%%R='%R'%t"
|
||||
"%%T='%T'%t"
|
||||
"%%r='%r'%t"
|
||||
"%%X='%X'%t"
|
||||
"%%EX='%EX'%t"
|
||||
"%n}");
|
||||
|
||||
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||
|
||||
// Non localized output using C-locale
|
||||
check(SV("%H='00'\t"
|
||||
"%OH='00'\t"
|
||||
"%I='12'\t"
|
||||
"%OI='12'\t"
|
||||
"%M='00'\t"
|
||||
"%OM='00'\t"
|
||||
"%S='00'\t"
|
||||
"%OS='00'\t"
|
||||
"%p='AM'\t"
|
||||
"%R='00:00'\t"
|
||||
"%T='00:00:00'\t"
|
||||
"%r='12:00:00 AM'\t"
|
||||
"%X='00:00:00'\t"
|
||||
"%EX='00:00:00'\t"
|
||||
"\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%H='23'\t"
|
||||
"%OH='23'\t"
|
||||
"%I='11'\t"
|
||||
"%OI='11'\t"
|
||||
"%M='31'\t"
|
||||
"%OM='31'\t"
|
||||
"%S='30.123'\t"
|
||||
"%OS='30.123'\t"
|
||||
"%p='PM'\t"
|
||||
"%R='23:31'\t"
|
||||
"%T='23:31:30.123'\t"
|
||||
"%r='11:31:30 PM'\t"
|
||||
"%X='23:31:30'\t"
|
||||
"%EX='23:31:30'\t"
|
||||
"\n"),
|
||||
fmt,
|
||||
std::chrono::sys_time<std::chrono::milliseconds>(
|
||||
1'234'567'890'123ms)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
// Use the global locale (fr_FR)
|
||||
check(SV("%H='00'\t"
|
||||
"%OH='00'\t"
|
||||
"%I='12'\t"
|
||||
"%OI='12'\t"
|
||||
"%M='00'\t"
|
||||
"%OM='00'\t"
|
||||
"%S='00'\t"
|
||||
"%OS='00'\t"
|
||||
#if defined(_AIX)
|
||||
"%p='AM'\t"
|
||||
#else
|
||||
"%p=''\t"
|
||||
#endif
|
||||
"%R='00:00'\t"
|
||||
"%T='00:00:00'\t"
|
||||
#ifdef _WIN32
|
||||
"%r='00:00:00'\t"
|
||||
#elif defined(_AIX)
|
||||
"%r='12:00:00 AM'\t"
|
||||
#elif defined(__APPLE__)
|
||||
"%r=''\t"
|
||||
#else
|
||||
"%r='12:00:00 '\t"
|
||||
#endif
|
||||
"%X='00:00:00'\t"
|
||||
"%EX='00:00:00'\t"
|
||||
"\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%H='23'\t"
|
||||
"%OH='23'\t"
|
||||
"%I='11'\t"
|
||||
"%OI='11'\t"
|
||||
"%M='31'\t"
|
||||
"%OM='31'\t"
|
||||
"%S='30,123'\t"
|
||||
"%OS='30,123'\t"
|
||||
#if defined(_AIX)
|
||||
"%p='PM'\t"
|
||||
#else
|
||||
"%p=''\t"
|
||||
#endif
|
||||
"%R='23:31'\t"
|
||||
"%T='23:31:30,123'\t"
|
||||
#ifdef _WIN32
|
||||
"%r='23:31:30'\t"
|
||||
#elif defined(_AIX)
|
||||
"%r='11:31:30 PM'\t"
|
||||
#elif defined(__APPLE__)
|
||||
"%r=''\t"
|
||||
#else
|
||||
"%r='11:31:30 '\t"
|
||||
#endif
|
||||
"%X='23:31:30'\t"
|
||||
"%EX='23:31:30'\t"
|
||||
"\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_time<std::chrono::milliseconds>(
|
||||
1'234'567'890'123ms)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
|
||||
// Use supplied locale (ja_JP). This locale has a different alternate.a
|
||||
#if defined(__APPLE__) || defined(_AIX)
|
||||
check(loc,
|
||||
SV("%H='00'\t"
|
||||
"%OH='00'\t"
|
||||
"%I='12'\t"
|
||||
"%OI='12'\t"
|
||||
"%M='00'\t"
|
||||
"%OM='00'\t"
|
||||
"%S='00'\t"
|
||||
"%OS='00'\t"
|
||||
# if defined(__APPLE__)
|
||||
"%p='AM'\t"
|
||||
# else
|
||||
"%p='午前'\t"
|
||||
# endif
|
||||
"%R='00:00'\t"
|
||||
"%T='00:00:00'\t"
|
||||
# if defined(__APPLE__)
|
||||
"%r='12:00:00 AM'\t"
|
||||
"%X='00時00分00秒'\t"
|
||||
"%EX='00時00分00秒'\t"
|
||||
# else
|
||||
"%r='午前12:00:00'\t"
|
||||
"%X='00:00:00'\t"
|
||||
"%EX='00:00:00'\t"
|
||||
# endif
|
||||
"\n"),
|
||||
lfmt,
|
||||
std::chrono::hh_mm_ss(0s));
|
||||
|
||||
check(loc,
|
||||
SV("%H='23'\t"
|
||||
"%OH='23'\t"
|
||||
"%I='11'\t"
|
||||
"%OI='11'\t"
|
||||
"%M='31'\t"
|
||||
"%OM='31'\t"
|
||||
"%S='30.123'\t"
|
||||
"%OS='30.123'\t"
|
||||
# if defined(__APPLE__)
|
||||
"%p='PM'\t"
|
||||
# else
|
||||
"%p='午後'\t"
|
||||
# endif
|
||||
"%R='23:31'\t"
|
||||
"%T='23:31:30.123'\t"
|
||||
# if defined(__APPLE__)
|
||||
"%r='11:31:30 PM'\t"
|
||||
"%X='23時31分30秒'\t"
|
||||
"%EX='23時31分30秒'\t"
|
||||
# else
|
||||
"%r='午後11:31:30'\t"
|
||||
"%X='23:31:30'\t"
|
||||
"%EX='23:31:30'\t"
|
||||
# endif
|
||||
"\n"),
|
||||
lfmt,
|
||||
std::chrono::hh_mm_ss(23h + 31min + 30s + 123ms));
|
||||
#else // defined(__APPLE__) || defined(_AIX)
|
||||
check(loc,
|
||||
SV("%H='00'\t"
|
||||
"%OH='〇'\t"
|
||||
"%I='12'\t"
|
||||
"%OI='十二'\t"
|
||||
"%M='00'\t"
|
||||
"%OM='〇'\t"
|
||||
"%S='00'\t"
|
||||
"%OS='〇'\t"
|
||||
"%p='午前'\t"
|
||||
"%R='00:00'\t"
|
||||
"%T='00:00:00'\t"
|
||||
"%r='午前12時00分00秒'\t"
|
||||
"%X='00時00分00秒'\t"
|
||||
"%EX='00時00分00秒'\t"
|
||||
"\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%H='23'\t"
|
||||
"%OH='二十三'\t"
|
||||
"%I='11'\t"
|
||||
"%OI='十一'\t"
|
||||
"%M='31'\t"
|
||||
"%OM='三十一'\t"
|
||||
"%S='30.123'\t"
|
||||
"%OS='三十.123'\t"
|
||||
"%p='午後'\t"
|
||||
"%R='23:31'\t"
|
||||
"%T='23:31:30.123'\t"
|
||||
"%r='午後11時31分30秒'\t"
|
||||
"%X='23時31分30秒'\t"
|
||||
"%EX='23時31分30秒'\t"
|
||||
"\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_time<std::chrono::milliseconds>(
|
||||
1'234'567'890'123ms)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
#endif // defined(__APPLE__) || defined(_AIX)
|
||||
|
||||
std::locale::global(std::locale::classic());
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test_valid_values_date_time() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
constexpr std::basic_string_view<CharT> fmt = SV("{:%%c='%c'%t%%Ec='%Ec'%n}");
|
||||
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%c='%c'%t%%Ec='%Ec'%n}");
|
||||
|
||||
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||
|
||||
// Non localized output using C-locale
|
||||
check(SV("%c='Thu Jan 1 00:00:00 1970'\t%Ec='Thu Jan 1 00:00:00 1970'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(SV("%c='Fri Feb 13 23:31:30 2009'\t%Ec='Fri Feb 13 23:31:30 2009'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
|
||||
// Use the global locale (fr_FR)
|
||||
check(
|
||||
// https://sourceware.org/bugzilla/show_bug.cgi?id=24054
|
||||
#if defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29
|
||||
SV("%c='jeu. 01 janv. 1970 00:00:00 GMT'\t%Ec='jeu. 01 janv. 1970 00:00:00 GMT'\n"),
|
||||
#elif defined(_AIX)
|
||||
SV("%c=' 1 janvier 1970 à 00:00:00 UTC'\t%Ec=' 1 janvier 1970 à 00:00:00 UTC'\n"),
|
||||
#elif defined(__APPLE__)
|
||||
SV("%c='Jeu 1 jan 00:00:00 1970'\t%Ec='Jeu 1 jan 00:00:00 1970'\n"),
|
||||
#else
|
||||
SV("%c='jeu. 01 janv. 1970 00:00:00'\t%Ec='jeu. 01 janv. 1970 00:00:00'\n"),
|
||||
#endif
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(
|
||||
// https://sourceware.org/bugzilla/show_bug.cgi?id=24054
|
||||
#if defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29
|
||||
SV("%c='ven. 13 févr. 2009 23:31:30 GMT'\t%Ec='ven. 13 févr. 2009 23:31:30 GMT'\n"),
|
||||
#elif defined(_AIX)
|
||||
SV("%c='13 février 2009 à 23:31:30 UTC'\t%Ec='13 février 2009 à 23:31:30 UTC'\n"),
|
||||
#elif defined(__APPLE__)
|
||||
SV("%c='Ven 13 fév 23:31:30 2009'\t%Ec='Ven 13 fév 23:31:30 2009'\n"),
|
||||
#else
|
||||
SV("%c='ven. 13 févr. 2009 23:31:30'\t%Ec='ven. 13 févr. 2009 23:31:30'\n"),
|
||||
#endif
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
|
||||
// Use supplied locale (ja_JP). This locale has a different alternate.a
|
||||
#if defined(__APPLE__)
|
||||
check(loc,
|
||||
SV("%c='木 1/ 1 00:00:00 1970'\t%Ec='木 1/ 1 00:00:00 1970'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
check(loc,
|
||||
SV("%c='金 2/13 23:31:30 2009'\t%Ec='金 2/13 23:31:30 2009'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
#elif defined(_AIX) // __APPLE__
|
||||
check(loc,
|
||||
SV("%c='1970年01月 1日 00:00:00 UTC'\t%Ec='1970年01月 1日 00:00:00 UTC'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
check(loc,
|
||||
SV("%c='2009年02月13日 23:31:30 UTC'\t%Ec='2009年02月13日 23:31:30 UTC'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
#else // __APPLE__
|
||||
check(loc,
|
||||
SV("%c='1970年01月01日 00時00分00秒'\t%Ec='昭和45年01月01日 00時00分00秒'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
check(loc,
|
||||
SV("%c='2009年02月13日 23時31分30秒'\t%Ec='平成21年02月13日 23時31分30秒'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(1'234'567'890s)); // 23:31:30 UTC on Friday, 13 February 2009
|
||||
#endif // __APPLE__
|
||||
|
||||
std::locale::global(std::locale::classic());
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test_valid_values_time_zone() {
|
||||
// The Apple CI gives %z='-0700' %Ez='-0700' %Oz='-0700' %Z='UTC'
|
||||
// -0700 looks like the local time where the CI happens to recide, therefore
|
||||
// omit this test on Apple.
|
||||
#if !defined(__APPLE__)
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
constexpr std::basic_string_view<CharT> fmt = SV("{:%%z='%z'%t%%Ez='%Ez'%t%%Oz='%Oz'%t%%Z='%Z'%n}");
|
||||
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%z='%z'%t%%Ez='%Ez'%t%%Oz='%Oz'%t%%Z='%Z'%n}");
|
||||
|
||||
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||
|
||||
# if defined(_AIX)
|
||||
// Non localized output using C-locale
|
||||
check(SV("%z='UTC'\t%Ez='UTC'\t%Oz='UTC'\t%Z='UTC'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
// Use the global locale (fr_FR)
|
||||
check(SV("%z='UTC'\t%Ez='UTC'\t%Oz='UTC'\t%Z='UTC'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
// Use supplied locale (ja_JP). This locale has a different alternate.a
|
||||
check(loc,
|
||||
SV("%z='UTC'\t%Ez='UTC'\t%Oz='UTC'\t%Z='UTC'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
# else // defined(_AIX)
|
||||
// Non localized output using C-locale
|
||||
check(SV("%z='+0000'\t%Ez='+0000'\t%Oz='+0000'\t%Z='UTC'\n"),
|
||||
fmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
// Use the global locale (fr_FR)
|
||||
check(SV("%z='+0000'\t%Ez='+0000'\t%Oz='+0000'\t%Z='UTC'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
|
||||
// Use supplied locale (ja_JP). This locale has a different alternate.a
|
||||
check(loc,
|
||||
SV("%z='+0000'\t%Ez='+0000'\t%Oz='+〇'\t%Z='UTC'\n"),
|
||||
lfmt,
|
||||
std::chrono::sys_seconds(0s)); // 00:00:00 UTC Thursday, 1 January 1970
|
||||
# endif // defined(_AIX)
|
||||
std::locale::global(std::locale::classic());
|
||||
#endif // !defined(__APPLE__)
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test_valid_values() {
|
||||
test_valid_values_year<CharT>();
|
||||
test_valid_values_month<CharT>();
|
||||
test_valid_values_day<CharT>();
|
||||
test_valid_values_weekday<CharT>();
|
||||
test_valid_values_day_of_year<CharT>();
|
||||
test_valid_values_week<CharT>();
|
||||
test_valid_values_iso_8601_week<CharT>();
|
||||
test_valid_values_date<CharT>();
|
||||
test_valid_values_time<CharT>();
|
||||
test_valid_values_date_time<CharT>();
|
||||
test_valid_values_time_zone<CharT>();
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void test() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
test_no_chrono_specs<CharT>();
|
||||
test_valid_values<CharT>();
|
||||
check_invalid_types<CharT>(
|
||||
{SV("a"), SV("A"), SV("b"), SV("B"), SV("c"), SV("C"), SV("d"), SV("D"), SV("e"), SV("F"), SV("g"),
|
||||
SV("G"), SV("h"), SV("H"), SV("I"), SV("j"), SV("m"), SV("M"), SV("p"), SV("r"), SV("R"), SV("S"),
|
||||
SV("T"), SV("u"), SV("U"), SV("V"), SV("w"), SV("W"), SV("x"), SV("X"), SV("y"), SV("Y"), SV("z"),
|
||||
SV("Z"), SV("Ec"), SV("EC"), SV("Ex"), SV("EX"), SV("Ey"), SV("EY"), SV("Ez"), SV("Od"), SV("Oe"), SV("OH"),
|
||||
SV("OI"), SV("Om"), SV("OM"), SV("OS"), SV("Ou"), SV("OU"), SV("OV"), SV("Ow"), SV("OW"), SV("Oy"), SV("Oz")},
|
||||
std::chrono::sys_seconds(0s));
|
||||
|
||||
check_exception("Expected '%' or '}' in the chrono format-string", SV("{:A"), std::chrono::sys_seconds(0s));
|
||||
check_exception("The chrono-specs contains a '{'", SV("{:%%{"), std::chrono::sys_seconds(0s));
|
||||
check_exception(
|
||||
"End of input while parsing the modifier chrono conversion-spec", SV("{:%"), std::chrono::sys_seconds(0s));
|
||||
check_exception("End of input while parsing the modifier E", SV("{:%E"), std::chrono::sys_seconds(0s));
|
||||
check_exception("End of input while parsing the modifier O", SV("{:%O"), std::chrono::sys_seconds(0s));
|
||||
|
||||
// Precision not allowed
|
||||
check_exception("Expected '%' or '}' in the chrono format-string", SV("{:.3}"), std::chrono::sys_seconds(0s));
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test<char>();
|
||||
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
test<wchar_t>();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -136,7 +136,7 @@ void test_P1361() {
|
||||
|
||||
assert_is_formattable<std::chrono::microseconds, CharT>();
|
||||
|
||||
assert_is_not_formattable<std::chrono::sys_time<std::chrono::microseconds>, CharT>();
|
||||
assert_is_formattable<std::chrono::sys_time<std::chrono::microseconds>, CharT>();
|
||||
//assert_is_formattable<std::chrono::utc_time<std::chrono::microseconds>, CharT>();
|
||||
//assert_is_formattable<std::chrono::tai_time<std::chrono::microseconds>, CharT>();
|
||||
//assert_is_formattable<std::chrono::gps_time<std::chrono::microseconds>, CharT>();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user