diff --git a/libcxx/docs/Status/FormatPaper.csv b/libcxx/docs/Status/FormatPaper.csv --- a/libcxx/docs/Status/FormatPaper.csv +++ b/libcxx/docs/Status/FormatPaper.csv @@ -11,18 +11,18 @@ `[time.syn] `_,"Formatter ``chrono::day``",,Mark de Wever,|Complete|, Clang 16 `[time.syn] `_,"Formatter ``chrono::month``",,Mark de Wever,|Complete|, Clang 16 `[time.syn] `_,"Formatter ``chrono::year``",,Mark de Wever,|Complete|, Clang 16 -`[time.syn] `_,"Formatter ``chrono::weekday``",,Mark de Wever,|In Progress|, -`[time.syn] `_,"Formatter ``chrono::weekday_indexed``",,Mark de Wever,|In Progress|, -`[time.syn] `_,"Formatter ``chrono::weekday_last``",,Mark de Wever,|In Progress|, -`[time.syn] `_,"Formatter ``chrono::month_day``",,Mark de Wever,|In Progress|, -`[time.syn] `_,"Formatter ``chrono::month_day_last``",,Mark de Wever,|In Progress|, -`[time.syn] `_,"Formatter ``chrono::month_weekday``",,Mark de Wever,|In Progress|, -`[time.syn] `_,"Formatter ``chrono::month_weekday_last``",,Mark de Wever,|In Progress|, -`[time.syn] `_,"Formatter ``chrono::year_month``",,Mark de Wever,|In Progress|, -`[time.syn] `_,"Formatter ``chrono::year_month_day``",,Mark de Wever,|In Progress|, -`[time.syn] `_,"Formatter ``chrono::year_month_day_last``",,Mark de Wever,|In Progress|, -`[time.syn] `_,"Formatter ``chrono::year_month_weekday``",,Mark de Wever,|In Progress|, -`[time.syn] `_,"Formatter ``chrono::year_month_weekday_last``",,Mark de Wever,|In Progress|, +`[time.syn] `_,"Formatter ``chrono::weekday``",,Mark de Wever,|Complete|, Clang 16 +`[time.syn] `_,"Formatter ``chrono::weekday_indexed``",,Mark de Wever,|Complete|, Clang 16 +`[time.syn] `_,"Formatter ``chrono::weekday_last``",,Mark de Wever,|Complete|, Clang 16 +`[time.syn] `_,"Formatter ``chrono::month_day``",,Mark de Wever,|Complete|, Clang 16 +`[time.syn] `_,"Formatter ``chrono::month_day_last``",,Mark de Wever,|Complete|, Clang 16 +`[time.syn] `_,"Formatter ``chrono::month_weekday``",,Mark de Wever,|Complete|, Clang 16 +`[time.syn] `_,"Formatter ``chrono::month_weekday_last``",,Mark de Wever,|Complete|, Clang 16 +`[time.syn] `_,"Formatter ``chrono::year_month``",,Mark de Wever,|Complete|, Clang 16 +`[time.syn] `_,"Formatter ``chrono::year_month_day``",,Mark de Wever,|Complete|, Clang 16 +`[time.syn] `_,"Formatter ``chrono::year_month_day_last``",,Mark de Wever,|Complete|, Clang 16 +`[time.syn] `_,"Formatter ``chrono::year_month_weekday``",,Mark de Wever,|Complete|, Clang 16 +`[time.syn] `_,"Formatter ``chrono::year_month_weekday_last``",,Mark de Wever,|Complete|, Clang 16 `[time.syn] `_,"Formatter ``chrono::hh_mm_ss>``",,Mark de Wever,|In Progress|, `[time.syn] `_,"Formatter ``chrono::sys_info``",A ```` implementation,Mark de Wever,, `[time.syn] `_,"Formatter ``chrono::local_info``",A ```` implementation,Mark de Wever,, diff --git a/libcxx/include/__chrono/convert_to_tm.h b/libcxx/include/__chrono/convert_to_tm.h --- a/libcxx/include/__chrono/convert_to_tm.h +++ b/libcxx/include/__chrono/convert_to_tm.h @@ -12,12 +12,23 @@ #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 +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -55,7 +66,58 @@ __result.tm_year = static_cast(__value) - 1900; else if constexpr (same_as<_ChronoT, chrono::weekday>) __result.tm_wday = __value.c_encoding(); - else + 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(__value.day()); + __result.tm_mon = static_cast(__value.month()) - 1; + } else if constexpr (same_as<_ChronoT, chrono::month_day_last>) { + __result.tm_mon = static_cast(__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(__value.month()) - 1; + } else if constexpr (same_as<_ChronoT, chrono::year_month>) { + __result.tm_year = static_cast(__value.year()) - 1900; + __result.tm_mon = static_cast(__value.month()) - 1; + } else if constexpr (same_as<_ChronoT, chrono::year_month_day> || same_as<_ChronoT, chrono::year_month_day_last>) { + if (__value.ok()) { + time_t __t = chrono::system_clock::to_time_t(static_cast(__value)); +# ifdef _LIBCPP_WIN32API // Windows doesn't have gmtime_r, but gmtime is thread-safe. + __result = *gmtime(std::addressof(__t)); +# else + gmtime_r(std::addressof(__t), std::addressof(__result)); +# endif + } else { + __result.tm_year = static_cast(__value.year()) - 1900; + __result.tm_mon = static_cast(__value.month()) - 1; + __result.tm_mday = static_cast(__value.day()); + } + } else if constexpr (same_as<_ChronoT, chrono::year_month_weekday> || + same_as<_ChronoT, chrono::year_month_weekday_last>) { + // The interesting question is what is the date of a year_month_weekday. + // - ok() specifies the date as ok when it's round-trippable. So if an + // index of 5 may change the month making the date invalid. An index of + // 0 is invalid. + // - sys_days() gives a valid result if y_.ok() && m_.ok() && + // wdi_.weekday().ok(). The date is specified in terms of index() and + // even specifies an invalid index of 0. + + if (__value.year().ok() && __value.month().ok() && __value.weekday().ok()) { + time_t __t = chrono::system_clock::to_time_t(static_cast(__value)); +# ifdef _LIBCPP_WIN32API // Windows doesn't have gmtime_r, but gmtime is thread-safe. + __result = *gmtime(std::addressof(__t)); +# else + gmtime_r(std::addressof(__t), std::addressof(__result)); +# endif + } else { + // When the index doesn't result in a valid date nothing might be known + // This includes the valid index 5. For example the 5th Monday of January 1970 doesn't exist + + __result.tm_year = static_cast(__value.year()) - 1900; + __result.tm_mon = static_cast(__value.month()) - 1; + __result.tm_wday = static_cast(__value.weekday().c_encoding()); + } + } else static_assert(sizeof(_ChronoT) == 0, "Add the missing type specialization"); return __result; diff --git a/libcxx/include/__chrono/formatter.h b/libcxx/include/__chrono/formatter.h --- a/libcxx/include/__chrono/formatter.h +++ b/libcxx/include/__chrono/formatter.h @@ -10,17 +10,23 @@ #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> @@ -249,6 +255,15 @@ __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 @@ -276,7 +291,7 @@ } template -_LIBCPP_HIDE_FROM_ABI constexpr bool __month_name_ok(const _Tp& __value) { +_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>) @@ -285,6 +300,28 @@ 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"); } @@ -299,6 +336,100 @@ 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 +_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 +_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"); } @@ -331,9 +462,19 @@ // 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"); @@ -436,6 +577,141 @@ } }; +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + // TODO FMT is there a way to extract the index? + // %i as an option? + + _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 + : 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 + : 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 + : 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 + : 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 + : 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 + : 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 + : 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 + : 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 + : 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 + : 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 diff --git a/libcxx/include/__chrono/ostream.h b/libcxx/include/__chrono/ostream.h --- a/libcxx/include/__chrono/ostream.h +++ b/libcxx/include/__chrono/ostream.h @@ -13,9 +13,14 @@ #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> @@ -136,6 +141,94 @@ static_cast(__wd.c_encoding()))); } +template +_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 +_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 +_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 Februari 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 +_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 +_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 +_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 +_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 +_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 +_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 +_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 +_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) diff --git a/libcxx/include/__chrono/parser_std_format_spec.h b/libcxx/include/__chrono/parser_std_format_spec.h --- a/libcxx/include/__chrono/parser_std_format_spec.h +++ b/libcxx/include/__chrono/parser_std_format_spec.h @@ -243,17 +243,20 @@ break; case _CharT('j'): + __parser_.__day_of_year_ = true; __format_spec::__validate_date_or_duration(__flags); break; case _CharT('g'): - case _CharT('x'): - case _CharT('D'): - case _CharT('F'): 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; @@ -267,6 +270,8 @@ [[fallthrough]]; case _CharT('u'): case _CharT('w'): + __parser_.__weekday_ = true; + __validate_weekday(__flags); __format_spec::__validate_weekday(__flags); break; @@ -373,11 +378,13 @@ 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; diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h --- a/libcxx/include/__format/parser_std_format_spec.h +++ b/libcxx/include/__format/parser_std_format_spec.h @@ -186,6 +186,9 @@ __alignment __alignment_ : 3; bool __locale_specific_form_ : 1; bool __weekday_name_ : 1; + bool __weekday_ : 1; + bool __day_of_year_ : 1; + bool __week_of_year_ : 1; bool __month_name_ : 1; }; @@ -309,10 +312,14 @@ _LIBCPP_HIDE_FROM_ABI __parsed_specifications<_CharT> __get_parsed_chrono_specifications(auto& __ctx) const { return __parsed_specifications<_CharT>{ - .__chrono_ = __chrono{.__alignment_ = __alignment_, - .__locale_specific_form_ = __locale_specific_form_, - .__weekday_name_ = __weekday_name_, - .__month_name_ = __month_name_}, + .__chrono_ = + __chrono{.__alignment_ = __alignment_, + .__locale_specific_form_ = __locale_specific_form_, + .__weekday_name_ = __weekday_name_, + .__weekday_ = __weekday_, + .__day_of_year_ = __day_of_year_, + .__week_of_year_ = __week_of_year_, + .__month_name_ = __month_name_}, .__width_{__get_width(__ctx)}, .__precision_{__get_precision(__ctx)}, .__fill_{__fill_}}; @@ -325,12 +332,17 @@ bool __reserved_0_ : 1 {false}; __type __type_{__type::__default}; - // These two flags are used for formatting chrono. Since the struct has + // These flags are only used for formatting chrono. Since the struct has // padding space left it's added to this structure. bool __weekday_name_ : 1 {false}; + bool __weekday_ : 1 {false}; + + bool __day_of_year_ : 1 {false}; + bool __week_of_year_ : 1 {false}; + bool __month_name_ : 1 {false}; - uint8_t __reserved_1_ : 6 {0}; + uint8_t __reserved_1_ : 3 {0}; uint8_t __reserved_2_ : 6 {0}; // These two flags are only used internally and not part of the // __parsed_specifications. Therefore put them at the end. diff --git a/libcxx/include/chrono b/libcxx/include/chrono --- a/libcxx/include/chrono +++ b/libcxx/include/chrono @@ -385,18 +385,29 @@ constexpr bool operator==(const weekday_indexed& x, const weekday_indexed& y) noexcept; constexpr bool operator!=(const weekday_indexed& x, const weekday_indexed& y) noexcept; +template + basic_ostream& + operator<<(basic_ostream& os, const weekday_indexed& wdi); + // 25.8.8, class weekday_last // C++20 class weekday_last; constexpr bool operator==(const weekday_last& x, const weekday_last& y) noexcept; constexpr bool operator!=(const weekday_last& x, const weekday_last& y) noexcept; +template + basic_ostream& + operator<<(basic_ostream& os, const weekday_last& wdl); + // 25.8.9, class month_day // C++20 class month_day; constexpr bool operator==(const month_day& x, const month_day& y) noexcept; constexpr strong_ordering operator<=>(const month_day& x, const month_day& y) noexcept; +template + basic_ostream& + operator<<(basic_ostream& os, const month_day& md); // 25.8.10, class month_day_last // C++20 class month_day_last; @@ -404,18 +415,30 @@ constexpr bool operator==(const month_day_last& x, const month_day_last& y) noexcept; constexpr strong_ordering operator<=>(const month_day_last& x, const month_day_last& y) noexcept; +template + basic_ostream& + operator<<(basic_ostream& os, const month_day_last& mdl); + // 25.8.11, class month_weekday // C++20 class month_weekday; constexpr bool operator==(const month_weekday& x, const month_weekday& y) noexcept; constexpr bool operator!=(const month_weekday& x, const month_weekday& y) noexcept; +template + basic_ostream& + operator<<(basic_ostream& os, const month_weekday& mwd); + // 25.8.12, class month_weekday_last // C++20 class month_weekday_last; constexpr bool operator==(const month_weekday_last& x, const month_weekday_last& y) noexcept; constexpr bool operator!=(const month_weekday_last& x, const month_weekday_last& y) noexcept; +template + basic_ostream& + operator<<(basic_ostream& os, const month_weekday_last& mwdl); + // 25.8.13, class year_month // C++20 class year_month; @@ -431,6 +454,10 @@ constexpr year_month operator+(const years& dy, const year_month& ym) noexcept; constexpr year_month operator-(const year_month& ym, const years& dy) noexcept; +template + basic_ostream& + operator<<(basic_ostream& os, const year_month& ym); + // 25.8.14, class year_month_day class // C++20 year_month_day; @@ -444,6 +471,9 @@ constexpr year_month_day operator-(const year_month_day& ymd, const months& dm) noexcept; constexpr year_month_day operator-(const year_month_day& ymd, const years& dy) noexcept; +template + basic_ostream& + operator<<(basic_ostream& os, const year_month_day& ymd); // 25.8.15, class year_month_day_last // C++20 class year_month_day_last; @@ -464,6 +494,10 @@ constexpr year_month_day_last operator-(const year_month_day_last& ymdl, const years& dy) noexcept; +template + basic_ostream& + operator<<(basic_ostream& os, const year_month_day_last& ymdl); + // 25.8.16, class year_month_weekday // C++20 class year_month_weekday; @@ -485,6 +519,10 @@ constexpr year_month_weekday operator-(const year_month_weekday& ymwd, const years& dy) noexcept; +template + basic_ostream& + operator<<(basic_ostream& os, const year_month_weekday& ymwd); + // 25.8.17, class year_month_weekday_last // C++20 class year_month_weekday_last; @@ -505,6 +543,10 @@ constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const years& dy) noexcept; +template + basic_ostream& + operator<<(basic_ostream& os, const year_month_weekday_last& ymwdl); + // 25.8.18, civil calendar conventional syntax operators // C++20 constexpr year_month operator/(const year& y, const month& m) noexcept; @@ -638,6 +680,17 @@ template struct formatter; // C++20 template struct formatter; // C++20 template struct formatter; // C++20 + template struct formatter; // C++20 + template struct formatter; // C++20 + template struct formatter; // C++20 + template struct formatter; // C++20 + template struct formatter; // C++20 + template struct formatter; // C++20 + template struct formatter; // C++20 + template struct formatter; // C++20 + template struct formatter; // C++20 + template struct formatter; // C++20 + template struct formatter; // C++20 } // namespace std namespace chrono { diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv --- a/libcxx/test/libcxx/transitive_includes/cxx03.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv @@ -108,10 +108,14 @@ charconv type_traits chrono compare chrono concepts +chrono cstddef chrono cstdint +chrono cstdlib chrono ctime chrono limits chrono ratio +chrono stdexcept +chrono string_view chrono type_traits chrono version cinttypes cstdint diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv --- a/libcxx/test/libcxx/transitive_includes/cxx11.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv @@ -108,10 +108,14 @@ charconv type_traits chrono compare chrono concepts +chrono cstddef chrono cstdint +chrono cstdlib chrono ctime chrono limits chrono ratio +chrono stdexcept +chrono string_view chrono type_traits chrono version cinttypes cstdint diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv --- a/libcxx/test/libcxx/transitive_includes/cxx14.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv @@ -108,10 +108,14 @@ charconv type_traits chrono compare chrono concepts +chrono cstddef chrono cstdint +chrono cstdlib chrono ctime chrono limits chrono ratio +chrono stdexcept +chrono string_view chrono type_traits chrono version cinttypes cstdint diff --git a/libcxx/test/std/time/time.cal/time.cal.md/time.cal.md.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.md/time.cal.md.nonmembers/ostream.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.cal/time.cal.md/time.cal.md.nonmembers/ostream.pass.cpp @@ -0,0 +1,127 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// +// class month_day; + +// template +// basic_ostream& +// operator<<(basic_ostream& os, const month_day& md); + +#include +#include +#include + +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "test_macros.h" + +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static std::basic_string stream_c_locale(std::chrono::month_day md) { + std::basic_stringstream sstr; + sstr << md; + return sstr.str(); +} + +template +static std::basic_string stream_fr_FR_locale(std::chrono::month_day md) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_fr_FR_UTF_8); + sstr.imbue(locale); + sstr << md; + return sstr.str(); +} + +template +static std::basic_string stream_ja_JP_locale(std::chrono::month_day md) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_ja_JP_UTF_8); + sstr.imbue(locale); + sstr << md; + return sstr.str(); +} + +template +static void test() { + using namespace std::literals::chrono_literals; + + assert(stream_c_locale(std::chrono::month_day{std::chrono::month{0}, 0d}) == + SV("0 is not a valid month/00 is not a valid day")); + assert(stream_c_locale(std::chrono::month_day{std::chrono::month{0}, 1d}) == SV("0 is not a valid month/01")); + assert(stream_c_locale(std::chrono::month_day{std::chrono::month{1}, 255d}) == + SV("Jan/255 is not a valid day")); + assert(stream_c_locale(std::chrono::month_day{std::chrono::month{1}, 31d}) == SV("Jan/31")); + // February is considered valid with 29 days; it lacks the year information + // to do a proper validation. + assert(stream_c_locale(std::chrono::month_day{std::chrono::month{2}, 29d}) == SV("Feb/29")); + // TODO FMT there is no validation in this ostream operator. + assert(stream_c_locale(std::chrono::month_day{std::chrono::month{6}, 31d}) == SV("Jun/31")); + + assert(stream_fr_FR_locale(std::chrono::month_day{std::chrono::month{0}, 0d}) == + SV("0 is not a valid month/00 is not a valid day")); + assert(stream_fr_FR_locale(std::chrono::month_day{std::chrono::month{0}, 1d}) == + SV("0 is not a valid month/01")); +#if defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::month_day{std::chrono::month{1}, 255d}) == + SV("jan/255 is not a valid day")); + assert(stream_fr_FR_locale(std::chrono::month_day{std::chrono::month{1}, 31d}) == SV("jan/31")); + assert(stream_fr_FR_locale(std::chrono::month_day{std::chrono::month{2}, 29d}) == SV("fév/29")); + assert(stream_fr_FR_locale(std::chrono::month_day{std::chrono::month{6}, 31d}) == SV("jui/31")); +#else // defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::month_day{std::chrono::month{1}, 255d}) == + SV("janv./255 is not a valid day")); + assert(stream_fr_FR_locale(std::chrono::month_day{std::chrono::month{1}, 31d}) == SV("janv./31")); + assert(stream_fr_FR_locale(std::chrono::month_day{std::chrono::month{2}, 29d}) == SV("févr./29")); + assert(stream_fr_FR_locale(std::chrono::month_day{std::chrono::month{6}, 31d}) == SV("juin/31")); +#endif // defined(__APPLE__) + + assert(stream_ja_JP_locale(std::chrono::month_day{std::chrono::month{0}, 0d}) == + SV("0 is not a valid month/00 is not a valid day")); + assert(stream_ja_JP_locale(std::chrono::month_day{std::chrono::month{0}, 1d}) == + SV("0 is not a valid month/01")); +#if defined(__APPLE__) + assert(stream_ja_JP_locale(std::chrono::month_day{std::chrono::month{1}, 255d}) == + SV(" 1/255 is not a valid day")); + assert(stream_ja_JP_locale(std::chrono::month_day{std::chrono::month{1}, 31d}) == SV(" 1/31")); + assert(stream_ja_JP_locale(std::chrono::month_day{std::chrono::month{2}, 29d}) == SV(" 2/29")); + assert(stream_ja_JP_locale(std::chrono::month_day{std::chrono::month{6}, 31d}) == SV(" 6/31")); +#elif defined(_AIX) // defined(__APPLE__) + assert(stream_ja_JP_locale(std::chrono::month_day{std::chrono::month{1}, 255d}) == + SV("1月/255 is not a valid day")); + assert(stream_ja_JP_locale(std::chrono::month_day{std::chrono::month{1}, 31d}) == SV("1月/31")); + assert(stream_ja_JP_locale(std::chrono::month_day{std::chrono::month{2}, 29d}) == SV("2月/29")); + assert(stream_ja_JP_locale(std::chrono::month_day{std::chrono::month{6}, 31d}) == SV("6月/31")); +#else // defined(__APPLE__) + assert(stream_ja_JP_locale(std::chrono::month_day{std::chrono::month{1}, 255d}) == + SV(" 1月/255 is not a valid day")); + assert(stream_ja_JP_locale(std::chrono::month_day{std::chrono::month{1}, 31d}) == SV(" 1月/31")); + assert(stream_ja_JP_locale(std::chrono::month_day{std::chrono::month{2}, 29d}) == SV(" 2月/29")); + assert(stream_ja_JP_locale(std::chrono::month_day{std::chrono::month{6}, 31d}) == SV(" 6月/31")); +#endif // defined(__APPLE__) +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.cal/time.cal.mdlast/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.mdlast/ostream.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.cal/time.cal.mdlast/ostream.pass.cpp @@ -0,0 +1,176 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// class month_day_last; + +// template +// basic_ostream& +// operator<<(basic_ostream& os, const month_day_last& mdl); + +#include +#include +#include + +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "test_macros.h" + +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static std::basic_string stream_c_locale(std::chrono::month_day_last mdl) { + std::basic_stringstream sstr; + sstr << mdl; + return sstr.str(); +} + +template +static std::basic_string stream_fr_FR_locale(std::chrono::month_day_last mdl) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_fr_FR_UTF_8); + sstr.imbue(locale); + sstr << mdl; + return sstr.str(); +} + +template +static std::basic_string stream_ja_JP_locale(std::chrono::month_day_last mdl) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_ja_JP_UTF_8); + sstr.imbue(locale); + sstr << mdl; + return sstr.str(); +} + +template +static void test() { + assert(stream_c_locale(std::chrono::month_day_last{std::chrono::month{0}}) == + SV("0 is not a valid month/last")); + assert(stream_c_locale(std::chrono::month_day_last{std::chrono::month{1}}) == SV("Jan/last")); + assert(stream_c_locale(std::chrono::month_day_last{std::chrono::month{2}}) == SV("Feb/last")); + assert(stream_c_locale(std::chrono::month_day_last{std::chrono::month{3}}) == SV("Mar/last")); + assert(stream_c_locale(std::chrono::month_day_last{std::chrono::month{4}}) == SV("Apr/last")); + assert(stream_c_locale(std::chrono::month_day_last{std::chrono::month{5}}) == SV("May/last")); + assert(stream_c_locale(std::chrono::month_day_last{std::chrono::month{6}}) == SV("Jun/last")); + assert(stream_c_locale(std::chrono::month_day_last{std::chrono::month{7}}) == SV("Jul/last")); + assert(stream_c_locale(std::chrono::month_day_last{std::chrono::month{8}}) == SV("Aug/last")); + assert(stream_c_locale(std::chrono::month_day_last{std::chrono::month{9}}) == SV("Sep/last")); + assert(stream_c_locale(std::chrono::month_day_last{std::chrono::month{10}}) == SV("Oct/last")); + assert(stream_c_locale(std::chrono::month_day_last{std::chrono::month{11}}) == SV("Nov/last")); + assert(stream_c_locale(std::chrono::month_day_last{std::chrono::month{12}}) == SV("Dec/last")); + assert(stream_c_locale(std::chrono::month_day_last{std::chrono::month{13}}) == + SV("13 is not a valid month/last")); + assert(stream_c_locale(std::chrono::month_day_last{std::chrono::month{255}}) == + SV("255 is not a valid month/last")); + + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{0}}) == + SV("0 is not a valid month/last")); +#if defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{1}}) == SV("jan/last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{2}}) == SV("fév/last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{3}}) == SV("mar/last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{4}}) == SV("avr/last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{5}}) == SV("mai/last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{6}}) == SV("jui/last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{7}}) == SV("jul/last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{8}}) == SV("aoû/last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{9}}) == SV("sep/last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{10}}) == SV("oct/last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{11}}) == SV("nov/last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{12}}) == SV("déc/last")); +#else // defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{1}}) == SV("janv./last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{2}}) == SV("févr./last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{3}}) == SV("mars/last")); +# if defined(_WIN32) || defined(_AIX) + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{4}}) == SV("avr./last")); +# else + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{4}}) == SV("avril/last")); +# endif + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{5}}) == SV("mai/last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{6}}) == SV("juin/last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{7}}) == SV("juil./last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{8}}) == SV("août/last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{9}}) == SV("sept./last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{10}}) == SV("oct./last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{11}}) == SV("nov./last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{12}}) == SV("déc./last")); +#endif // defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{13}}) == + SV("13 is not a valid month/last")); + assert(stream_fr_FR_locale(std::chrono::month_day_last{std::chrono::month{255}}) == + SV("255 is not a valid month/last")); + + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{0}}) == + SV("0 is not a valid month/last")); +#if defined(__APPLE__) + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{1}}) == SV(" 1/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{2}}) == SV(" 2/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{3}}) == SV(" 3/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{4}}) == SV(" 4/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{5}}) == SV(" 5/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{6}}) == SV(" 6/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{7}}) == SV(" 7/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{8}}) == SV(" 8/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{9}}) == SV(" 9/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{10}}) == SV("10/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{11}}) == SV("11/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{12}}) == SV("12/last")); +#else // defined(__APPLE__) +# if defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{1}}) == SV("1月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{2}}) == SV("2月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{3}}) == SV("3月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{4}}) == SV("4月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{5}}) == SV("5月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{6}}) == SV("6月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{7}}) == SV("7月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{8}}) == SV("8月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{9}}) == SV("9月/last")); +# else // defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{1}}) == SV(" 1月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{2}}) == SV(" 2月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{3}}) == SV(" 3月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{4}}) == SV(" 4月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{5}}) == SV(" 5月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{6}}) == SV(" 6月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{7}}) == SV(" 7月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{8}}) == SV(" 8月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{9}}) == SV(" 9月/last")); +# endif // defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{10}}) == SV("10月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{11}}) == SV("11月/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{12}}) == SV("12月/last")); +#endif // defined(__APPLE__) + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{13}}) == + SV("13 is not a valid month/last")); + assert(stream_ja_JP_locale(std::chrono::month_day_last{std::chrono::month{255}}) == + SV("255 is not a valid month/last")); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.cal/time.cal.mwd/time.cal.mwd.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.mwd/time.cal.mwd.nonmembers/ostream.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.cal/time.cal.mwd/time.cal.mwd.nonmembers/ostream.pass.cpp @@ -0,0 +1,282 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// class month_weekday; + +// template +// basic_ostream& +// operator<<(basic_ostream& os, const month_weekday& mwd); + +#include +#include +#include + +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "test_macros.h" + +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static std::basic_string stream_c_locale(std::chrono::month_weekday mwd) { + std::basic_stringstream sstr; + sstr << mwd; + return sstr.str(); +} + +template +static std::basic_string stream_fr_FR_locale(std::chrono::month_weekday mwd) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_fr_FR_UTF_8); + sstr.imbue(locale); + sstr << mwd; + return sstr.str(); +} + +template +static std::basic_string stream_ja_JP_locale(std::chrono::month_weekday mwd) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_ja_JP_UTF_8); + sstr.imbue(locale); + sstr << mwd; + return sstr.str(); +} + +template +static void test() { + assert(stream_c_locale(std::chrono::month_weekday{ + std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == + SV("0 is not a valid month/Sun[1]")); + assert(stream_c_locale(std::chrono::month_weekday{ + std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}) == SV("Jan/Mon[1]")); + assert(stream_c_locale(std::chrono::month_weekday{ + std::chrono::month{2}, std::chrono::weekday_indexed{std::chrono::weekday{2}, 2}}) == SV("Feb/Tue[2]")); + assert(stream_c_locale(std::chrono::month_weekday{ + std::chrono::month{3}, std::chrono::weekday_indexed{std::chrono::weekday{3}, 3}}) == SV("Mar/Wed[3]")); + assert(stream_c_locale(std::chrono::month_weekday{ + std::chrono::month{4}, std::chrono::weekday_indexed{std::chrono::weekday{4}, 4}}) == SV("Apr/Thu[4]")); + assert(stream_c_locale(std::chrono::month_weekday{ + std::chrono::month{5}, std::chrono::weekday_indexed{std::chrono::weekday{5}, 5}}) == SV("May/Fri[5]")); + assert(stream_c_locale(std::chrono::month_weekday{ + std::chrono::month{6}, std::chrono::weekday_indexed{std::chrono::weekday{6}, 6}}) == + SV("Jun/Sat[6 is not a valid index]")); + assert(stream_c_locale(std::chrono::month_weekday{ + std::chrono::month{7}, std::chrono::weekday_indexed{std::chrono::weekday{7}, 7}}) == + SV("Jul/Sun[7 is not a valid index]")); + assert(stream_c_locale(std::chrono::month_weekday{ + std::chrono::month{8}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}) == + SV("Aug/8 is not a valid weekday[0 is not a valid index]")); + assert(stream_c_locale(std::chrono::month_weekday{ + std::chrono::month{9}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("Sep/Sun[1]")); + assert(stream_c_locale(std::chrono::month_weekday{ + std::chrono::month{10}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("Oct/Sun[1]")); + assert(stream_c_locale(std::chrono::month_weekday{ + std::chrono::month{11}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("Nov/Sun[1]")); + assert(stream_c_locale(std::chrono::month_weekday{ + std::chrono::month{12}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("Dec/Sun[1]")); + assert(stream_c_locale(std::chrono::month_weekday{ + std::chrono::month{13}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == + SV("13 is not a valid month/Sun[1]")); + assert(stream_c_locale(std::chrono::month_weekday{ + std::chrono::month{255}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}) == + SV("255 is not a valid month/8 is not a valid weekday[0 is not a valid index]")); + +#if defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == + SV("0 is not a valid month/Dim[1]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}) == SV("jan/Lun[1]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{2}, std::chrono::weekday_indexed{std::chrono::weekday{2}, 2}}) == SV("fév/Mar[2]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{3}, std::chrono::weekday_indexed{std::chrono::weekday{3}, 3}}) == SV("mar/Mer[3]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{4}, std::chrono::weekday_indexed{std::chrono::weekday{4}, 4}}) == SV("avr/Jeu[4]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{5}, std::chrono::weekday_indexed{std::chrono::weekday{5}, 5}}) == SV("mai/Ven[5]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{6}, std::chrono::weekday_indexed{std::chrono::weekday{6}, 6}}) == + SV("jui/Sam[6 is not a valid index]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{7}, std::chrono::weekday_indexed{std::chrono::weekday{7}, 7}}) == + SV("jul/Dim[7 is not a valid index]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{8}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}) == + SV("aoû/8 is not a valid weekday[0 is not a valid index]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{9}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("sep/Dim[1]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{10}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("oct/Dim[1]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{11}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("nov/Dim[1]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{12}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("déc/Dim[1]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{13}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == + SV("13 is not a valid month/Dim[1]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{255}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}) == + SV("255 is not a valid month/8 is not a valid weekday[0 is not a valid index]")); +#else // defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == + SV("0 is not a valid month/dim.[1]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}) == SV("janv./lun.[1]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{2}, std::chrono::weekday_indexed{std::chrono::weekday{2}, 2}}) == SV("févr./mar.[2]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{3}, std::chrono::weekday_indexed{std::chrono::weekday{3}, 3}}) == SV("mars/mer.[3]")); +# if defined(_WIN32) || defined(_AIX) + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{4}, std::chrono::weekday_indexed{std::chrono::weekday{4}, 4}}) == SV("avr./jeu.[4]")); +# else + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{4}, std::chrono::weekday_indexed{std::chrono::weekday{4}, 4}}) == SV("avril/jeu.[4]")); +# endif + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{5}, std::chrono::weekday_indexed{std::chrono::weekday{5}, 5}}) == SV("mai/ven.[5]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{6}, std::chrono::weekday_indexed{std::chrono::weekday{6}, 6}}) == + SV("juin/sam.[6 is not a valid index]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{7}, std::chrono::weekday_indexed{std::chrono::weekday{7}, 7}}) == + SV("juil./dim.[7 is not a valid index]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{8}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}) == + SV("août/8 is not a valid weekday[0 is not a valid index]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{9}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("sept./dim.[1]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{10}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("oct./dim.[1]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{11}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("nov./dim.[1]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{12}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("déc./dim.[1]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{13}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == + SV("13 is not a valid month/dim.[1]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday{ + std::chrono::month{255}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}) == + SV("255 is not a valid month/8 is not a valid weekday[0 is not a valid index]")); +#endif // defined(__APPLE__) + + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == + SV("0 is not a valid month/日[1]")); +#if defined(__APPLE__) + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}) == SV(" 1/月[1]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{2}, std::chrono::weekday_indexed{std::chrono::weekday{2}, 2}}) == SV(" 2/火[2]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{3}, std::chrono::weekday_indexed{std::chrono::weekday{3}, 3}}) == SV(" 3/水[3]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{4}, std::chrono::weekday_indexed{std::chrono::weekday{4}, 4}}) == SV(" 4/木[4]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{5}, std::chrono::weekday_indexed{std::chrono::weekday{5}, 5}}) == SV(" 5/金[5]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{6}, std::chrono::weekday_indexed{std::chrono::weekday{6}, 6}}) == + SV(" 6/土[6 is not a valid index]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{7}, std::chrono::weekday_indexed{std::chrono::weekday{7}, 7}}) == + SV(" 7/日[7 is not a valid index]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{8}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}) == + SV(" 8/8 is not a valid weekday[0 is not a valid index]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{9}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV(" 9/日[1]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{10}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("10/日[1]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{11}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("11/日[1]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{12}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("12/日[1]")); +#else // defined(__APPLE__) +# if defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}) == SV("1月/月[1]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{2}, std::chrono::weekday_indexed{std::chrono::weekday{2}, 2}}) == SV("2月/火[2]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{3}, std::chrono::weekday_indexed{std::chrono::weekday{3}, 3}}) == SV("3月/水[3]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{4}, std::chrono::weekday_indexed{std::chrono::weekday{4}, 4}}) == SV("4月/木[4]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{5}, std::chrono::weekday_indexed{std::chrono::weekday{5}, 5}}) == SV("5月/金[5]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{6}, std::chrono::weekday_indexed{std::chrono::weekday{6}, 6}}) == + SV("6月/土[6 is not a valid index]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{7}, std::chrono::weekday_indexed{std::chrono::weekday{7}, 7}}) == + SV("7月/日[7 is not a valid index]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{8}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}) == + SV("8月/8 is not a valid weekday[0 is not a valid index]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{9}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("9月/日[1]")); +# else // defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}) == SV(" 1月/月[1]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{2}, std::chrono::weekday_indexed{std::chrono::weekday{2}, 2}}) == SV(" 2月/火[2]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{3}, std::chrono::weekday_indexed{std::chrono::weekday{3}, 3}}) == SV(" 3月/水[3]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{4}, std::chrono::weekday_indexed{std::chrono::weekday{4}, 4}}) == SV(" 4月/木[4]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{5}, std::chrono::weekday_indexed{std::chrono::weekday{5}, 5}}) == SV(" 5月/金[5]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{6}, std::chrono::weekday_indexed{std::chrono::weekday{6}, 6}}) == + SV(" 6月/土[6 is not a valid index]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{7}, std::chrono::weekday_indexed{std::chrono::weekday{7}, 7}}) == + SV(" 7月/日[7 is not a valid index]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{8}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}) == + SV(" 8月/8 is not a valid weekday[0 is not a valid index]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{9}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV(" 9月/日[1]")); +# endif // defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{10}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("10月/日[1]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{11}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("11月/日[1]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{12}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == SV("12月/日[1]")); +#endif // defined(__APPLE__) + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{13}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}) == + SV("13 is not a valid month/日[1]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday{ + std::chrono::month{255}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}) == + SV("255 is not a valid month/8 is not a valid weekday[0 is not a valid index]")); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.cal/time.cal.mwdlast/time.cal.mwdlast.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.mwdlast/time.cal.mwdlast.nonmembers/ostream.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.cal/time.cal.mwdlast/time.cal.mwdlast.nonmembers/ostream.pass.cpp @@ -0,0 +1,273 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// class month_weekday_last; + +// template +// basic_ostream& +// operator<<(basic_ostream& os, const month_weekday_last& mwdl); + +#include +#include +#include + +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "test_macros.h" + +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static std::basic_string stream_c_locale(std::chrono::month_weekday_last mwdl) { + std::basic_stringstream sstr; + sstr << mwdl; + return sstr.str(); +} + +template +static std::basic_string stream_fr_FR_locale(std::chrono::month_weekday_last mwdl) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_fr_FR_UTF_8); + sstr.imbue(locale); + sstr << mwdl; + return sstr.str(); +} + +template +static std::basic_string stream_ja_JP_locale(std::chrono::month_weekday_last mwdl) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_ja_JP_UTF_8); + sstr.imbue(locale); + sstr << mwdl; + return sstr.str(); +} + +template +static void test() { + assert(stream_c_locale(std::chrono::month_weekday_last{ + std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("0 is not a valid month/Sun[last]")); + assert(stream_c_locale(std::chrono::month_weekday_last{ + std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("Jan/Sun[last]")); + assert(stream_c_locale(std::chrono::month_weekday_last{ + std::chrono::month{2}, std::chrono::weekday_last{std::chrono::weekday{1}}}) == SV("Feb/Mon[last]")); + assert(stream_c_locale(std::chrono::month_weekday_last{ + std::chrono::month{3}, std::chrono::weekday_last{std::chrono::weekday{2}}}) == SV("Mar/Tue[last]")); + assert(stream_c_locale(std::chrono::month_weekday_last{ + std::chrono::month{4}, std::chrono::weekday_last{std::chrono::weekday{3}}}) == SV("Apr/Wed[last]")); + assert(stream_c_locale(std::chrono::month_weekday_last{ + std::chrono::month{5}, std::chrono::weekday_last{std::chrono::weekday{4}}}) == SV("May/Thu[last]")); + assert(stream_c_locale(std::chrono::month_weekday_last{ + std::chrono::month{6}, std::chrono::weekday_last{std::chrono::weekday{5}}}) == SV("Jun/Fri[last]")); + assert(stream_c_locale(std::chrono::month_weekday_last{ + std::chrono::month{7}, std::chrono::weekday_last{std::chrono::weekday{6}}}) == SV("Jul/Sat[last]")); + assert(stream_c_locale(std::chrono::month_weekday_last{ + std::chrono::month{8}, std::chrono::weekday_last{std::chrono::weekday{7}}}) == SV("Aug/Sun[last]")); + assert(stream_c_locale(std::chrono::month_weekday_last{ + std::chrono::month{9}, std::chrono::weekday_last{std::chrono::weekday{8}}}) == + SV("Sep/8 is not a valid weekday[last]")); + assert(stream_c_locale(std::chrono::month_weekday_last{ + std::chrono::month{10}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("Oct/Sun[last]")); + assert(stream_c_locale(std::chrono::month_weekday_last{ + std::chrono::month{11}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("Nov/Sun[last]")); + assert(stream_c_locale(std::chrono::month_weekday_last{ + std::chrono::month{12}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("Dec/Sun[last]")); + assert(stream_c_locale(std::chrono::month_weekday_last{ + std::chrono::month{13}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("13 is not a valid month/Sun[last]")); + assert(stream_c_locale(std::chrono::month_weekday_last{ + std::chrono::month{255}, std::chrono::weekday_last{std::chrono::weekday{8}}}) == + SV("255 is not a valid month/8 is not a valid weekday[last]")); + +#if defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("0 is not a valid month/Dim[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("jan/Dim[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{2}, std::chrono::weekday_last{std::chrono::weekday{1}}}) == SV("fév/Lun[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{3}, std::chrono::weekday_last{std::chrono::weekday{2}}}) == SV("mar/Mar[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{4}, std::chrono::weekday_last{std::chrono::weekday{3}}}) == SV("avr/Mer[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{5}, std::chrono::weekday_last{std::chrono::weekday{4}}}) == SV("mai/Jeu[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{6}, std::chrono::weekday_last{std::chrono::weekday{5}}}) == SV("jui/Ven[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{7}, std::chrono::weekday_last{std::chrono::weekday{6}}}) == SV("jul/Sam[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{8}, std::chrono::weekday_last{std::chrono::weekday{7}}}) == SV("aoû/Dim[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{9}, std::chrono::weekday_last{std::chrono::weekday{8}}}) == + SV("sep/8 is not a valid weekday[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{10}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("oct/Dim[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{11}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("nov/Dim[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{12}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("déc/Dim[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{13}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("13 is not a valid month/Dim[last]")); +#else // defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("0 is not a valid month/dim.[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("janv./dim.[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{2}, std::chrono::weekday_last{std::chrono::weekday{1}}}) == SV("févr./lun.[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{3}, std::chrono::weekday_last{std::chrono::weekday{2}}}) == SV("mars/mar.[last]")); +# if defined(_WIN32) || defined(_AIX) + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{4}, std::chrono::weekday_last{std::chrono::weekday{3}}}) == SV("avr./mer.[last]")); +# else // defined(_WIN32) || defined(_AIX) + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{4}, std::chrono::weekday_last{std::chrono::weekday{3}}}) == SV("avril/mer.[last]")); +# endif // defined(_WIN32) || defined(_AIX) + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{5}, std::chrono::weekday_last{std::chrono::weekday{4}}}) == SV("mai/jeu.[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{6}, std::chrono::weekday_last{std::chrono::weekday{5}}}) == SV("juin/ven.[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{7}, std::chrono::weekday_last{std::chrono::weekday{6}}}) == SV("juil./sam.[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{8}, std::chrono::weekday_last{std::chrono::weekday{7}}}) == SV("août/dim.[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{9}, std::chrono::weekday_last{std::chrono::weekday{8}}}) == + SV("sept./8 is not a valid weekday[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{10}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("oct./dim.[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{11}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("nov./dim.[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{12}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("déc./dim.[last]")); + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{13}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("13 is not a valid month/dim.[last]")); +#endif // defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::month_weekday_last{ + std::chrono::month{255}, std::chrono::weekday_last{std::chrono::weekday{8}}}) == + SV("255 is not a valid month/8 is not a valid weekday[last]")); + +#if defined(__APPLE__) + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("0 is not a valid month/日[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV(" 1/日[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{2}, std::chrono::weekday_last{std::chrono::weekday{1}}}) == SV(" 2/月[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{3}, std::chrono::weekday_last{std::chrono::weekday{2}}}) == SV(" 3/火[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{4}, std::chrono::weekday_last{std::chrono::weekday{3}}}) == SV(" 4/水[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{5}, std::chrono::weekday_last{std::chrono::weekday{4}}}) == SV(" 5/木[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{6}, std::chrono::weekday_last{std::chrono::weekday{5}}}) == SV(" 6/金[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{7}, std::chrono::weekday_last{std::chrono::weekday{6}}}) == SV(" 7/土[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{8}, std::chrono::weekday_last{std::chrono::weekday{7}}}) == SV(" 8/日[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{9}, std::chrono::weekday_last{std::chrono::weekday{8}}}) == + SV(" 9/8 is not a valid weekday[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{10}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("10/日[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{11}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("11/日[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{12}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("12/日[last]")); +#else // defined(__APPLE__) +# if defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("0 is not a valid month/日[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("1月/日[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{2}, std::chrono::weekday_last{std::chrono::weekday{1}}}) == SV("2月/月[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{3}, std::chrono::weekday_last{std::chrono::weekday{2}}}) == SV("3月/火[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{4}, std::chrono::weekday_last{std::chrono::weekday{3}}}) == SV("4月/水[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{5}, std::chrono::weekday_last{std::chrono::weekday{4}}}) == SV("5月/木[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{6}, std::chrono::weekday_last{std::chrono::weekday{5}}}) == SV("6月/金[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{7}, std::chrono::weekday_last{std::chrono::weekday{6}}}) == SV("7月/土[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{8}, std::chrono::weekday_last{std::chrono::weekday{7}}}) == SV("8月/日[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{9}, std::chrono::weekday_last{std::chrono::weekday{8}}}) == + SV("9月/8 is not a valid weekday[last]")); +# else // defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("0 is not a valid month/日[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV(" 1月/日[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{2}, std::chrono::weekday_last{std::chrono::weekday{1}}}) == SV(" 2月/月[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{3}, std::chrono::weekday_last{std::chrono::weekday{2}}}) == SV(" 3月/火[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{4}, std::chrono::weekday_last{std::chrono::weekday{3}}}) == SV(" 4月/水[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{5}, std::chrono::weekday_last{std::chrono::weekday{4}}}) == SV(" 5月/木[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{6}, std::chrono::weekday_last{std::chrono::weekday{5}}}) == SV(" 6月/金[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{7}, std::chrono::weekday_last{std::chrono::weekday{6}}}) == SV(" 7月/土[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{8}, std::chrono::weekday_last{std::chrono::weekday{7}}}) == SV(" 8月/日[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{9}, std::chrono::weekday_last{std::chrono::weekday{8}}}) == + SV(" 9月/8 is not a valid weekday[last]")); +# endif // defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{10}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("10月/日[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{11}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("11月/日[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{12}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == SV("12月/日[last]")); +#endif // defined(__APPLE__) + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{13}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("13 is not a valid month/日[last]")); + assert(stream_ja_JP_locale(std::chrono::month_weekday_last{ + std::chrono::month{255}, std::chrono::weekday_last{std::chrono::weekday{8}}}) == + SV("255 is not a valid month/8 is not a valid weekday[last]")); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.cal/time.cal.wdidx/time.cal.wdidx.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.wdidx/time.cal.wdidx.nonmembers/ostream.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.cal/time.cal.wdidx/time.cal.wdidx.nonmembers/ostream.pass.cpp @@ -0,0 +1,133 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// +// class weekday_indexed; + +// template +// basic_ostream& +// operator<<(basic_ostream& os, const weekday_indexed& wdi); + +#include +#include +#include + +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "test_macros.h" + +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static std::basic_string stream_c_locale(std::chrono::weekday_indexed wdi) { + std::basic_stringstream sstr; + sstr << wdi; + return sstr.str(); +} + +template +static std::basic_string stream_fr_FR_locale(std::chrono::weekday_indexed wdi) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_fr_FR_UTF_8); + sstr.imbue(locale); + sstr << wdi; + return sstr.str(); +} + +template +static std::basic_string stream_ja_JP_locale(std::chrono::weekday_indexed wdi) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_ja_JP_UTF_8); + sstr.imbue(locale); + sstr << wdi; + return sstr.str(); +} + +template +static void test() { + assert(stream_c_locale(std::chrono::weekday_indexed{std::chrono::weekday(0), 1}) == SV("Sun[1]")); + assert(stream_c_locale(std::chrono::weekday_indexed{std::chrono::weekday(1), 2}) == SV("Mon[2]")); + assert(stream_c_locale(std::chrono::weekday_indexed{std::chrono::weekday(2), 3}) == SV("Tue[3]")); + assert(stream_c_locale(std::chrono::weekday_indexed{std::chrono::weekday(3), 4}) == SV("Wed[4]")); + assert(stream_c_locale(std::chrono::weekday_indexed{std::chrono::weekday(4), 5}) == SV("Thu[5]")); + assert(stream_c_locale(std::chrono::weekday_indexed{std::chrono::weekday(5), 0}) == + SV("Fri[0 is not a valid index]")); + assert(stream_c_locale(std::chrono::weekday_indexed{std::chrono::weekday(6), 6}) == + SV("Sat[6 is not a valid index]")); + assert(stream_c_locale(std::chrono::weekday_indexed{std::chrono::weekday(7), 7}) == + SV("Sun[7 is not a valid index]")); + assert(stream_c_locale(std::chrono::weekday_indexed{std::chrono::weekday(8), 0}) == + SV("8 is not a valid weekday[0 is not a valid index]")); + assert(stream_c_locale(std::chrono::weekday_indexed{std::chrono::weekday(255), 1}) == + SV("255 is not a valid weekday[1]")); + +#if defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(0), 1}) == SV("Dim[1]")); + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(1), 2}) == SV("Lun[2]")); + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(2), 3}) == SV("Mar[3]")); + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(3), 4}) == SV("Mer[4]")); + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(4), 5}) == SV("Jeu[5]")); + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(5), 0}) == + SV("Ven[0 is not a valid index]")); + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(6), 6}) == + SV("Sam[6 is not a valid index]")); + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(7), 7}) == + SV("Dim[7 is not a valid index]")); + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(255), 1}) == + SV("255 is not a valid weekday[1]")); +#else // defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(0), 1}) == SV("dim.[1]")); + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(1), 2}) == SV("lun.[2]")); + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(2), 3}) == SV("mar.[3]")); + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(3), 4}) == SV("mer.[4]")); + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(4), 5}) == SV("jeu.[5]")); + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(5), 0}) == + SV("ven.[0 is not a valid index]")); + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(6), 6}) == + SV("sam.[6 is not a valid index]")); + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(7), 7}) == + SV("dim.[7 is not a valid index]")); +#endif // defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(8), 0}) == + SV("8 is not a valid weekday[0 is not a valid index]")); + assert(stream_fr_FR_locale(std::chrono::weekday_indexed{std::chrono::weekday(255), 1}) == + SV("255 is not a valid weekday[1]")); + + assert(stream_ja_JP_locale(std::chrono::weekday_indexed{std::chrono::weekday(0), 1}) == SV("日[1]")); + assert(stream_ja_JP_locale(std::chrono::weekday_indexed{std::chrono::weekday(1), 2}) == SV("月[2]")); + assert(stream_ja_JP_locale(std::chrono::weekday_indexed{std::chrono::weekday(2), 3}) == SV("火[3]")); + assert(stream_ja_JP_locale(std::chrono::weekday_indexed{std::chrono::weekday(3), 4}) == SV("水[4]")); + assert(stream_ja_JP_locale(std::chrono::weekday_indexed{std::chrono::weekday(4), 5}) == SV("木[5]")); + assert(stream_ja_JP_locale(std::chrono::weekday_indexed{std::chrono::weekday(5), 0}) == + SV("金[0 is not a valid index]")); + assert(stream_ja_JP_locale(std::chrono::weekday_indexed{std::chrono::weekday(6), 6}) == + SV("土[6 is not a valid index]")); + assert(stream_ja_JP_locale(std::chrono::weekday_indexed{std::chrono::weekday(7), 7}) == + SV("日[7 is not a valid index]")); + assert(stream_ja_JP_locale(std::chrono::weekday_indexed{std::chrono::weekday(8), 0}) == + SV("8 is not a valid weekday[0 is not a valid index]")); + assert(stream_ja_JP_locale(std::chrono::weekday_indexed{std::chrono::weekday(255), 1}) == + SV("255 is not a valid weekday[1]")); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.cal/time.cal.wdlast/time.cal.wdlast.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.wdlast/time.cal.wdlast.nonmembers/ostream.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.cal/time.cal.wdlast/time.cal.wdlast.nonmembers/ostream.pass.cpp @@ -0,0 +1,119 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// +// class weekday_last; + +// template +// basic_ostream& +// operator<<(basic_ostream& os, const weekday_last& wdl); + +#include +#include +#include + +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "test_macros.h" + +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static std::basic_string stream_c_locale(std::chrono::weekday_last wdl) { + std::basic_stringstream sstr; + sstr << wdl; + return sstr.str(); +} + +template +static std::basic_string stream_fr_FR_locale(std::chrono::weekday_last wdl) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_fr_FR_UTF_8); + sstr.imbue(locale); + sstr << wdl; + return sstr.str(); +} + +template +static std::basic_string stream_ja_JP_locale(std::chrono::weekday_last wdl) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_ja_JP_UTF_8); + sstr.imbue(locale); + sstr << wdl; + return sstr.str(); +} + +template +static void test() { + assert(stream_c_locale(std::chrono::weekday_last{std::chrono::weekday{0}}) == SV("Sun[last]")); + assert(stream_c_locale(std::chrono::weekday_last{std::chrono::weekday{1}}) == SV("Mon[last]")); + assert(stream_c_locale(std::chrono::weekday_last{std::chrono::weekday{2}}) == SV("Tue[last]")); + assert(stream_c_locale(std::chrono::weekday_last{std::chrono::weekday{3}}) == SV("Wed[last]")); + assert(stream_c_locale(std::chrono::weekday_last{std::chrono::weekday{4}}) == SV("Thu[last]")); + assert(stream_c_locale(std::chrono::weekday_last{std::chrono::weekday{5}}) == SV("Fri[last]")); + assert(stream_c_locale(std::chrono::weekday_last{std::chrono::weekday{6}}) == SV("Sat[last]")); + assert(stream_c_locale(std::chrono::weekday_last{std::chrono::weekday{7}}) == SV("Sun[last]")); + assert(stream_c_locale(std::chrono::weekday_last{std::chrono::weekday{8}}) == + SV("8 is not a valid weekday[last]")); + assert(stream_c_locale(std::chrono::weekday_last{std::chrono::weekday{255}}) == + SV("255 is not a valid weekday[last]")); + +#if defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{0}}) == SV("Dim[last]")); + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{1}}) == SV("Lun[last]")); + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{2}}) == SV("Mar[last]")); + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{3}}) == SV("Mer[last]")); + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{4}}) == SV("Jeu[last]")); + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{5}}) == SV("Ven[last]")); + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{6}}) == SV("Sam[last]")); + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{7}}) == SV("Dim[last]")); +#else // defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{0}}) == SV("dim.[last]")); + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{1}}) == SV("lun.[last]")); + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{2}}) == SV("mar.[last]")); + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{3}}) == SV("mer.[last]")); + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{4}}) == SV("jeu.[last]")); + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{5}}) == SV("ven.[last]")); + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{6}}) == SV("sam.[last]")); + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{7}}) == SV("dim.[last]")); +#endif // defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{8}}) == + SV("8 is not a valid weekday[last]")); + assert(stream_fr_FR_locale(std::chrono::weekday_last{std::chrono::weekday{255}}) == + SV("255 is not a valid weekday[last]")); + + assert(stream_ja_JP_locale(std::chrono::weekday_last{std::chrono::weekday{0}}) == SV("日[last]")); + assert(stream_ja_JP_locale(std::chrono::weekday_last{std::chrono::weekday{1}}) == SV("月[last]")); + assert(stream_ja_JP_locale(std::chrono::weekday_last{std::chrono::weekday{2}}) == SV("火[last]")); + assert(stream_ja_JP_locale(std::chrono::weekday_last{std::chrono::weekday{3}}) == SV("水[last]")); + assert(stream_ja_JP_locale(std::chrono::weekday_last{std::chrono::weekday{4}}) == SV("木[last]")); + assert(stream_ja_JP_locale(std::chrono::weekday_last{std::chrono::weekday{5}}) == SV("金[last]")); + assert(stream_ja_JP_locale(std::chrono::weekday_last{std::chrono::weekday{6}}) == SV("土[last]")); + assert(stream_ja_JP_locale(std::chrono::weekday_last{std::chrono::weekday{7}}) == SV("日[last]")); + assert(stream_ja_JP_locale(std::chrono::weekday_last{std::chrono::weekday{8}}) == + SV("8 is not a valid weekday[last]")); + assert(stream_ja_JP_locale(std::chrono::weekday_last{std::chrono::weekday{255}}) == + SV("255 is not a valid weekday[last]")); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/ostream.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/ostream.pass.cpp @@ -0,0 +1,246 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// class year_month; + +// template +// basic_ostream& +// operator<<(basic_ostream& os, const year_month& ym); + +#include +#include +#include + +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "test_macros.h" + +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static std::basic_string stream_c_locale(std::chrono::year_month ym) { + std::basic_stringstream sstr; + sstr << ym; + return sstr.str(); +} + +template +static std::basic_string stream_fr_FR_locale(std::chrono::year_month ym) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_fr_FR_UTF_8); + sstr.imbue(locale); + sstr << ym; + return sstr.str(); +} + +template +static std::basic_string stream_ja_JP_locale(std::chrono::year_month ym) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_ja_JP_UTF_8); + sstr.imbue(locale); + sstr << ym; + return sstr.str(); +} + +template +static void test() { + assert(stream_c_locale(std::chrono::year_month{std::chrono::year{-32'768}, std::chrono::month{0}}) == + SV("-32768 is not a valid year/0 is not a valid month")); + assert(stream_c_locale(std::chrono::year_month{std::chrono::year{-32'768}, std::chrono::month{1}}) == + SV("-32768 is not a valid year/Jan")); + assert(stream_c_locale(std::chrono::year_month{std::chrono::year{-32'767}, std::chrono::month{2}}) == + SV("-32767/Feb")); + assert(stream_c_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{3}}) == + SV("0000/Mar")); + assert(stream_c_locale(std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{4}}) == + SV("1970/Apr")); + assert(stream_c_locale(std::chrono::year_month{std::chrono::year{32'767}, std::chrono::month{5}}) == + SV("32767/May")); + assert(stream_c_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{6}}) == + SV("0000/Jun")); + assert(stream_c_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{7}}) == + SV("0000/Jul")); + assert(stream_c_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{8}}) == + SV("0000/Aug")); + assert(stream_c_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{9}}) == + SV("0000/Sep")); + assert(stream_c_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{10}}) == + SV("0000/Oct")); + assert(stream_c_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{11}}) == + SV("0000/Nov")); + assert(stream_c_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{12}}) == + SV("0000/Dec")); + assert(stream_c_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{13}}) == + SV("0000/13 is not a valid month")); + assert(stream_c_locale(std::chrono::year_month{std::chrono::year{-32'768}, std::chrono::month{255}}) == + SV("-32768 is not a valid year/255 is not a valid month")); + + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{-32'768}, std::chrono::month{0}}) == + SV("-32768 is not a valid year/0 is not a valid month")); +#if defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{-32'768}, std::chrono::month{1}}) == + SV("-32768 is not a valid year/jan")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{-32'767}, std::chrono::month{2}}) == + SV("-32767/fév")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{3}}) == + SV("0000/mar")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{4}}) == + SV("1970/avr")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{32'767}, std::chrono::month{5}}) == + SV("32767/mai")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{6}}) == + SV("0000/jui")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{7}}) == + SV("0000/jul")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{8}}) == + SV("0000/aoû")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{9}}) == + SV("0000/sep")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{10}}) == + SV("0000/oct")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{11}}) == + SV("0000/nov")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{12}}) == + SV("0000/déc")); +#else // defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{-32'768}, std::chrono::month{1}}) == + SV("-32768 is not a valid year/janv.")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{-32'767}, std::chrono::month{2}}) == + SV("-32767/févr.")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{3}}) == + SV("0000/mars")); +# if defined(_WIN32) || defined(_AIX) + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{4}}) == + SV("1970/avr.")); +# else // defined(_WIN32) || defined(_AIX) + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{4}}) == + SV("1970/avril")); +# endif // defined(_WIN32) || defined(_AIX) + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{32'767}, std::chrono::month{5}}) == + SV("32767/mai")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{6}}) == + SV("0000/juin")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{7}}) == + SV("0000/juil.")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{8}}) == + SV("0000/août")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{9}}) == + SV("0000/sept.")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{10}}) == + SV("0000/oct.")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{11}}) == + SV("0000/nov.")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{12}}) == + SV("0000/déc.")); +#endif // defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{13}}) == + SV("0000/13 is not a valid month")); + assert(stream_fr_FR_locale(std::chrono::year_month{std::chrono::year{-32'768}, std::chrono::month{255}}) == + SV("-32768 is not a valid year/255 is not a valid month")); + + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{-32'768}, std::chrono::month{0}}) == + SV("-32768 is not a valid year/0 is not a valid month")); +#if defined(__APPLE__) + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{-32'768}, std::chrono::month{1}}) == + SV("-32768 is not a valid year/ 1")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{-32'767}, std::chrono::month{2}}) == + SV("-32767/ 2")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{3}}) == + SV("0000/ 3")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{4}}) == + SV("1970/ 4")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{32'767}, std::chrono::month{5}}) == + SV("32767/ 5")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{6}}) == + SV("0000/ 6")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{7}}) == + SV("0000/ 7")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{8}}) == + SV("0000/ 8")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{9}}) == + SV("0000/ 9")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{10}}) == + SV("0000/10")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{11}}) == + SV("0000/11")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{12}}) == + SV("0000/12")); +#else // defined(__APPLE__) +# if defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{-32'768}, std::chrono::month{1}}) == + SV("-32768 is not a valid year/1月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{-32'767}, std::chrono::month{2}}) == + SV("-32767/2月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{3}}) == + SV("0000/3月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{4}}) == + SV("1970/4月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{32'767}, std::chrono::month{5}}) == + SV("32767/5月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{6}}) == + SV("0000/6月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{7}}) == + SV("0000/7月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{8}}) == + SV("0000/8月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{9}}) == + SV("0000/9月")); +# else // defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{-32'768}, std::chrono::month{1}}) == + SV("-32768 is not a valid year/ 1月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{-32'767}, std::chrono::month{2}}) == + SV("-32767/ 2月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{3}}) == + SV("0000/ 3月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{4}}) == + SV("1970/ 4月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{32'767}, std::chrono::month{5}}) == + SV("32767/ 5月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{6}}) == + SV("0000/ 6月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{7}}) == + SV("0000/ 7月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{8}}) == + SV("0000/ 8月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{9}}) == + SV("0000/ 9月")); +# endif // defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{10}}) == + SV("0000/10月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{11}}) == + SV("0000/11月")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{12}}) == + SV("0000/12月")); +#endif // defined(__APPLE__) + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{0}, std::chrono::month{13}}) == + SV("0000/13 is not a valid month")); + assert(stream_ja_JP_locale(std::chrono::year_month{std::chrono::year{-32'768}, std::chrono::month{255}}) == + SV("-32768 is not a valid year/255 is not a valid month")); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/ostream.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/ostream.pass.cpp @@ -0,0 +1,147 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// class year_month_day; + +// template +// basic_ostream& +// operator<<(basic_ostream& os, const year_month_day& ymd); + +#include +#include +#include + +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "test_macros.h" + +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static std::basic_string stream_c_locale(std::chrono::year_month_day ymd) { + std::basic_stringstream sstr; + sstr << ymd; + return sstr.str(); +} + +template +static std::basic_string stream_fr_FR_locale(std::chrono::year_month_day ymd) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_fr_FR_UTF_8); + sstr.imbue(locale); + sstr << ymd; + return sstr.str(); +} + +template +static std::basic_string stream_ja_JP_locale(std::chrono::year_month_day ymd) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_ja_JP_UTF_8); + sstr.imbue(locale); + sstr << ymd; + return sstr.str(); +} + +template +static void test() { + assert(stream_c_locale( + std::chrono::year_month_day{std::chrono::year{-32'768}, std::chrono::month{1}, std::chrono::day{1}}) == + SV("-32768-01-01 is not a valid date")); + assert(stream_c_locale( + std::chrono::year_month_day{std::chrono::year{-32'767}, std::chrono::month{0}, std::chrono::day{1}}) == + SV("-32767-00-01 is not a valid date")); + assert(stream_c_locale( + std::chrono::year_month_day{std::chrono::year{-32'767}, std::chrono::month{1}, std::chrono::day{0}}) == + SV("-32767-01-00 is not a valid date")); + assert(stream_c_locale(std::chrono::year_month_day{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{1}}) == SV("1970-01-01")); + assert(stream_c_locale( + std::chrono::year_month_day{std::chrono::year{1999}, std::chrono::month{2}, std::chrono::day{29}}) == + SV("1999-02-29 is not a valid date")); + assert(stream_c_locale(std::chrono::year_month_day{ + std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}) == SV("2000-02-29")); + +#if defined(_AIX) + // TODO FMT Fix this AIX bug. + assert(stream_c_locale(std::chrono::year_month_day{ + std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}) == SV("2008-12-03")); +#else // defined(_AIX) + assert(stream_c_locale(std::chrono::year_month_day{ + std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}) == SV("32767-12-31")); +#endif // defined(_AIX) + + assert(stream_fr_FR_locale( + std::chrono::year_month_day{std::chrono::year{-32'768}, std::chrono::month{1}, std::chrono::day{1}}) == + SV("-32768-01-01 is not a valid date")); + assert(stream_fr_FR_locale( + std::chrono::year_month_day{std::chrono::year{-32'767}, std::chrono::month{0}, std::chrono::day{1}}) == + SV("-32767-00-01 is not a valid date")); + assert(stream_fr_FR_locale( + std::chrono::year_month_day{std::chrono::year{-32'767}, std::chrono::month{1}, std::chrono::day{0}}) == + SV("-32767-01-00 is not a valid date")); + assert(stream_fr_FR_locale(std::chrono::year_month_day{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{1}}) == SV("1970-01-01")); + assert(stream_fr_FR_locale( + std::chrono::year_month_day{std::chrono::year{1999}, std::chrono::month{2}, std::chrono::day{29}}) == + SV("1999-02-29 is not a valid date")); + assert(stream_fr_FR_locale(std::chrono::year_month_day{ + std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}) == SV("2000-02-29")); +#if defined(_AIX) + assert(stream_fr_FR_locale(std::chrono::year_month_day{ + std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}) == SV("2008-12-03")); +#else // defined(_AIX) + assert(stream_fr_FR_locale(std::chrono::year_month_day{ + std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}) == SV("32767-12-31")); +#endif // defined(_AIX) + + assert(stream_ja_JP_locale( + std::chrono::year_month_day{std::chrono::year{-32'768}, std::chrono::month{1}, std::chrono::day{1}}) == + SV("-32768-01-01 is not a valid date")); + assert(stream_ja_JP_locale( + std::chrono::year_month_day{std::chrono::year{-32'767}, std::chrono::month{0}, std::chrono::day{1}}) == + SV("-32767-00-01 is not a valid date")); + assert(stream_ja_JP_locale( + std::chrono::year_month_day{std::chrono::year{-32'767}, std::chrono::month{1}, std::chrono::day{0}}) == + SV("-32767-01-00 is not a valid date")); + assert(stream_ja_JP_locale(std::chrono::year_month_day{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{1}}) == SV("1970-01-01")); + assert(stream_ja_JP_locale( + std::chrono::year_month_day{std::chrono::year{1999}, std::chrono::month{2}, std::chrono::day{29}}) == + SV("1999-02-29 is not a valid date")); + assert(stream_ja_JP_locale(std::chrono::year_month_day{ + std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}) == SV("2000-02-29")); +#if defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::year_month_day{ + std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}) == SV("2008-12-03")); +#else // defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::year_month_day{ + std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}) == SV("32767-12-31")); +#endif // defined(_AIX) +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/ostream.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/ostream.pass.cpp @@ -0,0 +1,263 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// class year_month_day_last; + +// template +// basic_ostream& +// operator<<(basic_ostream& os, const year_month_day_last& ymdl); + +#include +#include +#include + +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "test_macros.h" + +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static std::basic_string stream_c_locale(std::chrono::year_month_day_last ymdl) { + std::basic_stringstream sstr; + sstr << ymdl; + return sstr.str(); +} + +template +static std::basic_string stream_fr_FR_locale(std::chrono::year_month_day_last ymdl) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_fr_FR_UTF_8); + sstr.imbue(locale); + sstr << ymdl; + return sstr.str(); +} + +template +static std::basic_string stream_ja_JP_locale(std::chrono::year_month_day_last ymdl) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_ja_JP_UTF_8); + sstr.imbue(locale); + sstr << ymdl; + return sstr.str(); +} + +template +static void test() { + assert(stream_c_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{0}}}) == + SV("0000/0 is not a valid month/last")); + assert(stream_c_locale(std::chrono::year_month_day_last{ + std::chrono::year{-32'768}, std::chrono::month_day_last{std::chrono::month{1}}}) == + SV("-32768 is not a valid year/Jan/last")); + assert(stream_c_locale(std::chrono::year_month_day_last{ + std::chrono::year{-32'767}, std::chrono::month_day_last{std::chrono::month{2}}}) == SV("-32767/Feb/last")); + assert(stream_c_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{3}}}) == SV("0000/Mar/last")); + assert(stream_c_locale(std::chrono::year_month_day_last{ + std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{4}}}) == SV("1970/Apr/last")); + assert(stream_c_locale(std::chrono::year_month_day_last{ + std::chrono::year{32'767}, std::chrono::month_day_last{std::chrono::month{5}}}) == SV("32767/May/last")); + assert(stream_c_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{6}}}) == SV("0000/Jun/last")); + assert(stream_c_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{7}}}) == SV("0000/Jul/last")); + assert(stream_c_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{8}}}) == SV("0000/Aug/last")); + assert(stream_c_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{9}}}) == SV("0000/Sep/last")); + assert(stream_c_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{10}}}) == SV("0000/Oct/last")); + assert(stream_c_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{11}}}) == SV("0000/Nov/last")); + assert(stream_c_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{12}}}) == SV("0000/Dec/last")); + assert(stream_c_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{13}}}) == + SV("0000/13 is not a valid month/last")); + assert(stream_c_locale(std::chrono::year_month_day_last{ + std::chrono::year{-32'768}, std::chrono::month_day_last{std::chrono::month{255}}}) == + SV("-32768 is not a valid year/255 is not a valid month/last")); + + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{0}}}) == + SV("0000/0 is not a valid month/last")); +#if defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{-32'768}, std::chrono::month_day_last{std::chrono::month{1}}}) == + SV("-32768 is not a valid year/jan/last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{-32'767}, std::chrono::month_day_last{std::chrono::month{2}}}) == SV("-32767/fév/last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{3}}}) == SV("0000/mar/last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{4}}}) == SV("1970/avr/last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{32'767}, std::chrono::month_day_last{std::chrono::month{5}}}) == SV("32767/mai/last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{6}}}) == SV("0000/jui/last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{7}}}) == SV("0000/jul/last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{8}}}) == SV("0000/aoû/last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{9}}}) == SV("0000/sep/last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{10}}}) == SV("0000/oct/last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{11}}}) == SV("0000/nov/last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{12}}}) == SV("0000/déc/last")); +#else // defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{-32'768}, std::chrono::month_day_last{std::chrono::month{1}}}) == + SV("-32768 is not a valid year/janv./last")); + assert( + stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{-32'767}, std::chrono::month_day_last{std::chrono::month{2}}}) == SV("-32767/févr./last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{3}}}) == SV("0000/mars/last")); +# if defined(_WIN32) || defined(_AIX) + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{4}}}) == SV("1970/avr./last")); +# else // defined(_WIN32) || defined(_AIX) + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{4}}}) == SV("1970/avril/last")); +# endif // defined(_WIN32) || defined(_AIX) + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{32'767}, std::chrono::month_day_last{std::chrono::month{5}}}) == SV("32767/mai/last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{6}}}) == SV("0000/juin/last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{7}}}) == SV("0000/juil./last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{8}}}) == SV("0000/août/last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{9}}}) == SV("0000/sept./last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{10}}}) == SV("0000/oct./last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{11}}}) == SV("0000/nov./last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{12}}}) == SV("0000/déc./last")); +#endif // defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{13}}}) == + SV("0000/13 is not a valid month/last")); + assert(stream_fr_FR_locale(std::chrono::year_month_day_last{ + std::chrono::year{-32'768}, std::chrono::month_day_last{std::chrono::month{255}}}) == + SV("-32768 is not a valid year/255 is not a valid month/last")); + + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{0}}}) == + SV("0000/0 is not a valid month/last")); +#if defined(__APPLE__) + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{-32'768}, std::chrono::month_day_last{std::chrono::month{1}}}) == + SV("-32768 is not a valid year/ 1/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{-32'767}, std::chrono::month_day_last{std::chrono::month{2}}}) == SV("-32767/ 2/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{3}}}) == SV("0000/ 3/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{4}}}) == SV("1970/ 4/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{32'767}, std::chrono::month_day_last{std::chrono::month{5}}}) == SV("32767/ 5/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{6}}}) == SV("0000/ 6/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{7}}}) == SV("0000/ 7/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{8}}}) == SV("0000/ 8/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{9}}}) == SV("0000/ 9/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{10}}}) == SV("0000/10/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{11}}}) == SV("0000/11/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{12}}}) == SV("0000/12/last")); +#else // defined(__APPLE__) +# if defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{-32'768}, std::chrono::month_day_last{std::chrono::month{1}}}) == + SV("-32768 is not a valid year/1月/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{-32'767}, std::chrono::month_day_last{std::chrono::month{2}}}) == SV("-32767/2月/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{3}}}) == SV("0000/3月/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{4}}}) == SV("1970/4月/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{32'767}, std::chrono::month_day_last{std::chrono::month{5}}}) == SV("32767/5月/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{6}}}) == SV("0000/6月/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{7}}}) == SV("0000/7月/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{8}}}) == SV("0000/8月/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{9}}}) == SV("0000/9月/last")); +# else // defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{-32'768}, std::chrono::month_day_last{std::chrono::month{1}}}) == + SV("-32768 is not a valid year/ 1月/last")); + assert( + stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{-32'767}, std::chrono::month_day_last{std::chrono::month{2}}}) == SV("-32767/ 2月/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{3}}}) == SV("0000/ 3月/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{4}}}) == SV("1970/ 4月/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{32'767}, std::chrono::month_day_last{std::chrono::month{5}}}) == SV("32767/ 5月/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{6}}}) == SV("0000/ 6月/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{7}}}) == SV("0000/ 7月/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{8}}}) == SV("0000/ 8月/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{9}}}) == SV("0000/ 9月/last")); +# endif // defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{10}}}) == SV("0000/10月/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{11}}}) == SV("0000/11月/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{12}}}) == SV("0000/12月/last")); +#endif // defined(__APPLE__) + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{0}, std::chrono::month_day_last{std::chrono::month{13}}}) == + SV("0000/13 is not a valid month/last")); + assert(stream_ja_JP_locale(std::chrono::year_month_day_last{ + std::chrono::year{-32'768}, std::chrono::month_day_last{std::chrono::month{255}}}) == + SV("-32768 is not a valid year/255 is not a valid month/last")); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/ostream.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/ostream.pass.cpp @@ -0,0 +1,248 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// class year_month_weekday; + +// template +// basic_ostream& +// operator<<(basic_ostream& os, const year_month_weekday& ymwd); + +#include +#include +#include + +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "test_macros.h" + +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static std::basic_string stream_c_locale(std::chrono::year_month_weekday ymwd) { + std::basic_stringstream sstr; + sstr << ymwd; + return sstr.str(); +} + +template +static std::basic_string stream_fr_FR_locale(std::chrono::year_month_weekday ymwd) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_fr_FR_UTF_8); + sstr.imbue(locale); + sstr << ymwd; + return sstr.str(); +} + +template +static std::basic_string stream_ja_JP_locale(std::chrono::year_month_weekday ymwd) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_ja_JP_UTF_8); + sstr.imbue(locale); + sstr << ymwd; + return sstr.str(); +} + +template +static void test() { + assert(stream_c_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'768}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32768 is not a valid year/Jan/Sun[1]")); + assert(stream_c_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{0}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32767/0 is not a valid month/Sun[1]")); + assert( + stream_c_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(8), 1}}) == SV("-32767/Jan/8 is not a valid weekday[1]")); + assert(stream_c_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 0}}) == + SV("-32767/Jan/Sun[0 is not a valid index]")); // note 0 is a valid index here... + assert(stream_c_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32767/Jan/Sun[1]")); + + assert( + stream_c_locale(std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == + SV("1970/Jan/Sun[1]")); + +#if defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'768}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32768 is not a valid year/jan/Dim[1]")); + assert(stream_fr_FR_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{0}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32767/0 is not a valid month/Dim[1]")); + assert( + stream_fr_FR_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(8), 1}}) == SV("-32767/jan/8 is not a valid weekday[1]")); + assert(stream_fr_FR_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 0}}) == + SV("-32767/jan/Dim[0 is not a valid index]")); // note 0 is a valid index here... + assert(stream_fr_FR_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32767/jan/Dim[1]")); + + assert( + stream_fr_FR_locale(std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == + SV("1970/jan/Dim[1]")); +#else // defined(__APPLE__) + assert( + stream_fr_FR_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'768}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32768 is not a valid year/janv./dim.[1]")); + assert(stream_fr_FR_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{0}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32767/0 is not a valid month/dim.[1]")); + assert( + stream_fr_FR_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(8), 1}}) == SV("-32767/janv./8 is not a valid weekday[1]")); + assert(stream_fr_FR_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 0}}) == + SV("-32767/janv./dim.[0 is not a valid index]")); // note 0 is a valid index here... + assert(stream_fr_FR_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32767/janv./dim.[1]")); + + assert( + stream_fr_FR_locale(std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == + SV("1970/janv./dim.[1]")); +#endif // defined(__APPLE__) + +#if defined(__APPLE__) + assert(stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'768}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32768 is not a valid year/ 1/日[1]")); + assert(stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{0}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32767/0 is not a valid month/日[1]")); + assert(stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(8), 1}}) == SV("-32767/ 1/8 is not a valid weekday[1]")); + assert(stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 0}}) == + SV("-32767/ 1/日[0 is not a valid index]")); // note 0 is a valid index here... + assert(stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32767/ 1/日[1]")); + + assert( + stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == + SV("1970/ 1/日[1]")); +#else // defined(__APPLE__) +# if defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'768}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32768 is not a valid year/1月/日[1]")); + assert(stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{0}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32767/0 is not a valid month/日[1]")); + assert( + stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(8), 1}}) == SV("-32767/1月/8 is not a valid weekday[1]")); + + assert(stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 0}}) == + SV("-32767/1月/日[0 is not a valid index]")); // note 0 is a valid index here... + assert(stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32767/1月/日[1]")); + + assert( + stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == + SV("1970/1月/日[1]")); +# else // defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'768}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32768 is not a valid year/ 1月/日[1]")); + assert(stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{0}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32767/0 is not a valid month/日[1]")); + assert( + stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(8), 1}}) == SV("-32767/ 1月/8 is not a valid weekday[1]")); + assert(stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 0}}) == + SV("-32767/ 1月/日[0 is not a valid index]")); // note 0 is a valid index here... + assert(stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{-32'767}, + std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == SV("-32767/ 1月/日[1]")); + + assert( + stream_ja_JP_locale(std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday(0), 1}}) == + SV("1970/ 1月/日[1]")); +# endif // defined(_WIN32) || defined(_AIX) +#endif // defined(__APPLE__) +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.nonmembers/ostream.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.nonmembers/ostream.pass.cpp @@ -0,0 +1,182 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// class year_month_weekday_last; + +// template +// basic_ostream& +// operator<<(basic_ostream& os, const year_month_weekday_last& ymwdl); + +#include +#include +#include + +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "test_macros.h" + +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static std::basic_string stream_c_locale(std::chrono::year_month_weekday_last ymwdl) { + std::basic_stringstream sstr; + sstr << ymwdl; + return sstr.str(); +} + +template +static std::basic_string stream_fr_FR_locale(std::chrono::year_month_weekday_last ymwdl) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_fr_FR_UTF_8); + sstr.imbue(locale); + sstr << ymwdl; + return sstr.str(); +} + +template +static std::basic_string stream_ja_JP_locale(std::chrono::year_month_weekday_last ymwdl) { + std::basic_stringstream sstr; + const std::locale locale(LOCALE_ja_JP_UTF_8); + sstr.imbue(locale); + sstr << ymwdl; + return sstr.str(); +} + +template +static void test() { + assert(stream_c_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'768}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32768 is not a valid year/Jan/Sun[last]")); + assert(stream_c_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32767/0 is not a valid month/Sun[last]")); + assert(stream_c_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{8}}}) == + SV("-32767/Jan/8 is not a valid weekday[last]")); + assert(stream_c_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32767/Jan/Sun[last]")); + + assert(stream_c_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("1970/Jan/Sun[last]")); + +#if defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'768}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32768 is not a valid year/jan/Dim[last]")); + assert(stream_fr_FR_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32767/0 is not a valid month/Dim[last]")); + assert(stream_fr_FR_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{8}}}) == + SV("-32767/jan/8 is not a valid weekday[last]")); + assert(stream_fr_FR_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32767/jan/Dim[last]")); + + assert(stream_fr_FR_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("1970/jan/Dim[last]")); +#else // defined(__APPLE__) + assert(stream_fr_FR_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'768}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32768 is not a valid year/janv./dim.[last]")); + assert(stream_fr_FR_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32767/0 is not a valid month/dim.[last]")); + assert(stream_fr_FR_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{8}}}) == + SV("-32767/janv./8 is not a valid weekday[last]")); + assert(stream_fr_FR_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32767/janv./dim.[last]")); + + assert(stream_fr_FR_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("1970/janv./dim.[last]")); +#endif // defined(__APPLE__) + +#if defined(__APPLE__) + assert(stream_ja_JP_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'768}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32768 is not a valid year/ 1/日[last]")); + assert(stream_ja_JP_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32767/0 is not a valid month/日[last]")); + assert(stream_ja_JP_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{8}}}) == + SV("-32767/ 1/8 is not a valid weekday[last]")); + assert(stream_ja_JP_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32767/ 1/日[last]")); + + assert(stream_ja_JP_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("1970/ 1/日[last]")); +#else // defined(__APPLE__) +# if defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'768}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32768 is not a valid year/1月/日[last]")); + assert(stream_ja_JP_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32767/0 is not a valid month/日[last]")); + assert(stream_ja_JP_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{8}}}) == + SV("-32767/1月/8 is not a valid weekday[last]")); + + assert(stream_ja_JP_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32767/1月/日[last]")); + + assert(stream_ja_JP_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("1970/1月/日[last]")); +# else // defined(_WIN32) || defined(_AIX) + assert(stream_ja_JP_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'768}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32768 is not a valid year/ 1月/日[last]")); + assert(stream_ja_JP_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32767/0 is not a valid month/日[last]")); + assert(stream_ja_JP_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{8}}}) == + SV("-32767/ 1月/8 is not a valid weekday[last]")); + assert(stream_ja_JP_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{-32'767}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("-32767/ 1月/日[last]")); + + assert(stream_ja_JP_locale(std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{0}}}) == + SV("1970/ 1月/日[last]")); +# endif // defined(_WIN32) || defined(_AIX) +#endif // defined(__APPLE__) +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.syn/formatter.month_day.pass.cpp b/libcxx/test/std/time/time.syn/formatter.month_day.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.syn/formatter.month_day.pass.cpp @@ -0,0 +1,483 @@ +//===----------------------------------------------------------------------===// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// template struct formatter; + +#include +#include + +#include +#include +#include +#include +#include + +#include "formatter_tests.h" +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "string_literal.h" +#include "test_macros.h" + +template +static void test_no_chrono_specs() { + // Valid month "valid" day + check(SV("Feb/31"), SV("{}"), std::chrono::month_day{std::chrono::month{2}, std::chrono::day{31}}); + check(SV("*Feb/31*"), SV("{:*^8}"), std::chrono::month_day{std::chrono::month{2}, std::chrono::day{31}}); + check(SV("*Feb/31"), SV("{:*>7}"), std::chrono::month_day{std::chrono::month{2}, std::chrono::day{31}}); + + // Invalid month "valid" day + check(SV("0 is not a valid month/31"), SV("{}"), std::chrono::month_day{std::chrono::month{0}, std::chrono::day{31}}); + check(SV("*0 is not a valid month/31*"), + SV("{:*^27}"), + std::chrono::month_day{std::chrono::month{0}, std::chrono::day{31}}); + + // Valid month invalid day + check(SV("Feb/32 is not a valid day"), SV("{}"), std::chrono::month_day{std::chrono::month{2}, std::chrono::day{32}}); + check(SV("*Feb/32 is not a valid day*"), + SV("{:*^27}"), + std::chrono::month_day{std::chrono::month{2}, std::chrono::day{32}}); + check(SV("*Feb/32 is not a valid day"), + SV("{:*>26}"), + std::chrono::month_day{std::chrono::month{2}, std::chrono::day{32}}); + + // Invalid month invalid day + check(SV("0 is not a valid month/32 is not a valid day"), + SV("{}"), + std::chrono::month_day{std::chrono::month{0}, std::chrono::day{32}}); + check(SV("*0 is not a valid month/32 is not a valid day*"), + SV("{:*^46}"), + std::chrono::month_day{std::chrono::month{0}, std::chrono::day{32}}); +} + +template +static void test_valid_values() { + // Test that %b, %h, and %B throw an exception. + check_exception("formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::month_day{std::chrono::month{200}, std::chrono::day{31}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::month_day{std::chrono::month{13}, std::chrono::day{31}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::month_day{std::chrono::month{255}, std::chrono::day{31}}); + + check_exception("formatting a month name from an invalid month number", + SV("{:%h}"), + std::chrono::month_day{std::chrono::month{0}, std::chrono::day{31}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%h}"), + std::chrono::month_day{std::chrono::month{13}, std::chrono::day{31}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%h}"), + std::chrono::month_day{std::chrono::month{255}, std::chrono::day{31}}); + + check_exception("formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::month_day{std::chrono::month{0}, std::chrono::day{31}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::month_day{std::chrono::month{13}, std::chrono::day{31}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::month_day{std::chrono::month{255}, std::chrono::day{31}}); + + constexpr std::basic_string_view fmt = + SV("{:%%b='%b'%t%%B='%B'%t%%h='%h'%t%%m='%m'%t%%Om='%Om'%t%%d='%d'%t%%e='%e'%t%%Od='%Od'%t%%Oe='%Oe'%n}"); + constexpr std::basic_string_view lfmt = + SV("{:L%%b='%b'%t%%B='%B'%t%%h='%h'%t%%m='%m'%t%%Om='%Om'%t%%d='%d'%t%%e='%e'%t%%Od='%Od'%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("%b='Jan'\t%B='January'\t%h='Jan'\t%m='01'\t%Om='01'\t%d='00'\t%e=' 0'\t%Od='00'\t%Oe=' 0'\n"), + fmt, + std::chrono::month_day{std::chrono::January, std::chrono::day{0}}); + check(SV("%b='Feb'\t%B='February'\t%h='Feb'\t%m='02'\t%Om='02'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), + fmt, + std::chrono::month_day{std::chrono::February, std::chrono::day{1}}); + check(SV("%b='Mar'\t%B='March'\t%h='Mar'\t%m='03'\t%Om='03'\t%d='09'\t%e=' 9'\t%Od='09'\t%Oe=' 9'\n"), + fmt, + std::chrono::month_day{std::chrono::March, std::chrono::day{9}}); + check(SV("%b='Apr'\t%B='April'\t%h='Apr'\t%m='04'\t%Om='04'\t%d='10'\t%e='10'\t%Od='10'\t%Oe='10'\n"), + fmt, + std::chrono::month_day{std::chrono::April, std::chrono::day{10}}); + check(SV("%b='May'\t%B='May'\t%h='May'\t%m='05'\t%Om='05'\t%d='28'\t%e='28'\t%Od='28'\t%Oe='28'\n"), + fmt, + std::chrono::month_day{std::chrono::May, std::chrono::day{28}}); + check(SV("%b='Jun'\t%B='June'\t%h='Jun'\t%m='06'\t%Om='06'\t%d='29'\t%e='29'\t%Od='29'\t%Oe='29'\n"), + fmt, + std::chrono::month_day{std::chrono::June, std::chrono::day{29}}); + check(SV("%b='Jul'\t%B='July'\t%h='Jul'\t%m='07'\t%Om='07'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + fmt, + std::chrono::month_day{std::chrono::July, std::chrono::day{30}}); + check(SV("%b='Aug'\t%B='August'\t%h='Aug'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + fmt, + std::chrono::month_day{std::chrono::August, std::chrono::day{31}}); + check(SV("%b='Sep'\t%B='September'\t%h='Sep'\t%m='09'\t%Om='09'\t%d='32'\t%e='32'\t%Od='32'\t%Oe='32'\n"), + fmt, + std::chrono::month_day{std::chrono::September, std::chrono::day{32}}); + check(SV("%b='Oct'\t%B='October'\t%h='Oct'\t%m='10'\t%Om='10'\t%d='99'\t%e='99'\t%Od='99'\t%Oe='99'\n"), + fmt, + std::chrono::month_day{std::chrono::October, std::chrono::day{99}}); +#if defined(_AIX) + check(SV("%b='Nov'\t%B='November'\t%h='Nov'\t%m='11'\t%Om='11'\t%d='00'\t%e=' 0'\t%Od='00'\t%Oe=' 0'\n"), + fmt, + std::chrono::month_day{std::chrono::November, std::chrono::day{100}}); + check(SV("%b='Dec'\t%B='December'\t%h='Dec'\t%m='12'\t%Om='12'\t%d='55'\t%e='55'\t%Od='55'\t%Oe='55'\n"), + fmt, + std::chrono::month_day{std::chrono::December, std::chrono::day{255}}); +#else // defined(_AIX) + check(SV("%b='Nov'\t%B='November'\t%h='Nov'\t%m='11'\t%Om='11'\t%d='100'\t%e='100'\t%Od='100'\t%Oe='100'\n"), + fmt, + std::chrono::month_day{std::chrono::November, std::chrono::day{100}}); + check(SV("%b='Dec'\t%B='December'\t%h='Dec'\t%m='12'\t%Om='12'\t%d='255'\t%e='255'\t%Od='255'\t%Oe='255'\n"), + fmt, + std::chrono::month_day{std::chrono::December, std::chrono::day{255}}); +#endif // defined(_AIX) + + // Use the global locale (fr_FR) +#if defined(__APPLE__) + check(SV("%b='jan'\t%B='janvier'\t%h='jan'\t%m='01'\t%Om='01'\t%d='00'\t%e=' 0'\t%Od='00'\t%Oe=' 0'\n"), + lfmt, + std::chrono::month_day{std::chrono::January, std::chrono::day{0}}); + check(SV("%b='fév'\t%B='février'\t%h='fév'\t%m='02'\t%Om='02'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), + lfmt, + std::chrono::month_day{std::chrono::February, std::chrono::day{1}}); + check(SV("%b='mar'\t%B='mars'\t%h='mar'\t%m='03'\t%Om='03'\t%d='09'\t%e=' 9'\t%Od='09'\t%Oe=' 9'\n"), + lfmt, + std::chrono::month_day{std::chrono::March, std::chrono::day{9}}); + check(SV("%b='avr'\t%B='avril'\t%h='avr'\t%m='04'\t%Om='04'\t%d='10'\t%e='10'\t%Od='10'\t%Oe='10'\n"), + lfmt, + std::chrono::month_day{std::chrono::April, std::chrono::day{10}}); + check(SV("%b='mai'\t%B='mai'\t%h='mai'\t%m='05'\t%Om='05'\t%d='28'\t%e='28'\t%Od='28'\t%Oe='28'\n"), + lfmt, + std::chrono::month_day{std::chrono::May, std::chrono::day{28}}); + check(SV("%b='jui'\t%B='juin'\t%h='jui'\t%m='06'\t%Om='06'\t%d='29'\t%e='29'\t%Od='29'\t%Oe='29'\n"), + lfmt, + std::chrono::month_day{std::chrono::June, std::chrono::day{29}}); + check(SV("%b='jul'\t%B='juillet'\t%h='jul'\t%m='07'\t%Om='07'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::month_day{std::chrono::July, std::chrono::day{30}}); + check(SV("%b='aoû'\t%B='août'\t%h='aoû'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::month_day{std::chrono::August, std::chrono::day{31}}); + check(SV("%b='sep'\t%B='septembre'\t%h='sep'\t%m='09'\t%Om='09'\t%d='32'\t%e='32'\t%Od='32'\t%Oe='32'\n"), + lfmt, + std::chrono::month_day{std::chrono::September, std::chrono::day{32}}); + check(SV("%b='oct'\t%B='octobre'\t%h='oct'\t%m='10'\t%Om='10'\t%d='99'\t%e='99'\t%Od='99'\t%Oe='99'\n"), + lfmt, + std::chrono::month_day{std::chrono::October, std::chrono::day{99}}); + check(SV("%b='nov'\t%B='novembre'\t%h='nov'\t%m='11'\t%Om='11'\t%d='100'\t%e='100'\t%Od='100'\t%Oe='100'\n"), + lfmt, + std::chrono::month_day{std::chrono::November, std::chrono::day{100}}); + check(SV("%b='déc'\t%B='décembre'\t%h='déc'\t%m='12'\t%Om='12'\t%d='255'\t%e='255'\t%Od='255'\t%Oe='255'\n"), + lfmt, + std::chrono::month_day{std::chrono::December, std::chrono::day{255}}); +#else // defined(__APPLE__) + check(SV("%b='janv.'\t%B='janvier'\t%h='janv.'\t%m='01'\t%Om='01'\t%d='00'\t%e=' 0'\t%Od='00'\t%Oe=' 0'\n"), + lfmt, + std::chrono::month_day{std::chrono::January, std::chrono::day{0}}); + check(SV("%b='févr.'\t%B='février'\t%h='févr.'\t%m='02'\t%Om='02'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), + lfmt, + std::chrono::month_day{std::chrono::February, std::chrono::day{1}}); + check(SV("%b='mars'\t%B='mars'\t%h='mars'\t%m='03'\t%Om='03'\t%d='09'\t%e=' 9'\t%Od='09'\t%Oe=' 9'\n"), + lfmt, + std::chrono::month_day{std::chrono::March, std::chrono::day{9}}); + check( +# if defined(_WIN32) || defined(_AIX) + SV("%b='avr.'\t%B='avril'\t%h='avr.'\t%m='04'\t%Om='04'\t%d='10'\t%e='10'\t%Od='10'\t%Oe='10'\n"), +# else // defined(_WIN32) || defined(_AIX) + SV("%b='avril'\t%B='avril'\t%h='avril'\t%m='04'\t%Om='04'\t%d='10'\t%e='10'\t%Od='10'\t%Oe='10'\n"), +# endif // defined(_WIN32) || defined(_AIX) + lfmt, + std::chrono::month_day{std::chrono::April, std::chrono::day{10}}); + check(SV("%b='mai'\t%B='mai'\t%h='mai'\t%m='05'\t%Om='05'\t%d='28'\t%e='28'\t%Od='28'\t%Oe='28'\n"), + lfmt, + std::chrono::month_day{std::chrono::May, std::chrono::day{28}}); + check(SV("%b='juin'\t%B='juin'\t%h='juin'\t%m='06'\t%Om='06'\t%d='29'\t%e='29'\t%Od='29'\t%Oe='29'\n"), + lfmt, + std::chrono::month_day{std::chrono::June, std::chrono::day{29}}); + check(SV("%b='juil.'\t%B='juillet'\t%h='juil.'\t%m='07'\t%Om='07'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::month_day{std::chrono::July, std::chrono::day{30}}); + check(SV("%b='août'\t%B='août'\t%h='août'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::month_day{std::chrono::August, std::chrono::day{31}}); + check(SV("%b='sept.'\t%B='septembre'\t%h='sept.'\t%m='09'\t%Om='09'\t%d='32'\t%e='32'\t%Od='32'\t%Oe='32'\n"), + lfmt, + std::chrono::month_day{std::chrono::September, std::chrono::day{32}}); + check(SV("%b='oct.'\t%B='octobre'\t%h='oct.'\t%m='10'\t%Om='10'\t%d='99'\t%e='99'\t%Od='99'\t%Oe='99'\n"), + lfmt, + std::chrono::month_day{std::chrono::October, std::chrono::day{99}}); +# if defined(_AIX) + check(SV("%b='nov.'\t%B='novembre'\t%h='nov.'\t%m='11'\t%Om='11'\t%d='00'\t%e=' 0'\t%Od='00'\t%Oe=' 0'\n"), + lfmt, + std::chrono::month_day{std::chrono::November, std::chrono::day{100}}); + check(SV("%b='déc.'\t%B='décembre'\t%h='déc.'\t%m='12'\t%Om='12'\t%d='55'\t%e='55'\t%Od='55'\t%Oe='55'\n"), + lfmt, + std::chrono::month_day{std::chrono::December, std::chrono::day{255}}); +# else // defined(_AIX) + check(SV("%b='nov.'\t%B='novembre'\t%h='nov.'\t%m='11'\t%Om='11'\t%d='100'\t%e='100'\t%Od='100'\t%Oe='100'\n"), + lfmt, + std::chrono::month_day{std::chrono::November, std::chrono::day{100}}); + check(SV("%b='déc.'\t%B='décembre'\t%h='déc.'\t%m='12'\t%Om='12'\t%d='255'\t%e='255'\t%Od='255'\t%Oe='255'\n"), + lfmt, + std::chrono::month_day{std::chrono::December, std::chrono::day{255}}); +# endif // defined(_AIX) +#endif // defined(__APPLE__) + + // Use supplied locale (ja_JP) +#if defined(_WIN32) + check(loc, + SV("%b='1'\t%B='1月'\t%h='1'\t%m='01'\t%Om='01'\t%d='00'\t%e=' 0'\t%Od='〇'\t%Oe='〇'\n"), + lfmt, + std::chrono::month_day{std::chrono::January, std::chrono::day{0}}); + check(loc, + SV("%b='2'\t%B='2月'\t%h='2'\t%m='02'\t%Om='02'\t%d='01'\t%e=' 1'\t%Od='一'\t%Oe='一'\n"), + lfmt, + std::chrono::month_day{std::chrono::February, std::chrono::day{1}}); + check(loc, + SV("%b='3'\t%B='3月'\t%h='3'\t%m='03'\t%Om='03'\t%d='09'\t%e=' 9'\t%Od='九'\t%Oe='九'\n"), + lfmt, + std::chrono::month_day{std::chrono::March, std::chrono::day{9}}); + check(loc, + SV("%b='4'\t%B='4月'\t%h='4'\t%m='04'\t%Om='04'\t%d='10'\t%e='10'\t%Od='十'\t%Oe='十'\n"), + lfmt, + std::chrono::month_day{std::chrono::April, std::chrono::day{10}}); + check(loc, + SV("%b='5'\t%B='5月'\t%h='5'\t%m='05'\t%Om='05'\t%d='28'\t%e='28'\t%Od='二十八'\t%Oe='二十八'\n"), + lfmt, + std::chrono::month_day{std::chrono::May, std::chrono::day{28}}); + check(loc, + SV("%b='6'\t%B='6月'\t%h='6'\t%m='06'\t%Om='06'\t%d='29'\t%e='29'\t%Od='二十九'\t%Oe='二十九'\n"), + lfmt, + std::chrono::month_day{std::chrono::June, std::chrono::day{29}}); + check(loc, + SV("%b='7'\t%B='7月'\t%h='7'\t%m='07'\t%Om='07'\t%d='30'\t%e='30'\t%Od='三十'\t%Oe='三十'\n"), + lfmt, + std::chrono::month_day{std::chrono::July, std::chrono::day{30}}); + check(loc, + SV("%b='8'\t%B='8月'\t%h='8'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='三十一'\t%Oe='三十一'\n"), + lfmt, + std::chrono::month_day{std::chrono::August, std::chrono::day{31}}); + check(loc, + SV("%b='9'\t%B='9月'\t%h='9'\t%m='09'\t%Om='09'\t%d='32'\t%e='32'\t%Od='三十二'\t%Oe='三十二'\n"), + lfmt, + std::chrono::month_day{std::chrono::September, std::chrono::day{32}}); + check(loc, + SV("%b='10'\t%B='10月'\t%h='10'\t%m='10'\t%Om='10'\t%d='99'\t%e='99'\t%Od='九十九'\t%Oe='九十九'\n"), + lfmt, + std::chrono::month_day{std::chrono::October, std::chrono::day{99}}); + check(loc, + SV("%b='11'\t%B='11月'\t%h='11'\t%m='11'\t%Om='11'\t%d='100'\t%e='100'\t%Od='100'\t%Oe='100'\n"), + lfmt, + std::chrono::month_day{std::chrono::November, std::chrono::day{100}}); + check(loc, + SV("%b='12'\t%B='12月'\t%h='12'\t%m='12'\t%Om='12'\t%d='255'\t%e='255'\t%Od='255'\t%Oe='255'\n"), + lfmt, + std::chrono::month_day{std::chrono::December, std::chrono::day{255}}); +#elif defined(_AIX) // defined(_WIN32) + check(loc, + SV("%b='1月'\t%B='1月'\t%h='1月'\t%m='01'\t%Om='01'\t%d='00'\t%e=' 0'\t%Od='00'\t%Oe=' 0'\n"), + lfmt, + std::chrono::month_day{std::chrono::January, std::chrono::day{0}}); + check(loc, + SV("%b='2月'\t%B='2月'\t%h='2月'\t%m='02'\t%Om='02'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), + lfmt, + std::chrono::month_day{std::chrono::February, std::chrono::day{1}}); + check(loc, + SV("%b='3月'\t%B='3月'\t%h='3月'\t%m='03'\t%Om='03'\t%d='09'\t%e=' 9'\t%Od='09'\t%Oe=' 9'\n"), + lfmt, + std::chrono::month_day{std::chrono::March, std::chrono::day{9}}); + check(loc, + SV("%b='4月'\t%B='4月'\t%h='4月'\t%m='04'\t%Om='04'\t%d='10'\t%e='10'\t%Od='10'\t%Oe='10'\n"), + lfmt, + std::chrono::month_day{std::chrono::April, std::chrono::day{10}}); + check(loc, + SV("%b='5月'\t%B='5月'\t%h='5月'\t%m='05'\t%Om='05'\t%d='28'\t%e='28'\t%Od='28'\t%Oe='28'\n"), + lfmt, + std::chrono::month_day{std::chrono::May, std::chrono::day{28}}); + check(loc, + SV("%b='6月'\t%B='6月'\t%h='6月'\t%m='06'\t%Om='06'\t%d='29'\t%e='29'\t%Od='29'\t%Oe='29'\n"), + lfmt, + std::chrono::month_day{std::chrono::June, std::chrono::day{29}}); + check(loc, + SV("%b='7月'\t%B='7月'\t%h='7月'\t%m='07'\t%Om='07'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::month_day{std::chrono::July, std::chrono::day{30}}); + check(loc, + SV("%b='8月'\t%B='8月'\t%h='8月'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::month_day{std::chrono::August, std::chrono::day{31}}); + check(loc, + SV("%b='9月'\t%B='9月'\t%h='9月'\t%m='09'\t%Om='09'\t%d='32'\t%e='32'\t%Od='32'\t%Oe='32'\n"), + lfmt, + std::chrono::month_day{std::chrono::September, std::chrono::day{32}}); + check(loc, + SV("%b='10月'\t%B='10月'\t%h='10月'\t%m='10'\t%Om='10'\t%d='99'\t%e='99'\t%Od='99'\t%Oe='99'\n"), + lfmt, + std::chrono::month_day{std::chrono::October, std::chrono::day{99}}); + check(loc, + SV("%b='11月'\t%B='11月'\t%h='11月'\t%m='11'\t%Om='11'\t%d='00'\t%e=' 0'\t%Od='00'\t%Oe=' 0'\n"), + lfmt, + std::chrono::month_day{std::chrono::November, std::chrono::day{100}}); + check(loc, + SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='12'\t%d='55'\t%e='55'\t%Od='55'\t%Oe='55'\n"), + lfmt, + std::chrono::month_day{std::chrono::December, std::chrono::day{255}}); +#elif defined(__APPLE__) // defined(_WIN32) + check(loc, + SV("%b=' 1'\t%B='1月'\t%h=' 1'\t%m='01'\t%Om='01'\t%d='00'\t%e=' 0'\t%Od='00'\t%Oe=' 0'\n"), + lfmt, + std::chrono::month_day{std::chrono::January, std::chrono::day{0}}); + check(loc, + SV("%b=' 2'\t%B='2月'\t%h=' 2'\t%m='02'\t%Om='02'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), + lfmt, + std::chrono::month_day{std::chrono::February, std::chrono::day{1}}); + check(loc, + SV("%b=' 3'\t%B='3月'\t%h=' 3'\t%m='03'\t%Om='03'\t%d='09'\t%e=' 9'\t%Od='09'\t%Oe=' 9'\n"), + lfmt, + std::chrono::month_day{std::chrono::March, std::chrono::day{9}}); + check(loc, + SV("%b=' 4'\t%B='4月'\t%h=' 4'\t%m='04'\t%Om='04'\t%d='10'\t%e='10'\t%Od='10'\t%Oe='10'\n"), + lfmt, + std::chrono::month_day{std::chrono::April, std::chrono::day{10}}); + check(loc, + SV("%b=' 5'\t%B='5月'\t%h=' 5'\t%m='05'\t%Om='05'\t%d='28'\t%e='28'\t%Od='28'\t%Oe='28'\n"), + lfmt, + std::chrono::month_day{std::chrono::May, std::chrono::day{28}}); + check(loc, + SV("%b=' 6'\t%B='6月'\t%h=' 6'\t%m='06'\t%Om='06'\t%d='29'\t%e='29'\t%Od='29'\t%Oe='29'\n"), + lfmt, + std::chrono::month_day{std::chrono::June, std::chrono::day{29}}); + check(loc, + SV("%b=' 7'\t%B='7月'\t%h=' 7'\t%m='07'\t%Om='07'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::month_day{std::chrono::July, std::chrono::day{30}}); + check(loc, + SV("%b=' 8'\t%B='8月'\t%h=' 8'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::month_day{std::chrono::August, std::chrono::day{31}}); + check(loc, + SV("%b=' 9'\t%B='9月'\t%h=' 9'\t%m='09'\t%Om='09'\t%d='32'\t%e='32'\t%Od='32'\t%Oe='32'\n"), + lfmt, + std::chrono::month_day{std::chrono::September, std::chrono::day{32}}); + check(loc, + SV("%b='10'\t%B='10月'\t%h='10'\t%m='10'\t%Om='10'\t%d='99'\t%e='99'\t%Od='99'\t%Oe='99'\n"), + lfmt, + std::chrono::month_day{std::chrono::October, std::chrono::day{99}}); + check(loc, + SV("%b='11'\t%B='11月'\t%h='11'\t%m='11'\t%Om='11'\t%d='100'\t%e='100'\t%Od='100'\t%Oe='100'\n"), + lfmt, + std::chrono::month_day{std::chrono::November, std::chrono::day{100}}); + check(loc, + SV("%b='12'\t%B='12月'\t%h='12'\t%m='12'\t%Om='12'\t%d='255'\t%e='255'\t%Od='255'\t%Oe='255'\n"), + lfmt, + std::chrono::month_day{std::chrono::December, std::chrono::day{255}}); +#else // defined(_WIN32) + check(loc, + SV("%b=' 1月'\t%B='1月'\t%h=' 1月'\t%m='01'\t%Om='一'\t%d='00'\t%e=' 0'\t%Od='〇'\t%Oe='〇'\n"), + lfmt, + std::chrono::month_day{std::chrono::January, std::chrono::day{0}}); + check(loc, + SV("%b=' 2月'\t%B='2月'\t%h=' 2月'\t%m='02'\t%Om='二'\t%d='01'\t%e=' 1'\t%Od='一'\t%Oe='一'\n"), + lfmt, + std::chrono::month_day{std::chrono::February, std::chrono::day{1}}); + check(loc, + SV("%b=' 3月'\t%B='3月'\t%h=' 3月'\t%m='03'\t%Om='三'\t%d='09'\t%e=' 9'\t%Od='九'\t%Oe='九'\n"), + lfmt, + std::chrono::month_day{std::chrono::March, std::chrono::day{9}}); + check(loc, + SV("%b=' 4月'\t%B='4月'\t%h=' 4月'\t%m='04'\t%Om='四'\t%d='10'\t%e='10'\t%Od='十'\t%Oe='十'\n"), + lfmt, + std::chrono::month_day{std::chrono::April, std::chrono::day{10}}); + check(loc, + SV("%b=' 5月'\t%B='5月'\t%h=' 5月'\t%m='05'\t%Om='五'\t%d='28'\t%e='28'\t%Od='二十八'\t%Oe='二十八'\n"), + lfmt, + std::chrono::month_day{std::chrono::May, std::chrono::day{28}}); + check(loc, + SV("%b=' 6月'\t%B='6月'\t%h=' 6月'\t%m='06'\t%Om='六'\t%d='29'\t%e='29'\t%Od='二十九'\t%Oe='二十九'\n"), + lfmt, + std::chrono::month_day{std::chrono::June, std::chrono::day{29}}); + check(loc, + SV("%b=' 7月'\t%B='7月'\t%h=' 7月'\t%m='07'\t%Om='七'\t%d='30'\t%e='30'\t%Od='三十'\t%Oe='三十'\n"), + lfmt, + std::chrono::month_day{std::chrono::July, std::chrono::day{30}}); + check(loc, + SV("%b=' 8月'\t%B='8月'\t%h=' 8月'\t%m='08'\t%Om='八'\t%d='31'\t%e='31'\t%Od='三十一'\t%Oe='三十一'\n"), + lfmt, + std::chrono::month_day{std::chrono::August, std::chrono::day{31}}); + check(loc, + SV("%b=' 9月'\t%B='9月'\t%h=' 9月'\t%m='09'\t%Om='九'\t%d='32'\t%e='32'\t%Od='三十二'\t%Oe='三十二'\n"), + lfmt, + std::chrono::month_day{std::chrono::September, std::chrono::day{32}}); + check(loc, + SV("%b='10月'\t%B='10月'\t%h='10月'\t%m='10'\t%Om='十'\t%d='99'\t%e='99'\t%Od='九十九'\t%Oe='九十九'\n"), + lfmt, + std::chrono::month_day{std::chrono::October, std::chrono::day{99}}); + check(loc, + SV("%b='11月'\t%B='11月'\t%h='11月'\t%m='11'\t%Om='十一'\t%d='100'\t%e='100'\t%Od='100'\t%Oe='100'\n"), + lfmt, + std::chrono::month_day{std::chrono::November, std::chrono::day{100}}); + check(loc, + SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='十二'\t%d='255'\t%e='255'\t%Od='255'\t%Oe='255'\n"), + lfmt, + std::chrono::month_day{std::chrono::December, std::chrono::day{255}}); +#endif // defined(_WIN32) + + std::locale::global(std::locale::classic()); +} + +template +static void test() { + test_no_chrono_specs(); + test_valid_values(); + check_invalid_types({SV("b"), SV("B"), SV("d"), SV("e"), SV("h"), SV("m"), SV("Od"), SV("Oe"), SV("Om")}, + std::chrono::month_day{std::chrono::January, std::chrono::day{31}}); + + check_exception("Expected '%' or '}' in the chrono format-string", + SV("{:A"), + std::chrono::month_day{std::chrono::January, std::chrono::day{31}}); + check_exception("The chrono-specs contains a '{'", + SV("{:%%{"), + std::chrono::month_day{std::chrono::January, std::chrono::day{31}}); + check_exception("End of input while parsing the modifier chrono conversion-spec", + SV("{:%"), + std::chrono::month_day{std::chrono::January, std::chrono::day{31}}); + check_exception("End of input while parsing the modifier E", + SV("{:%E"), + std::chrono::month_day{std::chrono::January, std::chrono::day{31}}); + check_exception("End of input while parsing the modifier O", + SV("{:%O"), + std::chrono::month_day{std::chrono::January, std::chrono::day{31}}); + + // Precision not allowed + check_exception("Expected '%' or '}' in the chrono format-string", + SV("{:.3}"), + std::chrono::month_day{std::chrono::January, std::chrono::day{31}}); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.syn/formatter.month_day_last.pass.cpp b/libcxx/test/std/time/time.syn/formatter.month_day_last.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.syn/formatter.month_day_last.pass.cpp @@ -0,0 +1,400 @@ +//===----------------------------------------------------------------------===// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// template struct formatter; + +#include +#include + +#include +#include +#include +#include +#include + +#include "formatter_tests.h" +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "string_literal.h" +#include "test_macros.h" + +template +static void test_no_chrono_specs() { + // Valid month + check(SV("Jan/last"), SV("{}"), std::chrono::month_day_last{std::chrono::month{1}}); + check(SV("*Jan/last*"), SV("{:*^10}"), std::chrono::month_day_last{std::chrono::month{1}}); + check(SV("*Jan/last"), SV("{:*>9}"), std::chrono::month_day_last{std::chrono::month{1}}); + + // Invalid month + check(SV("0 is not a valid month/last"), SV("{}"), std::chrono::month_day_last{std::chrono::month{0}}); + check(SV("*0 is not a valid month/last*"), SV("{:*^29}"), std::chrono::month_day_last{std::chrono::month{0}}); +} + +template +static void test_valid_values() { + // Test that %b, %h, and %B throw an exception. + check_exception("formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::month_day_last{std::chrono::month{200}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::month_day_last{std::chrono::month{13}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::month_day_last{std::chrono::month{255}}); + + check_exception("formatting a month name from an invalid month number", + SV("{:%h}"), + std::chrono::month_day_last{std::chrono::month{0}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%h}"), + std::chrono::month_day_last{std::chrono::month{13}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%h}"), + std::chrono::month_day_last{std::chrono::month{255}}); + + check_exception("formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::month_day_last{std::chrono::month{0}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::month_day_last{std::chrono::month{13}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::month_day_last{std::chrono::month{255}}); + + constexpr std::basic_string_view fmt = SV("{:%%b='%b'%t%%B='%B'%t%%h='%h'%t%%m='%m'%t%%Om='%Om'%n}"); + constexpr std::basic_string_view lfmt = SV("{:L%%b='%b'%t%%B='%B'%t%%h='%h'%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%B='January'\t%h='Jan'\t%m='01'\t%Om='01'\n"), + fmt, + std::chrono::month_day_last{std::chrono::January}); + check(SV("%b='Feb'\t%B='February'\t%h='Feb'\t%m='02'\t%Om='02'\n"), + fmt, + std::chrono::month_day_last{std::chrono::February}); + check( + SV("%b='Mar'\t%B='March'\t%h='Mar'\t%m='03'\t%Om='03'\n"), fmt, std::chrono::month_day_last{std::chrono::March}); + check( + SV("%b='Apr'\t%B='April'\t%h='Apr'\t%m='04'\t%Om='04'\n"), fmt, std::chrono::month_day_last{std::chrono::April}); + check(SV("%b='May'\t%B='May'\t%h='May'\t%m='05'\t%Om='05'\n"), fmt, std::chrono::month_day_last{std::chrono::May}); + check(SV("%b='Jun'\t%B='June'\t%h='Jun'\t%m='06'\t%Om='06'\n"), fmt, std::chrono::month_day_last{std::chrono::June}); + check(SV("%b='Jul'\t%B='July'\t%h='Jul'\t%m='07'\t%Om='07'\n"), fmt, std::chrono::month_day_last{std::chrono::July}); + check(SV("%b='Aug'\t%B='August'\t%h='Aug'\t%m='08'\t%Om='08'\n"), + fmt, + std::chrono::month_day_last{std::chrono::August}); + check(SV("%b='Sep'\t%B='September'\t%h='Sep'\t%m='09'\t%Om='09'\n"), + fmt, + std::chrono::month_day_last{std::chrono::September}); + check(SV("%b='Oct'\t%B='October'\t%h='Oct'\t%m='10'\t%Om='10'\n"), + fmt, + std::chrono::month_day_last{std::chrono::October}); + check(SV("%b='Nov'\t%B='November'\t%h='Nov'\t%m='11'\t%Om='11'\n"), + fmt, + std::chrono::month_day_last{std::chrono::November}); + check(SV("%b='Dec'\t%B='December'\t%h='Dec'\t%m='12'\t%Om='12'\n"), + fmt, + std::chrono::month_day_last{std::chrono::December}); + + // Use the global locale (fr_FR) +#if defined(__APPLE__) + check(SV("%b='jan'\t%B='janvier'\t%h='jan'\t%m='01'\t%Om='01'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::January}); + check(SV("%b='fév'\t%B='février'\t%h='fév'\t%m='02'\t%Om='02'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::February}); + check( + SV("%b='mar'\t%B='mars'\t%h='mar'\t%m='03'\t%Om='03'\n"), lfmt, std::chrono::month_day_last{std::chrono::March}); + check( + SV("%b='avr'\t%B='avril'\t%h='avr'\t%m='04'\t%Om='04'\n"), lfmt, std::chrono::month_day_last{std::chrono::April}); + check(SV("%b='mai'\t%B='mai'\t%h='mai'\t%m='05'\t%Om='05'\n"), lfmt, std::chrono::month_day_last{std::chrono::May}); + check(SV("%b='jui'\t%B='juin'\t%h='jui'\t%m='06'\t%Om='06'\n"), lfmt, std::chrono::month_day_last{std::chrono::June}); + check(SV("%b='jul'\t%B='juillet'\t%h='jul'\t%m='07'\t%Om='07'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::July}); + check( + SV("%b='aoû'\t%B='août'\t%h='aoû'\t%m='08'\t%Om='08'\n"), lfmt, std::chrono::month_day_last{std::chrono::August}); + check(SV("%b='sep'\t%B='septembre'\t%h='sep'\t%m='09'\t%Om='09'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::September}); + check(SV("%b='oct'\t%B='octobre'\t%h='oct'\t%m='10'\t%Om='10'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::October}); + check(SV("%b='nov'\t%B='novembre'\t%h='nov'\t%m='11'\t%Om='11'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::November}); + check(SV("%b='déc'\t%B='décembre'\t%h='déc'\t%m='12'\t%Om='12'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::December}); +#else // defined(__APPLE__) + check(SV("%b='janv.'\t%B='janvier'\t%h='janv.'\t%m='01'\t%Om='01'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::January}); + check(SV("%b='févr.'\t%B='février'\t%h='févr.'\t%m='02'\t%Om='02'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::February}); + check(SV("%b='mars'\t%B='mars'\t%h='mars'\t%m='03'\t%Om='03'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::March}); + check( +# if defined(_WIN32) || defined(_AIX) + SV("%b='avr.'\t%B='avril'\t%h='avr.'\t%m='04'\t%Om='04'\n"), +# else // defined(_WIN32) || defined(_AIX) + SV("%b='avril'\t%B='avril'\t%h='avril'\t%m='04'\t%Om='04'\n"), +# endif // defined(_WIN32) || defined(_AIX) + lfmt, + std::chrono::month_day_last{std::chrono::April}); + check(SV("%b='mai'\t%B='mai'\t%h='mai'\t%m='05'\t%Om='05'\n"), lfmt, std::chrono::month_day_last{std::chrono::May}); + check( + SV("%b='juin'\t%B='juin'\t%h='juin'\t%m='06'\t%Om='06'\n"), lfmt, std::chrono::month_day_last{std::chrono::June}); + check(SV("%b='juil.'\t%B='juillet'\t%h='juil.'\t%m='07'\t%Om='07'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::July}); + check(SV("%b='août'\t%B='août'\t%h='août'\t%m='08'\t%Om='08'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::August}); + check(SV("%b='sept.'\t%B='septembre'\t%h='sept.'\t%m='09'\t%Om='09'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::September}); + check(SV("%b='oct.'\t%B='octobre'\t%h='oct.'\t%m='10'\t%Om='10'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::October}); + check(SV("%b='nov.'\t%B='novembre'\t%h='nov.'\t%m='11'\t%Om='11'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::November}); + check(SV("%b='déc.'\t%B='décembre'\t%h='déc.'\t%m='12'\t%Om='12'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::December}); +#endif // defined(__APPLE__) + + // Use supplied locale (ja_JP) +#ifdef _WIN32 + check(loc, + SV("%b='1'\t%B='1月'\t%h='1'\t%m='01'\t%Om='01'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::January}); + check(loc, + SV("%b='2'\t%B='2月'\t%h='2'\t%m='02'\t%Om='02'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::February}); + check( + loc, SV("%b='3'\t%B='3月'\t%h='3'\t%m='03'\t%Om='03'\n"), lfmt, std::chrono::month_day_last{std::chrono::March}); + check( + loc, SV("%b='4'\t%B='4月'\t%h='4'\t%m='04'\t%Om='04'\n"), lfmt, std::chrono::month_day_last{std::chrono::April}); + check(loc, SV("%b='5'\t%B='5月'\t%h='5'\t%m='05'\t%Om='05'\n"), lfmt, std::chrono::month_day_last{std::chrono::May}); + check(loc, SV("%b='6'\t%B='6月'\t%h='6'\t%m='06'\t%Om='06'\n"), lfmt, std::chrono::month_day_last{std::chrono::June}); + check(loc, SV("%b='7'\t%B='7月'\t%h='7'\t%m='07'\t%Om='07'\n"), lfmt, std::chrono::month_day_last{std::chrono::July}); + check( + loc, SV("%b='8'\t%B='8月'\t%h='8'\t%m='08'\t%Om='08'\n"), lfmt, std::chrono::month_day_last{std::chrono::August}); + check(loc, + SV("%b='9'\t%B='9月'\t%h='9'\t%m='09'\t%Om='09'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::September}); + check(loc, + SV("%b='10'\t%B='10月'\t%h='10'\t%m='10'\t%Om='10'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::October}); + check(loc, + SV("%b='11'\t%B='11月'\t%h='11'\t%m='11'\t%Om='11'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::November}); + check(loc, + SV("%b='12'\t%B='12月'\t%h='12'\t%m='12'\t%Om='12'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::December}); +#elif defined(__APPLE__) // defined(_WIN32) + check(loc, + SV("%b=' 1'\t%B='1月'\t%h=' 1'\t%m='01'\t%Om='01'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::January}); + check(loc, + SV("%b=' 2'\t%B='2月'\t%h=' 2'\t%m='02'\t%Om='02'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::February}); + check(loc, + SV("%b=' 3'\t%B='3月'\t%h=' 3'\t%m='03'\t%Om='03'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::March}); + check(loc, + SV("%b=' 4'\t%B='4月'\t%h=' 4'\t%m='04'\t%Om='04'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::April}); + check( + loc, SV("%b=' 5'\t%B='5月'\t%h=' 5'\t%m='05'\t%Om='05'\n"), lfmt, std::chrono::month_day_last{std::chrono::May}); + check( + loc, SV("%b=' 6'\t%B='6月'\t%h=' 6'\t%m='06'\t%Om='06'\n"), lfmt, std::chrono::month_day_last{std::chrono::June}); + check( + loc, SV("%b=' 7'\t%B='7月'\t%h=' 7'\t%m='07'\t%Om='07'\n"), lfmt, std::chrono::month_day_last{std::chrono::July}); + check(loc, + SV("%b=' 8'\t%B='8月'\t%h=' 8'\t%m='08'\t%Om='08'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::August}); + check(loc, + SV("%b=' 9'\t%B='9月'\t%h=' 9'\t%m='09'\t%Om='09'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::September}); + check(loc, + SV("%b='10'\t%B='10月'\t%h='10'\t%m='10'\t%Om='10'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::October}); + check(loc, + SV("%b='11'\t%B='11月'\t%h='11'\t%m='11'\t%Om='11'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::November}); + check(loc, + SV("%b='12'\t%B='12月'\t%h='12'\t%m='12'\t%Om='12'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::December}); +#elif defined(_AIX) // defined(_WIN32) + check(loc, + SV("%b='1月'\t%B='1月'\t%h='1月'\t%m='01'\t%Om='01'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::January}); + check(loc, + SV("%b='2月'\t%B='2月'\t%h='2月'\t%m='02'\t%Om='02'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::February}); + check(loc, + SV("%b='3月'\t%B='3月'\t%h='3月'\t%m='03'\t%Om='03'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::March}); + check(loc, + SV("%b='4月'\t%B='4月'\t%h='4月'\t%m='04'\t%Om='04'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::April}); + check(loc, + SV("%b='5月'\t%B='5月'\t%h='5月'\t%m='05'\t%Om='05'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::May}); + check(loc, + SV("%b='6月'\t%B='6月'\t%h='6月'\t%m='06'\t%Om='06'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::June}); + check(loc, + SV("%b='7月'\t%B='7月'\t%h='7月'\t%m='07'\t%Om='07'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::July}); + check(loc, + SV("%b='8月'\t%B='8月'\t%h='8月'\t%m='08'\t%Om='08'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::August}); + check(loc, + SV("%b='9月'\t%B='9月'\t%h='9月'\t%m='09'\t%Om='09'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::September}); + check(loc, + SV("%b='10月'\t%B='10月'\t%h='10月'\t%m='10'\t%Om='10'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::October}); + check(loc, + SV("%b='11月'\t%B='11月'\t%h='11月'\t%m='11'\t%Om='11'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::November}); + check(loc, + SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='12'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::December}); +#else // defined(_WIN32) + check(loc, + SV("%b=' 1月'\t%B='1月'\t%h=' 1月'\t%m='01'\t%Om='一'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::January}); + check(loc, + SV("%b=' 2月'\t%B='2月'\t%h=' 2月'\t%m='02'\t%Om='二'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::February}); + check(loc, + SV("%b=' 3月'\t%B='3月'\t%h=' 3月'\t%m='03'\t%Om='三'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::March}); + check(loc, + SV("%b=' 4月'\t%B='4月'\t%h=' 4月'\t%m='04'\t%Om='四'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::April}); + check(loc, + SV("%b=' 5月'\t%B='5月'\t%h=' 5月'\t%m='05'\t%Om='五'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::May}); + check(loc, + SV("%b=' 6月'\t%B='6月'\t%h=' 6月'\t%m='06'\t%Om='六'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::June}); + check(loc, + SV("%b=' 7月'\t%B='7月'\t%h=' 7月'\t%m='07'\t%Om='七'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::July}); + check(loc, + SV("%b=' 8月'\t%B='8月'\t%h=' 8月'\t%m='08'\t%Om='八'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::August}); + check(loc, + SV("%b=' 9月'\t%B='9月'\t%h=' 9月'\t%m='09'\t%Om='九'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::September}); + check(loc, + SV("%b='10月'\t%B='10月'\t%h='10月'\t%m='10'\t%Om='十'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::October}); + check(loc, + SV("%b='11月'\t%B='11月'\t%h='11月'\t%m='11'\t%Om='十一'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::November}); + check(loc, + SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='十二'\n"), + lfmt, + std::chrono::month_day_last{std::chrono::December}); +#endif // defined(_WIN32) + + std::locale::global(std::locale::classic()); +} + +template +static void test() { + test_no_chrono_specs(); + test_valid_values(); + check_invalid_types( + {SV("b"), SV("B"), SV("h"), SV("m"), SV("Om")}, std::chrono::month_day_last{std::chrono::January}); + + check_exception( + "Expected '%' or '}' in the chrono format-string", SV("{:A"), std::chrono::month_day_last{std::chrono::January}); + check_exception("The chrono-specs contains a '{'", SV("{:%%{"), std::chrono::month_day_last{std::chrono::January}); + check_exception("End of input while parsing the modifier chrono conversion-spec", + SV("{:%"), + std::chrono::month_day_last{std::chrono::January}); + check_exception( + "End of input while parsing the modifier E", SV("{:%E"), std::chrono::month_day_last{std::chrono::January}); + check_exception( + "End of input while parsing the modifier O", SV("{:%O"), std::chrono::month_day_last{std::chrono::January}); + + // Precision not allowed + check_exception("Expected '%' or '}' in the chrono format-string", + SV("{:.3}"), + std::chrono::month_day_last{std::chrono::January}); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.syn/formatter.month_weekday.pass.cpp b/libcxx/test/std/time/time.syn/formatter.month_weekday.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.syn/formatter.month_weekday.pass.cpp @@ -0,0 +1,718 @@ +//===----------------------------------------------------------------------===// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// template struct formatter; + +#include +#include + +#include +#include +#include +#include +#include + +#include "formatter_tests.h" +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "string_literal.h" +#include "test_macros.h" + +template +static void test_no_chrono_specs() { + // Month: valid, weekday: valid, index: invalid + check(SV("Jan/Sun[0 is not a valid index]"), + SV("{}"), + std::chrono::month_weekday{std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 0}}); + check(SV("*Jan/Sun[0 is not a valid index]*"), + SV("{:*^33}"), + std::chrono::month_weekday{std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 0}}); + check(SV("*Jan/Sun[0 is not a valid index]"), + SV("{:*>32}"), + std::chrono::month_weekday{std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 0}}); + + // Month: valid, weekday: invalid, index: valid + check(SV("Jan/8 is not a valid weekday[1]"), + SV("{}"), + std::chrono::month_weekday{std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 1}}); + check(SV("*Jan/8 is not a valid weekday[1]*"), + SV("{:*^33}"), + std::chrono::month_weekday{std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 1}}); + check(SV("*Jan/8 is not a valid weekday[1]"), + SV("{:*>32}"), + std::chrono::month_weekday{std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 1}}); + + // Month: valid, weekday: invalid, index: invalid + check(SV("Jan/8 is not a valid weekday[0 is not a valid index]"), + SV("{}"), + std::chrono::month_weekday{std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}); + check(SV("*Jan/8 is not a valid weekday[0 is not a valid index]*"), + SV("{:*^54}"), + std::chrono::month_weekday{std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}); + check(SV("*Jan/8 is not a valid weekday[0 is not a valid index]"), + SV("{:*>53}"), + std::chrono::month_weekday{std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}); + + // Month: invalid, weekday: valid, index: valid + check(SV("0 is not a valid month/Sun[1]"), + SV("{}"), + std::chrono::month_weekday{std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("*0 is not a valid month/Sun[1]*"), + SV("{:*^31}"), + std::chrono::month_weekday{std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("*0 is not a valid month/Sun[1]"), + SV("{:*>30}"), + std::chrono::month_weekday{std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + + // Month: invalid, weekday: valid, index: invalid + check(SV("0 is not a valid month/Sun[0 is not a valid index]"), + SV("{}"), + std::chrono::month_weekday{std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 0}}); + check(SV("*0 is not a valid month/Sun[0 is not a valid index]*"), + SV("{:*^52}"), + std::chrono::month_weekday{std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 0}}); + check(SV("*0 is not a valid month/Sun[0 is not a valid index]"), + SV("{:*>51}"), + std::chrono::month_weekday{std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 0}}); + + // Month: invalid, weekday: invalid, index: valid + check(SV("0 is not a valid month/8 is not a valid weekday[1]"), + SV("{}"), + std::chrono::month_weekday{std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 1}}); + check(SV("*0 is not a valid month/8 is not a valid weekday[1]*"), + SV("{:*^52}"), + std::chrono::month_weekday{std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 1}}); + check(SV("*0 is not a valid month/8 is not a valid weekday[1]"), + SV("{:*>51}"), + std::chrono::month_weekday{std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 1}}); + + // Month: invalid, weekday: valid, index: invalid + check(SV("0 is not a valid month/8 is not a valid weekday[0 is not a valid index]"), + SV("{}"), + std::chrono::month_weekday{std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}); + check(SV("*0 is not a valid month/8 is not a valid weekday[0 is not a valid index]*"), + SV("{:*^73}"), + std::chrono::month_weekday{std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}); + check(SV("*0 is not a valid month/8 is not a valid weekday[0 is not a valid index]"), + SV("{:*>72}"), + std::chrono::month_weekday{std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}); +} + +template +static void test_invalid_values() { + // Test that %a, %b, %h, %a, and %B throw an exception. + check_exception( + "formatting a weekday name needs a valid weekday", + SV("{:%a}"), + std::chrono::month_weekday{std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 1}}); + check_exception( + "formatting a weekday name needs a valid weekday", + SV("{:%a}"), + std::chrono::month_weekday{std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{255}, 1}}); + + check_exception( + "formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::month_weekday{std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check_exception( + "formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::month_weekday{std::chrono::month{13}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check_exception( + "formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::month_weekday{std::chrono::month{255}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + + check_exception( + "formatting a month name from an invalid month number", + SV("{:%h}"), + std::chrono::month_weekday{std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check_exception( + "formatting a month name from an invalid month number", + SV("{:%h}"), + std::chrono::month_weekday{std::chrono::month{13}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check_exception( + "formatting a month name from an invalid month number", + SV("{:%h}"), + std::chrono::month_weekday{std::chrono::month{255}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + + check_exception( + "formatting a weekday name needs a valid weekday", + SV("{:%A}"), + std::chrono::month_weekday{std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 1}}); + check_exception( + "formatting a weekday name needs a valid weekday", + SV("{:%A}"), + std::chrono::month_weekday{std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{255}, 1}}); + + check_exception( + "formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::month_weekday{std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check_exception( + "formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::month_weekday{std::chrono::month{13}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check_exception( + "formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::month_weekday{std::chrono::month{255}, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); +} + +template +static void test_valid_month() { + constexpr std::basic_string_view fmt = SV("{:%%b='%b'%t%%B='%B'%t%%h='%h'%t%%m='%m'%t%%Om='%Om'%n}"); + constexpr std::basic_string_view lfmt = SV("{:L%%b='%b'%t%%B='%B'%t%%h='%h'%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%B='January'\t%h='Jan'\t%m='01'\t%Om='01'\n"), + fmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='Feb'\t%B='February'\t%h='Feb'\t%m='02'\t%Om='02'\n"), + fmt, + std::chrono::month_weekday{std::chrono::February, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='Mar'\t%B='March'\t%h='Mar'\t%m='03'\t%Om='03'\n"), + fmt, + std::chrono::month_weekday{std::chrono::March, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='Apr'\t%B='April'\t%h='Apr'\t%m='04'\t%Om='04'\n"), + fmt, + std::chrono::month_weekday{std::chrono::April, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='May'\t%B='May'\t%h='May'\t%m='05'\t%Om='05'\n"), + fmt, + std::chrono::month_weekday{std::chrono::May, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='Jun'\t%B='June'\t%h='Jun'\t%m='06'\t%Om='06'\n"), + fmt, + std::chrono::month_weekday{std::chrono::June, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='Jul'\t%B='July'\t%h='Jul'\t%m='07'\t%Om='07'\n"), + fmt, + std::chrono::month_weekday{std::chrono::July, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='Aug'\t%B='August'\t%h='Aug'\t%m='08'\t%Om='08'\n"), + fmt, + std::chrono::month_weekday{std::chrono::August, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='Sep'\t%B='September'\t%h='Sep'\t%m='09'\t%Om='09'\n"), + fmt, + std::chrono::month_weekday{std::chrono::September, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='Oct'\t%B='October'\t%h='Oct'\t%m='10'\t%Om='10'\n"), + fmt, + std::chrono::month_weekday{std::chrono::October, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='Nov'\t%B='November'\t%h='Nov'\t%m='11'\t%Om='11'\n"), + fmt, + std::chrono::month_weekday{std::chrono::November, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='Dec'\t%B='December'\t%h='Dec'\t%m='12'\t%Om='12'\n"), + fmt, + std::chrono::month_weekday{std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + + // Use the global locale (fr_FR) +#if defined(__APPLE__) + check(SV("%b='jan'\t%B='janvier'\t%h='jan'\t%m='01'\t%Om='01'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='fév'\t%B='février'\t%h='fév'\t%m='02'\t%Om='02'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::February, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='mar'\t%B='mars'\t%h='mar'\t%m='03'\t%Om='03'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::March, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='avr'\t%B='avril'\t%h='avr'\t%m='04'\t%Om='04'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::April, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='mai'\t%B='mai'\t%h='mai'\t%m='05'\t%Om='05'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::May, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='jui'\t%B='juin'\t%h='jui'\t%m='06'\t%Om='06'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::June, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='jul'\t%B='juillet'\t%h='jul'\t%m='07'\t%Om='07'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::July, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='aoû'\t%B='août'\t%h='aoû'\t%m='08'\t%Om='08'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::August, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='sep'\t%B='septembre'\t%h='sep'\t%m='09'\t%Om='09'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::September, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='oct'\t%B='octobre'\t%h='oct'\t%m='10'\t%Om='10'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::October, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='nov'\t%B='novembre'\t%h='nov'\t%m='11'\t%Om='11'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::November, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='déc'\t%B='décembre'\t%h='déc'\t%m='12'\t%Om='12'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); +#else // defined(__APPLE__) + check(SV("%b='janv.'\t%B='janvier'\t%h='janv.'\t%m='01'\t%Om='01'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='févr.'\t%B='février'\t%h='févr.'\t%m='02'\t%Om='02'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::February, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='mars'\t%B='mars'\t%h='mars'\t%m='03'\t%Om='03'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::March, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check( +# if defined(_WIN32) || defined(_AIX) + SV("%b='avr.'\t%B='avril'\t%h='avr.'\t%m='04'\t%Om='04'\n"), +# else // defined(_WIN32) || defined(_AIX) + SV("%b='avril'\t%B='avril'\t%h='avril'\t%m='04'\t%Om='04'\n"), +# endif // defined(_WIN32) || defined(_AIX) + lfmt, + std::chrono::month_weekday{std::chrono::April, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='mai'\t%B='mai'\t%h='mai'\t%m='05'\t%Om='05'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::May, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='juin'\t%B='juin'\t%h='juin'\t%m='06'\t%Om='06'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::June, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='juil.'\t%B='juillet'\t%h='juil.'\t%m='07'\t%Om='07'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::July, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='août'\t%B='août'\t%h='août'\t%m='08'\t%Om='08'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::August, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='sept.'\t%B='septembre'\t%h='sept.'\t%m='09'\t%Om='09'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::September, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='oct.'\t%B='octobre'\t%h='oct.'\t%m='10'\t%Om='10'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::October, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='nov.'\t%B='novembre'\t%h='nov.'\t%m='11'\t%Om='11'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::November, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%b='déc.'\t%B='décembre'\t%h='déc.'\t%m='12'\t%Om='12'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); +#endif // defined(__APPLE__) + + // Use supplied locale (ja_JP) +#ifdef _WIN32 + check(loc, + SV("%b='1'\t%B='1月'\t%h='1'\t%m='01'\t%Om='01'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='2'\t%B='2月'\t%h='2'\t%m='02'\t%Om='02'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::February, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='3'\t%B='3月'\t%h='3'\t%m='03'\t%Om='03'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::March, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='4'\t%B='4月'\t%h='4'\t%m='04'\t%Om='04'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::April, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='5'\t%B='5月'\t%h='5'\t%m='05'\t%Om='05'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::May, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='6'\t%B='6月'\t%h='6'\t%m='06'\t%Om='06'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::June, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='7'\t%B='7月'\t%h='7'\t%m='07'\t%Om='07'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::July, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='8'\t%B='8月'\t%h='8'\t%m='08'\t%Om='08'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::August, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='9'\t%B='9月'\t%h='9'\t%m='09'\t%Om='09'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::September, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='10'\t%B='10月'\t%h='10'\t%m='10'\t%Om='10'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::October, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='11'\t%B='11月'\t%h='11'\t%m='11'\t%Om='11'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::November, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='12'\t%B='12月'\t%h='12'\t%m='12'\t%Om='12'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); +#elif defined(__APPLE__) // defined(_WIN32) + check(loc, + SV("%b=' 1'\t%B='1月'\t%h=' 1'\t%m='01'\t%Om='01'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b=' 2'\t%B='2月'\t%h=' 2'\t%m='02'\t%Om='02'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::February, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b=' 3'\t%B='3月'\t%h=' 3'\t%m='03'\t%Om='03'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::March, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b=' 4'\t%B='4月'\t%h=' 4'\t%m='04'\t%Om='04'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::April, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b=' 5'\t%B='5月'\t%h=' 5'\t%m='05'\t%Om='05'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::May, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b=' 6'\t%B='6月'\t%h=' 6'\t%m='06'\t%Om='06'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::June, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b=' 7'\t%B='7月'\t%h=' 7'\t%m='07'\t%Om='07'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::July, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b=' 8'\t%B='8月'\t%h=' 8'\t%m='08'\t%Om='08'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::August, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b=' 9'\t%B='9月'\t%h=' 9'\t%m='09'\t%Om='09'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::September, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='10'\t%B='10月'\t%h='10'\t%m='10'\t%Om='10'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::October, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='11'\t%B='11月'\t%h='11'\t%m='11'\t%Om='11'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::November, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='12'\t%B='12月'\t%h='12'\t%m='12'\t%Om='12'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); +#elif defined(_AIX) // _WIN32 + check(loc, + SV("%b='1月'\t%B='1月'\t%h='1月'\t%m='01'\t%Om='01'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='2月'\t%B='2月'\t%h='2月'\t%m='02'\t%Om='02'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::February, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='3月'\t%B='3月'\t%h='3月'\t%m='03'\t%Om='03'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::March, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='4月'\t%B='4月'\t%h='4月'\t%m='04'\t%Om='04'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::April, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='5月'\t%B='5月'\t%h='5月'\t%m='05'\t%Om='05'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::May, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='6月'\t%B='6月'\t%h='6月'\t%m='06'\t%Om='06'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::June, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='7月'\t%B='7月'\t%h='7月'\t%m='07'\t%Om='07'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::July, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='8月'\t%B='8月'\t%h='8月'\t%m='08'\t%Om='08'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::August, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='9月'\t%B='9月'\t%h='9月'\t%m='09'\t%Om='09'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::September, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='10月'\t%B='10月'\t%h='10月'\t%m='10'\t%Om='10'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::October, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='11月'\t%B='11月'\t%h='11月'\t%m='11'\t%Om='11'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::November, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='12'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); +#else // _WIN32 + check(loc, + SV("%b=' 1月'\t%B='1月'\t%h=' 1月'\t%m='01'\t%Om='一'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b=' 2月'\t%B='2月'\t%h=' 2月'\t%m='02'\t%Om='二'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::February, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b=' 3月'\t%B='3月'\t%h=' 3月'\t%m='03'\t%Om='三'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::March, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b=' 4月'\t%B='4月'\t%h=' 4月'\t%m='04'\t%Om='四'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::April, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b=' 5月'\t%B='5月'\t%h=' 5月'\t%m='05'\t%Om='五'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::May, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b=' 6月'\t%B='6月'\t%h=' 6月'\t%m='06'\t%Om='六'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::June, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b=' 7月'\t%B='7月'\t%h=' 7月'\t%m='07'\t%Om='七'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::July, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b=' 8月'\t%B='8月'\t%h=' 8月'\t%m='08'\t%Om='八'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::August, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b=' 9月'\t%B='9月'\t%h=' 9月'\t%m='09'\t%Om='九'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::September, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='10月'\t%B='10月'\t%h='10月'\t%m='10'\t%Om='十'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::October, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='11月'\t%B='11月'\t%h='11月'\t%m='11'\t%Om='十一'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::November, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='十二'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); +#endif // _WIN32 + + std::locale::global(std::locale::classic()); +} + +template +static void test_valid_weekday() { + constexpr std::basic_string_view fmt = + SV("{:%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%t%%a='%a'%t%%A='%A'%n}"); + constexpr std::basic_string_view lfmt = + SV("{:L%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%t%%a='%a'%t%%A='%A'%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='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Sun'\t%A='Sunday'\n"), + fmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='Mon'\t%A='Monday'\n"), + fmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check(SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='Tue'\t%A='Tuesday'\n"), + fmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{2}, 1}}); + check(SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='Wed'\t%A='Wednesday'\n"), + fmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{3}, 1}}); + check(SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='Thu'\t%A='Thursday'\n"), + fmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); + check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='Fri'\t%A='Friday'\n"), + fmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{5}, 1}}); + check(SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='Sat'\t%A='Saturday'\n"), + fmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{6}, 1}}); + check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Sun'\t%A='Sunday'\n"), + fmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{7}, 1}}); + + // Use the global locale (fr_FR) +#if defined(__APPLE__) + check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Dim'\t%A='Dimanche'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='Lun'\t%A='Lundi'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check(SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='Mar'\t%A='Mardi'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{2}, 1}}); + check(SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='Mer'\t%A='Mercredi'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{3}, 1}}); + check(SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='Jeu'\t%A='Jeudi'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); + check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='Ven'\t%A='Vendredi'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{5}, 1}}); + check(SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='Sam'\t%A='Samedi'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{6}, 1}}); + check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Dim'\t%A='Dimanche'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{7}, 1}}); +#else // defined(__APPLE__) + check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='dim.'\t%A='dimanche'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='lun.'\t%A='lundi'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check(SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='mar.'\t%A='mardi'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{2}, 1}}); + check(SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='mer.'\t%A='mercredi'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{3}, 1}}); + check(SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='jeu.'\t%A='jeudi'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); + check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='ven.'\t%A='vendredi'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{5}, 1}}); + check(SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='sam.'\t%A='samedi'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{6}, 1}}); + check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='dim.'\t%A='dimanche'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{7}, 1}}); +#endif // defined(__APPLE__) + + // 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("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='日'\t%A='日曜日'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='月'\t%A='月曜日'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check(loc, + SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='火'\t%A='火曜日'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{2}, 1}}); + check(loc, + SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='水'\t%A='水曜日'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{3}, 1}}); + check(loc, + SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='木'\t%A='木曜日'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); + check(loc, + SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='金'\t%A='金曜日'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{5}, 1}}); + check(loc, + SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='土'\t%A='土曜日'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{6}, 1}}); + check(loc, + SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='日'\t%A='日曜日'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{7}, 1}}); +#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) + check(loc, + SV("%u='7'\t%Ou='七'\t%w='0'\t%Ow='〇'\t%a='日'\t%A='日曜日'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check(loc, + SV("%u='1'\t%Ou='一'\t%w='1'\t%Ow='一'\t%a='月'\t%A='月曜日'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check(loc, + SV("%u='2'\t%Ou='二'\t%w='2'\t%Ow='二'\t%a='火'\t%A='火曜日'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{2}, 1}}); + check(loc, + SV("%u='3'\t%Ou='三'\t%w='3'\t%Ow='三'\t%a='水'\t%A='水曜日'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{3}, 1}}); + check(loc, + SV("%u='4'\t%Ou='四'\t%w='4'\t%Ow='四'\t%a='木'\t%A='木曜日'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); + check(loc, + SV("%u='5'\t%Ou='五'\t%w='5'\t%Ow='五'\t%a='金'\t%A='金曜日'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{5}, 1}}); + check(loc, + SV("%u='6'\t%Ou='六'\t%w='6'\t%Ow='六'\t%a='土'\t%A='土曜日'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{6}, 1}}); + check(loc, + SV("%u='7'\t%Ou='七'\t%w='0'\t%Ow='〇'\t%a='日'\t%A='日曜日'\n"), + lfmt, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{7}, 1}}); +#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) + + std::locale::global(std::locale::classic()); +} + +template +static void test_valid_values() { + test_valid_month(); + test_valid_weekday(); +} + +template +static void test() { + test_no_chrono_specs(); + test_invalid_values(); + test_valid_values(); + check_invalid_types( + {SV("a"), SV("A"), SV("b"), SV("B"), SV("h"), SV("m"), SV("u"), SV("w"), SV("Om"), SV("Ou"), SV("Ow")}, + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + + check_exception( + "Expected '%' or '}' in the chrono format-string", + SV("{:A"), + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check_exception( + "The chrono-specs contains a '{'", + SV("{:%%{"), + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check_exception( + "End of input while parsing the modifier chrono conversion-spec", + SV("{:%"), + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check_exception( + "End of input while parsing the modifier E", + SV("{:%E"), + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + check_exception( + "End of input while parsing the modifier O", + SV("{:%O"), + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); + + // Precision not allowed + check_exception( + "Expected '%' or '}' in the chrono format-string", + SV("{:.3}"), + std::chrono::month_weekday{std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{0}, 1}}); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.syn/formatter.weekday_index.pass.cpp b/libcxx/test/std/time/time.syn/formatter.weekday_index.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.syn/formatter.weekday_index.pass.cpp @@ -0,0 +1,404 @@ +//===----------------------------------------------------------------------===// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// template struct formatter; + +#include +#include + +#include +#include +#include +#include +#include + +#include "formatter_tests.h" +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "test_macros.h" + +template +static void test_no_chrono_specs() { + using namespace std::literals::chrono_literals; + + // Valid weekday valid index + check(SV("Sun[1]"), SV("{}"), std::chrono::weekday_indexed{std::chrono::weekday(0), 1}); + + // Invalid weekday valid index + check(SV("8 is not a valid weekday[1]"), SV("{}"), std::chrono::weekday_indexed{std::chrono::weekday(8), 1}); + check(SV("255 is not a valid weekday[1]"), SV("{}"), std::chrono::weekday_indexed{std::chrono::weekday(255), 1}); + + // Valid weekday invalid index + check(SV("Sun[0 is not a valid index]"), SV("{}"), std::chrono::weekday_indexed{std::chrono::weekday(0), 0}); + check(SV("Sun[6 is not a valid index]"), SV("{}"), std::chrono::weekday_indexed{std::chrono::weekday(0), 6}); + check(SV("Sun[255 is not a valid index]"), SV("{}"), std::chrono::weekday_indexed{std::chrono::weekday(0), 255}); + + // Invalid weekday invalid index + check(SV("8 is not a valid weekday[0 is not a valid index]"), + SV("{}"), + std::chrono::weekday_indexed{std::chrono::weekday(8), 0}); + check(SV("127 is not a valid weekday[6 is not a valid index]"), + SV("{}"), + std::chrono::weekday_indexed{std::chrono::weekday(127), 6}); + check(SV("255 is not a valid weekday[255 is not a valid index]"), + SV("{}"), + std::chrono::weekday_indexed{std::chrono::weekday(255), 255}); +} + +template +static void test_valid_values() { + constexpr std::basic_string_view fmt = + SV("{:%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%t%%a='%a'%t%%A='%A'%n}"); + constexpr std::basic_string_view lfmt = + SV("{:L%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%t%%a='%a'%t%%A='%A'%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='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Sun'\t%A='Sunday'\n"), + fmt, + std::chrono::weekday_indexed{std::chrono::weekday(0), 0}); + check(SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='Mon'\t%A='Monday'\n"), + fmt, + std::chrono::weekday_indexed{std::chrono::weekday(1), 1}); + check(SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='Tue'\t%A='Tuesday'\n"), + fmt, + std::chrono::weekday_indexed{std::chrono::weekday(2), 2}); + check(SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='Wed'\t%A='Wednesday'\n"), + fmt, + std::chrono::weekday_indexed{std::chrono::weekday(3), 3}); + check(SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='Thu'\t%A='Thursday'\n"), + fmt, + std::chrono::weekday_indexed{std::chrono::weekday(4), 4}); + check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='Fri'\t%A='Friday'\n"), + fmt, + std::chrono::weekday_indexed{std::chrono::weekday(5), 5}); + check(SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='Sat'\t%A='Saturday'\n"), + fmt, + std::chrono::weekday_indexed{std::chrono::weekday(6), 6}); + check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Sun'\t%A='Sunday'\n"), + fmt, + std::chrono::weekday_indexed{std::chrono::weekday(7), 7}); + + // Use the global locale (fr_FR) +#if defined(__APPLE__) + check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Dim'\t%A='Dimanche'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(0), 0}); + check(SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='Lun'\t%A='Lundi'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(1), 1}); + check(SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='Mar'\t%A='Mardi'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(2), 2}); + check(SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='Mer'\t%A='Mercredi'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(3), 3}); + check(SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='Jeu'\t%A='Jeudi'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(4), 4}); + check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='Ven'\t%A='Vendredi'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(5), 5}); + check(SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='Sam'\t%A='Samedi'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(6), 6}); + check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Dim'\t%A='Dimanche'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(7), 7}); +#else // defined(__APPLE__) + check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='dim.'\t%A='dimanche'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(0), 0}); + check(SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='lun.'\t%A='lundi'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(1), 1}); + check(SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='mar.'\t%A='mardi'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(2), 2}); + check(SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='mer.'\t%A='mercredi'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(3), 3}); + check(SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='jeu.'\t%A='jeudi'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(4), 4}); + check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='ven.'\t%A='vendredi'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(5), 5}); + check(SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='sam.'\t%A='samedi'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(6), 6}); + check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='dim.'\t%A='dimanche'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(7), 7}); +#endif // defined(__APPLE__) + + // 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("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='日'\t%A='日曜日'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(0), 0}); + check(loc, + SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='月'\t%A='月曜日'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(1), 1}); + check(loc, + SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='火'\t%A='火曜日'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(2), 2}); + check(loc, + SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='水'\t%A='水曜日'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(3), 3}); + check(loc, + SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='木'\t%A='木曜日'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(4), 4}); + check(loc, + SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='金'\t%A='金曜日'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(5), 5}); + check(loc, + SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='土'\t%A='土曜日'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(6), 6}); + check(loc, + SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='日'\t%A='日曜日'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(7), 7}); +#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) + check(loc, + SV("%u='7'\t%Ou='七'\t%w='0'\t%Ow='〇'\t%a='日'\t%A='日曜日'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(0), 0}); + check(loc, + SV("%u='1'\t%Ou='一'\t%w='1'\t%Ow='一'\t%a='月'\t%A='月曜日'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(1), 1}); + check(loc, + SV("%u='2'\t%Ou='二'\t%w='2'\t%Ow='二'\t%a='火'\t%A='火曜日'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(2), 2}); + check(loc, + SV("%u='3'\t%Ou='三'\t%w='3'\t%Ow='三'\t%a='水'\t%A='水曜日'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(3), 3}); + check(loc, + SV("%u='4'\t%Ou='四'\t%w='4'\t%Ow='四'\t%a='木'\t%A='木曜日'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(4), 4}); + check(loc, + SV("%u='5'\t%Ou='五'\t%w='5'\t%Ow='五'\t%a='金'\t%A='金曜日'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(5), 5}); + check(loc, + SV("%u='6'\t%Ou='六'\t%w='6'\t%Ow='六'\t%a='土'\t%A='土曜日'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(6), 6}); + check(loc, + SV("%u='7'\t%Ou='七'\t%w='0'\t%Ow='〇'\t%a='日'\t%A='日曜日'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(7), 7}); +#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) + + std::locale::global(std::locale::classic()); +} + +template +static void test_invalid_values() { + // Test that %a and %A throw an exception. + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%a}"), + std::chrono::weekday_indexed{std::chrono::weekday(8), 1}); + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%a}"), + std::chrono::weekday_indexed{std::chrono::weekday(255), 1}); + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%A}"), + std::chrono::weekday_indexed{std::chrono::weekday(8), 1}); + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%A}"), + std::chrono::weekday_indexed{std::chrono::weekday(255), 1}); + + const std::locale loc(LOCALE_ja_JP_UTF_8); + std::locale::global(std::locale(LOCALE_fr_FR_UTF_8)); + + { // Invalid weekday, can't test %a and %A + constexpr std::basic_string_view fmt = SV("{:%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}"); + constexpr std::basic_string_view lfmt = SV("{:L%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}"); +#if defined(__APPLE__) + // Non localized output using C-locale + check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0}); + check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1}); + check(SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"), + fmt, + std::chrono::weekday_indexed{std::chrono::weekday(255), 0}); + check(SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"), + fmt, + std::chrono::weekday_indexed{std::chrono::weekday(255), 1}); + + // Use the global locale (fr_FR) + check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0}); + check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1}); + check(SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(255), 0}); + check(SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(255), 1}); + + // Use supplied locale (ja_JP). This locale has a different alternate. + check( + loc, SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0}); + check( + loc, SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1}); + check(loc, + SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(255), 0}); + check(loc, + SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(255), 1}); +#elif defined(_AIX) // defined(__APPLE__) + // Non localized output using C-locale + check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0}); + check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1}); + check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 0}); + check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 1}); + + // Use the global locale (fr_FR) + check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0}); + check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1}); + check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 0}); + check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 1}); + + // Use supplied locale (ja_JP). This locale has a different alternate. + check( + loc, SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0}); + check( + loc, SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1}); + check(loc, + SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(255), 0}); + check(loc, + SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(255), 1}); +#else // defined(__APPLE__) + // Non localized output using C-locale + check(SV("%u='1'\t%Ou='1'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0}); + check(SV("%u='1'\t%Ou='1'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1}); + check( + SV("%u='3'\t%Ou='3'\t%w='255'\t%Ow='255'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 0}); + check( + SV("%u='3'\t%Ou='3'\t%w='255'\t%Ow='255'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 1}); + + // Use the global locale (fr_FR) + check(SV("%u='1'\t%Ou='1'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 0}); + check(SV("%u='1'\t%Ou='1'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(8), 1}); + check( + SV("%u='3'\t%Ou='3'\t%w='255'\t%Ow='255'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 0}); + check( + SV("%u='3'\t%Ou='3'\t%w='255'\t%Ow='255'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(255), 1}); + + // Use supplied locale (ja_JP). This locale has a different alternate. + check(loc, + SV("%u='1'\t%Ou='一'\t%w='8'\t%Ow='八'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(8), 0}); + check(loc, + SV("%u='1'\t%Ou='一'\t%w='8'\t%Ow='八'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(8), 1}); + check(loc, + SV("%u='3'\t%Ou='三'\t%w='255'\t%Ow='255'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(255), 0}); + check(loc, + SV("%u='3'\t%Ou='三'\t%w='255'\t%Ow='255'\n"), + lfmt, + std::chrono::weekday_indexed{std::chrono::weekday(255), 1}); +#endif // defined(__APPLE__) + } + + { // Valid weekday, tests %a and %A + constexpr std::basic_string_view fmt = SV("{:%%a='%a'%t%%A='%A'%n}"); + constexpr std::basic_string_view lfmt = SV("{:L%%a='%a'%t%%A='%A'%n}"); + + // Non localized output using C-locale + check(SV("%a='Sun'\t%A='Sunday'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(0), 0}); + check(SV("%a='Sun'\t%A='Sunday'\n"), fmt, std::chrono::weekday_indexed{std::chrono::weekday(0), 6}); + + // Use the global locale (fr_FR) +#if defined(__APPLE__) + check(SV("%a='Dim'\t%A='Dimanche'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(0), 0}); + check(SV("%a='Dim'\t%A='Dimanche'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(0), 6}); +#else // defined(__APPLE__) + check(SV("%a='dim.'\t%A='dimanche'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(0), 0}); + check(SV("%a='dim.'\t%A='dimanche'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(0), 6}); +#endif // defined(__APPLE__) + + // Use supplied locale (ja_JP) + check(loc, SV("%a='日'\t%A='日曜日'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(0), 0}); + check(loc, SV("%a='日'\t%A='日曜日'\n"), lfmt, std::chrono::weekday_indexed{std::chrono::weekday(0), 6}); + } + + std::locale::global(std::locale::classic()); +} + +template +static void test() { + test_no_chrono_specs(); + test_valid_values(); + test_invalid_values(); + check_invalid_types({SV("a"), SV("A"), SV("t"), SV("u"), SV("w"), SV("Ou"), SV("Ow")}, + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}); + + check_exception("Expected '%' or '}' in the chrono format-string", + SV("{:A"), + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}); + check_exception( + "The chrono-specs contains a '{'", SV("{:%%{"), std::chrono::weekday_indexed{std::chrono::weekday(0), 1}); + check_exception("End of input while parsing the modifier chrono conversion-spec", + SV("{:%"), + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}); + check_exception("End of input while parsing the modifier E", + SV("{:%E"), + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}); + check_exception("End of input while parsing the modifier O", + SV("{:%O"), + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}); + + // Precision not allowed + check_exception("Expected '%' or '}' in the chrono format-string", + SV("{:.3}"), + std::chrono::weekday_indexed{std::chrono::weekday(0), 1}); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.syn/formatter.weekday_last.pass.cpp b/libcxx/test/std/time/time.syn/formatter.weekday_last.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.syn/formatter.weekday_last.pass.cpp @@ -0,0 +1,305 @@ +//===----------------------------------------------------------------------===// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// template struct formatter; + +#include +#include + +#include +#include +#include +#include +#include + +#include "formatter_tests.h" +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "test_macros.h" + +template +static void test_no_chrono_specs() { + using namespace std::literals::chrono_literals; + + // Valid day + check(SV("Sun[last]"), SV("{}"), std::chrono::weekday_last{std::chrono::weekday(0)}); + + // Invalid day + check(SV("8 is not a valid weekday[last]"), SV("{}"), std::chrono::weekday_last{std::chrono::weekday(8)}); +} + +template +static void test_valid_values() { + constexpr std::basic_string_view fmt = + SV("{:%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%t%%a='%a'%t%%A='%A'%n}"); + constexpr std::basic_string_view lfmt = + SV("{:L%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%t%%a='%a'%t%%A='%A'%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='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Sun'\t%A='Sunday'\n"), + fmt, + std::chrono::weekday_last{std::chrono::weekday(0)}); + check(SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='Mon'\t%A='Monday'\n"), + fmt, + std::chrono::weekday_last{std::chrono::weekday(1)}); + check(SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='Tue'\t%A='Tuesday'\n"), + fmt, + std::chrono::weekday_last{std::chrono::weekday(2)}); + check(SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='Wed'\t%A='Wednesday'\n"), + fmt, + std::chrono::weekday_last{std::chrono::weekday(3)}); + check(SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='Thu'\t%A='Thursday'\n"), + fmt, + std::chrono::weekday_last{std::chrono::weekday(4)}); + check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='Fri'\t%A='Friday'\n"), + fmt, + std::chrono::weekday_last{std::chrono::weekday(5)}); + check(SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='Sat'\t%A='Saturday'\n"), + fmt, + std::chrono::weekday_last{std::chrono::weekday(6)}); + check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Sun'\t%A='Sunday'\n"), + fmt, + std::chrono::weekday_last{std::chrono::weekday(7)}); + + // Use the global locale (fr_FR) +#if defined(__APPLE__) + check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Dim'\t%A='Dimanche'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(0)}); + check(SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='Lun'\t%A='Lundi'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(1)}); + check(SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='Mar'\t%A='Mardi'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(2)}); + check(SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='Mer'\t%A='Mercredi'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(3)}); + check(SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='Jeu'\t%A='Jeudi'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(4)}); + check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='Ven'\t%A='Vendredi'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(5)}); + check(SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='Sam'\t%A='Samedi'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(6)}); + check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='Dim'\t%A='Dimanche'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(7)}); +#else // defined(__APPLE__) + check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='dim.'\t%A='dimanche'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(0)}); + check(SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='lun.'\t%A='lundi'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(1)}); + check(SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='mar.'\t%A='mardi'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(2)}); + check(SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='mer.'\t%A='mercredi'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(3)}); + check(SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='jeu.'\t%A='jeudi'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(4)}); + check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='ven.'\t%A='vendredi'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(5)}); + check(SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='sam.'\t%A='samedi'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(6)}); + check(SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='dim.'\t%A='dimanche'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(7)}); +#endif // defined(__APPLE__) + + // 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("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='日'\t%A='日曜日'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(0)}); + check(loc, + SV("%u='1'\t%Ou='1'\t%w='1'\t%Ow='1'\t%a='月'\t%A='月曜日'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(1)}); + check(loc, + SV("%u='2'\t%Ou='2'\t%w='2'\t%Ow='2'\t%a='火'\t%A='火曜日'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(2)}); + check(loc, + SV("%u='3'\t%Ou='3'\t%w='3'\t%Ow='3'\t%a='水'\t%A='水曜日'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(3)}); + check(loc, + SV("%u='4'\t%Ou='4'\t%w='4'\t%Ow='4'\t%a='木'\t%A='木曜日'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(4)}); + check(loc, + SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\t%a='金'\t%A='金曜日'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(5)}); + check(loc, + SV("%u='6'\t%Ou='6'\t%w='6'\t%Ow='6'\t%a='土'\t%A='土曜日'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(6)}); + check(loc, + SV("%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\t%a='日'\t%A='日曜日'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(7)}); +#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) + check(loc, + SV("%u='7'\t%Ou='七'\t%w='0'\t%Ow='〇'\t%a='日'\t%A='日曜日'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(0)}); + check(loc, + SV("%u='1'\t%Ou='一'\t%w='1'\t%Ow='一'\t%a='月'\t%A='月曜日'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(1)}); + check(loc, + SV("%u='2'\t%Ou='二'\t%w='2'\t%Ow='二'\t%a='火'\t%A='火曜日'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(2)}); + check(loc, + SV("%u='3'\t%Ou='三'\t%w='3'\t%Ow='三'\t%a='水'\t%A='水曜日'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(3)}); + check(loc, + SV("%u='4'\t%Ou='四'\t%w='4'\t%Ow='四'\t%a='木'\t%A='木曜日'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(4)}); + check(loc, + SV("%u='5'\t%Ou='五'\t%w='5'\t%Ow='五'\t%a='金'\t%A='金曜日'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(5)}); + check(loc, + SV("%u='6'\t%Ou='六'\t%w='6'\t%Ow='六'\t%a='土'\t%A='土曜日'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(6)}); + check(loc, + SV("%u='7'\t%Ou='七'\t%w='0'\t%Ow='〇'\t%a='日'\t%A='日曜日'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(7)}); +#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) + + std::locale::global(std::locale::classic()); +} + +template +static void test_invalid_values() { + // Test that %a and %A throw an exception. + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%a}"), + std::chrono::weekday_last{std::chrono::weekday(8)}); + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%a}"), + std::chrono::weekday_last{std::chrono::weekday(255)}); + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%A}"), + std::chrono::weekday_last{std::chrono::weekday(8)}); + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%A}"), + std::chrono::weekday_last{std::chrono::weekday(255)}); + + constexpr std::basic_string_view fmt = SV("{:%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}"); + constexpr std::basic_string_view 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)); + +#if defined(__APPLE__) + // Non localized output using C-locale + check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_last{std::chrono::weekday(8)}); + check(SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"), fmt, std::chrono::weekday_last{std::chrono::weekday(255)}); + + // Use the global locale (fr_FR) + check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(8)}); + check(SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(255)}); + + // Use supplied locale (ja_JP). This locale has a different alternate. + check(loc, SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(8)}); + check(loc, + SV("%u='255'\t%Ou='255'\t%w='255'\t%Ow='255'\n"), + lfmt, + std::chrono::weekday_last{std::chrono::weekday(255)}); +#elif defined(_AIX) // defined(__APPLE__) + // Non localized output using C-locale + check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_last{std::chrono::weekday(8)}); + check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"), fmt, std::chrono::weekday_last{std::chrono::weekday(255)}); + + // Use the global locale (fr_FR) + check(SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(8)}); + check(SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(255)}); + + // Use supplied locale (ja_JP). This locale has a different alternate. + check(loc, SV("%u='8'\t%Ou='8'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(8)}); + check(loc, SV("%u='5'\t%Ou='5'\t%w='5'\t%Ow='5'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(255)}); +#else // defined(__APPLE__) + // Non localized output using C-locale + check(SV("%u='1'\t%Ou='1'\t%w='8'\t%Ow='8'\n"), fmt, std::chrono::weekday_last{std::chrono::weekday(8)}); + check(SV("%u='3'\t%Ou='3'\t%w='255'\t%Ow='255'\n"), fmt, std::chrono::weekday_last{std::chrono::weekday(255)}); + + // Use the global locale (fr_FR) + check(SV("%u='1'\t%Ou='1'\t%w='8'\t%Ow='8'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(8)}); + check(SV("%u='3'\t%Ou='3'\t%w='255'\t%Ow='255'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(255)}); + + // Use supplied locale (ja_JP). This locale has a different alternate. + check(loc, SV("%u='1'\t%Ou='一'\t%w='8'\t%Ow='八'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(8)}); + check(loc, SV("%u='3'\t%Ou='三'\t%w='255'\t%Ow='255'\n"), lfmt, std::chrono::weekday_last{std::chrono::weekday(255)}); +#endif // defined(__APPLE__) + + std::locale::global(std::locale::classic()); +} + +template +static void test() { + test_no_chrono_specs(); + test_valid_values(); + test_invalid_values(); + check_invalid_types({SV("a"), SV("A"), SV("t"), SV("u"), SV("w"), SV("Ou"), SV("Ow")}, + std::chrono::weekday_last{std::chrono::weekday(0)}); + + check_exception( + "Expected '%' or '}' in the chrono format-string", SV("{:A"), std::chrono::weekday_last{std::chrono::weekday(0)}); + check_exception("The chrono-specs contains a '{'", SV("{:%%{"), std::chrono::weekday_last{std::chrono::weekday(0)}); + check_exception("End of input while parsing the modifier chrono conversion-spec", + SV("{:%"), + std::chrono::weekday_last{std::chrono::weekday(0)}); + check_exception( + "End of input while parsing the modifier E", SV("{:%E"), std::chrono::weekday_last{std::chrono::weekday(0)}); + check_exception( + "End of input while parsing the modifier O", SV("{:%O"), std::chrono::weekday_last{std::chrono::weekday(0)}); + + // Precision not allowed + check_exception("Expected '%' or '}' in the chrono format-string", + SV("{:.3}"), + std::chrono::weekday_last{std::chrono::weekday(0)}); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.syn/formatter.year_month.pass.cpp b/libcxx/test/std/time/time.syn/formatter.year_month.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.syn/formatter.year_month.pass.cpp @@ -0,0 +1,285 @@ +//===----------------------------------------------------------------------===// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// template struct formatter; + +#include +#include + +#include +#include +#include +#include +#include + +#include "formatter_tests.h" +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "string_literal.h" +#include "test_macros.h" + +template +static void test_no_chrono_specs() { + // Valid month + check(SV("1970/Jan"), SV("{}"), std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{1}}); + check(SV("*1970/Jan*"), SV("{:*^10}"), std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{1}}); + check(SV("*1970/Jan"), SV("{:*>9}"), std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{1}}); + + // Invalid month_day + check(SV("1970/0 is not a valid month"), + SV("{}"), + std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{0}}); + check(SV("*1970/0 is not a valid month*"), + SV("{:*^29}"), + std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{0}}); +} + +template +static void test_invalid_values() { + // Test that %b and %B throw an exception. + check_exception("formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{0}}); + + check_exception("formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{0}}); +} + +template +static void test_valid_values() { + constexpr std::basic_string_view fmt = SV( + "{:" + "%%b='%b'%t" + "%%B='%B'%t" + "%%C='%C'%t" + "%%h='%h'%t" + "%%y='%y'%t" + "%%Y='%Y'%t" + "%%EC='%EC'%t" + "%%Ey='%Ey'%t" + "%%EY='%EY'%t" + "%%Oy='%Oy'%t" + "%n}"); + + constexpr std::basic_string_view lfmt = SV( + "{:L" + "%%b='%b'%t" + "%%B='%B'%t" + "%%C='%C'%t" + "%%h='%h'%t" + "%%y='%y'%t" + "%%Y='%Y'%t" + "%%EC='%EC'%t" + "%%Ey='%Ey'%t" + "%%EY='%EY'%t" + "%%Oy='%Oy'%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("%b='Jan'\t" + "%B='January'\t" + "%C='19'\t" + "%h='Jan'\t" + "%y='70'\t" + "%Y='1970'\t" + "%EC='19'\t" + "%Ey='70'\t" + "%EY='1970'\t" + "%Oy='70'\t" + "\n"), + fmt, + std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); + + check(SV("%b='May'\t" + "%B='May'\t" + "%C='20'\t" + "%h='May'\t" + "%y='04'\t" + "%Y='2004'\t" + "%EC='20'\t" + "%Ey='04'\t" + "%EY='2004'\t" + "%Oy='04'\t" + "\n"), + fmt, + std::chrono::year_month{std::chrono::year{2004}, std::chrono::May}); + + // Use the global locale (fr_FR) + check(SV( +#if defined(__APPLE__) + "%b='jan'\t" +#else + "%b='janv.'\t" +#endif + "%B='janvier'\t" + "%C='19'\t" +#if defined(__APPLE__) + "%h='jan'\t" +#else + "%h='janv.'\t" +#endif + "%y='70'\t" + "%Y='1970'\t" + "%EC='19'\t" + "%Ey='70'\t" + "%EY='1970'\t" + "%Oy='70'\t" + "\n"), + lfmt, + std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); + + check(SV("%b='mai'\t" + "%B='mai'\t" + "%C='20'\t" + "%h='mai'\t" + "%y='04'\t" + "%Y='2004'\t" + "%EC='20'\t" + "%Ey='04'\t" + "%EY='2004'\t" + "%Oy='04'\t" + "\n"), + lfmt, + std::chrono::year_month{std::chrono::year{2004}, std::chrono::May}); + + // Use supplied locale (ja_JP) + check(loc, + SV( +#if defined(_WIN32) + "%b='1'\t" +#elif defined(_AIX) // defined(_WIN32) + "%b='1月'\t" +#elif defined(__APPLE__) // defined(_WIN32) + "%b=' 1'\t" +#else // defined(_WIN32) + "%b=' 1月'\t" +#endif // defined(_WIN32) + "%B='1月'\t" + "%C='19'\t" +#if defined(_WIN32) + "%h='1'\t" +#elif defined(_AIX) // defined(_WIN32) + "%h='1月'\t" +#elif defined(__APPLE__) // defined(_WIN32) + "%h=' 1'\t" +#else // defined(_WIN32) + "%h=' 1月'\t" +#endif // defined(_WIN32) + "%y='70'\t" + "%Y='1970'\t" +#if defined(__APPLE__) || defined(_AIX) + "%EC='19'\t" + "%Ey='70'\t" + "%EY='1970'\t" + "%Oy='70'\t" +#else // defined(__APPLE__) || defined(_AIX) + "%EC='昭和'\t" + "%Ey='45'\t" + "%EY='昭和45年'\t" + "%Oy='七十'\t" +#endif // defined(__APPLE__) || defined(_AIX) + "\n"), + lfmt, + std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); + + check(loc, + SV( + +#if defined(_WIN32) + "%b='5'\t" +#elif defined(_AIX) // defined(_WIN32) + "%b='5月'\t" +#elif defined(__APPLE__) // defined(_WIN32) + "%b=' 5'\t" +#else // defined(_WIN32) + "%b=' 5月'\t" +#endif // defined(_WIN32) + "%B='5月'\t" + "%C='20'\t" +#if defined(_WIN32) + "%h='5'\t" +#elif defined(_AIX) // defined(_WIN32) + "%h='5月'\t" +#elif defined(__APPLE__) // defined(_WIN32) + "%h=' 5'\t" +#else // defined(_WIN32) + "%h=' 5月'\t" +#endif // defined(_WIN32) + "%y='04'\t" + "%Y='2004'\t" +#if defined(__APPLE__) || defined(_AIX) + "%EC='20'\t" + "%Ey='04'\t" + "%EY='2004'\t" + "%Oy='04'\t" +#else // defined(__APPLE__) || defined(_AIX) + "%EC='平成'\t" + "%Ey='16'\t" + "%EY='平成16年'\t" + "%Oy='四'\t" +#endif // defined(__APPLE__) || defined(_AIX) + "\n"), + lfmt, + std::chrono::year_month{std::chrono::year{2004}, std::chrono::May}); + + std::locale::global(std::locale::classic()); +} + +template +static void test() { + test_no_chrono_specs(); + test_invalid_values(); + test_valid_values(); + + check_invalid_types( + {SV("b"), SV("B"), SV("C"), SV("EC"), SV("Ey"), SV("EY"), SV("h"), SV("m"), SV("Om"), SV("Oy"), SV("y"), SV("Y")}, + std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); + + check_exception("Expected '%' or '}' in the chrono format-string", + SV("{:A"), + std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); + check_exception("The chrono-specs contains a '{'", + SV("{:%%{"), + std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); + check_exception("End of input while parsing the modifier chrono conversion-spec", + SV("{:%"), + std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); + check_exception("End of input while parsing the modifier E", + SV("{:%E"), + std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); + check_exception("End of input while parsing the modifier O", + SV("{:%O"), + std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); + + // Precision not allowed + check_exception("Expected '%' or '}' in the chrono format-string", + SV("{:.3}"), + std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.syn/formatter.year_month_day.pass.cpp b/libcxx/test/std/time/time.syn/formatter.year_month_day.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.syn/formatter.year_month_day.pass.cpp @@ -0,0 +1,1074 @@ +//===----------------------------------------------------------------------===// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// template struct formatter; + +#include +#include + +#include +#include +#include +#include +#include + +#include "formatter_tests.h" +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "string_literal.h" +#include "test_macros.h" + +template +static void test_no_chrono_specs() { + // Valid year, valid month, valid day + check(SV("1970-01-31"), + SV("{}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{31}}); + check(SV("*1970-01-31*"), + SV("{:*^12}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{31}}); + check(SV("*1970-01-31"), + SV("{:*>11}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{31}}); + + // Valid year, valid month, invalid day + check(SV("1970-02-31 is not a valid date"), + SV("{}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{31}}); + check(SV("*1970-02-31 is not a valid date*"), + SV("{:*^32}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{31}}); + check(SV("*1970-02-31 is not a valid date"), + SV("{:*>31}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{31}}); + + // Valid year, invalid month, valid day + check(SV("1970-00-31 is not a valid date"), + SV("{}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + check(SV("*1970-00-31 is not a valid date*"), + SV("{:*^32}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + check(SV("*1970-00-31 is not a valid date"), + SV("{:*>31}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + + // Valid year, invalid month, invalid day + check(SV("1970-00-32 is not a valid date"), + SV("{}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{32}}); + check(SV("*1970-00-32 is not a valid date*"), + SV("{:*^32}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{32}}); + check(SV("*1970-00-32 is not a valid date"), + SV("{:*>31}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{32}}); + + // Invalid year, valid month, valid day + check(SV("-32768-01-31 is not a valid date"), + SV("{}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{31}}); + check(SV("*-32768-01-31 is not a valid date*"), + SV("{:*^34}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{31}}); + check(SV("*-32768-01-31 is not a valid date"), + SV("{:*>33}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{31}}); + + // Invalid year, valid month, invalid day + check(SV("-32768-01-32 is not a valid date"), + SV("{}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{32}}); + check(SV("*-32768-01-32 is not a valid date*"), + SV("{:*^34}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{32}}); + check(SV("*-32768-01-32 is not a valid date"), + SV("{:*>33}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{32}}); + + // Invalid year, invalid month, valid day + check(SV("-32768-00-31 is not a valid date"), + SV("{}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{0}, std::chrono::day{31}}); + check(SV("*-32768-00-31 is not a valid date*"), + SV("{:*^34}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{0}, std::chrono::day{31}}); + check(SV("*-32768-00-31 is not a valid date"), + SV("{:*>33}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{0}, std::chrono::day{31}}); + + // Invalid year, invalid month, invalid day + check(SV("-32768-00-32 is not a valid date"), + SV("{}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{0}, std::chrono::day{32}}); + check(SV("*-32768-00-32 is not a valid date*"), + SV("{:*^34}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{0}, std::chrono::day{32}}); + check(SV("*-32768-00-32 is not a valid date"), + SV("{:*>33}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{0}, std::chrono::day{32}}); +} + +// TODO FMT Should x throw? +template +static void test_invalid_values() { + // Test that %a, %A, %b, %B, %h, %j, %u, %U, %V, %w, %W, %Ou, %OU, %OV, %Ow, and %OW throw an exception. + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%A}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%A}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{32}}); + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%A}"), + std::chrono::year_month_day{ + std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{29}}); // not a leap year + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%A}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%A}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{31}}); + + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%a}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%a}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{32}}); + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%a}"), + std::chrono::year_month_day{ + std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{29}}); // not a leap year + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%a}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + check_exception("formatting a weekday name needs a valid weekday", + SV("{:%a}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{31}}); + + check_exception("formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{13}, std::chrono::day{31}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{255}, std::chrono::day{31}}); + + check_exception("formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{200}, std::chrono::day{31}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{13}, std::chrono::day{31}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{255}, std::chrono::day{31}}); + + check_exception("formatting a month name from an invalid month number", + SV("{:%h}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%h}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{13}, std::chrono::day{31}}); + check_exception("formatting a month name from an invalid month number", + SV("{:%h}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{255}, std::chrono::day{31}}); + + check_exception("formatting a day of year needs a valid date", + SV("{:%j}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + check_exception("formatting a day of year needs a valid date", + SV("{:%j}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{32}}); + check_exception("formatting a day of year needs a valid date", + SV("{:%j}"), + std::chrono::year_month_day{ + std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{29}}); // not a leap year + check_exception("formatting a day of year needs a valid date", + SV("{:%j}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + check_exception("formatting a day of year needs a valid date", + SV("{:%j}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{31}}); + + check_exception("formatting a weekday needs a valid weekday", + SV("{:%u}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + check_exception("formatting a weekday needs a valid weekday", + SV("{:%u}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{32}}); + check_exception("formatting a weekday needs a valid weekday", + SV("{:%u}"), + std::chrono::year_month_day{ + std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{29}}); // not a leap year + check_exception("formatting a weekday needs a valid weekday", + SV("{:%u}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + check_exception("formatting a weekday needs a valid weekday", + SV("{:%u}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{31}}); + + check_exception("formatting a week of year needs a valid date", + SV("{:%U}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%U}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{32}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%U}"), + std::chrono::year_month_day{ + std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{29}}); // not a leap year + check_exception("formatting a week of year needs a valid date", + SV("{:%U}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%U}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{31}}); + + check_exception("formatting a week of year needs a valid date", + SV("{:%V}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%V}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{32}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%V}"), + std::chrono::year_month_day{ + std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{29}}); // not a leap year + check_exception("formatting a week of year needs a valid date", + SV("{:%V}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%V}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{31}}); + + check_exception("formatting a weekday needs a valid weekday", + SV("{:%w}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + check_exception("formatting a weekday needs a valid weekday", + SV("{:%w}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{32}}); + check_exception("formatting a weekday needs a valid weekday", + SV("{:%w}"), + std::chrono::year_month_day{ + std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{29}}); // not a leap year + check_exception("formatting a weekday needs a valid weekday", + SV("{:%w}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + check_exception("formatting a weekday needs a valid weekday", + SV("{:%w}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{31}}); + + check_exception("formatting a week of year needs a valid date", + SV("{:%W}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%W}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{32}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%W}"), + std::chrono::year_month_day{ + std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{29}}); // not a leap year + check_exception("formatting a week of year needs a valid date", + SV("{:%W}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%W}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{31}}); + + check_exception("formatting a weekday needs a valid weekday", + SV("{:%Ou}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + check_exception("formatting a weekday needs a valid weekday", + SV("{:%Ou}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{32}}); + check_exception("formatting a weekday needs a valid weekday", + SV("{:%Ou}"), + std::chrono::year_month_day{ + std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{29}}); // not a leap year + check_exception("formatting a weekday needs a valid weekday", + SV("{:%Ou}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + check_exception("formatting a weekday needs a valid weekday", + SV("{:%Ou}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{31}}); + + check_exception("formatting a week of year needs a valid date", + SV("{:%OU}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%OU}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{32}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%OU}"), + std::chrono::year_month_day{ + std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{29}}); // not a leap year + check_exception("formatting a week of year needs a valid date", + SV("{:%OU}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%OU}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{31}}); + + check_exception("formatting a week of year needs a valid date", + SV("{:%OV}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%OV}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{32}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%OV}"), + std::chrono::year_month_day{ + std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{29}}); // not a leap year + check_exception("formatting a week of year needs a valid date", + SV("{:%OV}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%OV}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{31}}); + + check_exception("formatting a weekday needs a valid weekday", + SV("{:%Ow}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + check_exception("formatting a weekday needs a valid weekday", + SV("{:%Ow}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{32}}); + check_exception("formatting a weekday needs a valid weekday", + SV("{:%Ow}"), + std::chrono::year_month_day{ + std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{29}}); // not a leap year + check_exception("formatting a weekday needs a valid weekday", + SV("{:%Ow}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + check_exception("formatting a weekday needs a valid weekday", + SV("{:%Ow}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{31}}); + + check_exception("formatting a week of year needs a valid date", + SV("{:%OW}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%OW}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{32}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%OW}"), + std::chrono::year_month_day{ + std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{29}}); // not a leap year + check_exception("formatting a week of year needs a valid date", + SV("{:%OW}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}}); + check_exception("formatting a week of year needs a valid date", + SV("{:%OW}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{31}}); +} + +template +static void test_valid_md_values() { + constexpr std::basic_string_view fmt = + SV("{:%%b='%b'%t%%B='%B'%t%%h='%h'%t%%m='%m'%t%%Om='%Om'%t%%d='%d'%t%%e='%e'%t%%Od='%Od'%t%%Oe='%Oe'%n}"); + constexpr std::basic_string_view lfmt = + SV("{:L%%b='%b'%t%%B='%B'%t%%h='%h'%t%%m='%m'%t%%Om='%Om'%t%%d='%d'%t%%e='%e'%t%%Od='%Od'%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("%b='Jan'\t%B='January'\t%h='Jan'\t%m='01'\t%Om='01'\t%d='00'\t%e=' 0'\t%Od='00'\t%Oe=' 0'\n"), + fmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::January, std::chrono::day{0}}); + check(SV("%b='Feb'\t%B='February'\t%h='Feb'\t%m='02'\t%Om='02'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), + fmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::February, std::chrono::day{1}}); + check(SV("%b='Mar'\t%B='March'\t%h='Mar'\t%m='03'\t%Om='03'\t%d='09'\t%e=' 9'\t%Od='09'\t%Oe=' 9'\n"), + fmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::March, std::chrono::day{9}}); + check(SV("%b='Apr'\t%B='April'\t%h='Apr'\t%m='04'\t%Om='04'\t%d='10'\t%e='10'\t%Od='10'\t%Oe='10'\n"), + fmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::April, std::chrono::day{10}}); + check(SV("%b='May'\t%B='May'\t%h='May'\t%m='05'\t%Om='05'\t%d='28'\t%e='28'\t%Od='28'\t%Oe='28'\n"), + fmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::May, std::chrono::day{28}}); + check(SV("%b='Jun'\t%B='June'\t%h='Jun'\t%m='06'\t%Om='06'\t%d='29'\t%e='29'\t%Od='29'\t%Oe='29'\n"), + fmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::June, std::chrono::day{29}}); + check(SV("%b='Jul'\t%B='July'\t%h='Jul'\t%m='07'\t%Om='07'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + fmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::July, std::chrono::day{30}}); + check(SV("%b='Aug'\t%B='August'\t%h='Aug'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + fmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::August, std::chrono::day{31}}); + check(SV("%b='Sep'\t%B='September'\t%h='Sep'\t%m='09'\t%Om='09'\t%d='32'\t%e='32'\t%Od='32'\t%Oe='32'\n"), + fmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::September, std::chrono::day{32}}); + check(SV("%b='Oct'\t%B='October'\t%h='Oct'\t%m='10'\t%Om='10'\t%d='99'\t%e='99'\t%Od='99'\t%Oe='99'\n"), + fmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::October, std::chrono::day{99}}); +#if defined(_AIX) + check(SV("%b='Nov'\t%B='November'\t%h='Nov'\t%m='11'\t%Om='11'\t%d='00'\t%e=' 0'\t%Od='00'\t%Oe=' 0'\n"), + fmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::November, std::chrono::day{100}}); + check(SV("%b='Dec'\t%B='December'\t%h='Dec'\t%m='12'\t%Om='12'\t%d='55'\t%e='55'\t%Od='55'\t%Oe='55'\n"), + fmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::December, std::chrono::day{255}}); +#else // defined(_AIX) + check(SV("%b='Nov'\t%B='November'\t%h='Nov'\t%m='11'\t%Om='11'\t%d='100'\t%e='100'\t%Od='100'\t%Oe='100'\n"), + fmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::November, std::chrono::day{100}}); + check(SV("%b='Dec'\t%B='December'\t%h='Dec'\t%m='12'\t%Om='12'\t%d='255'\t%e='255'\t%Od='255'\t%Oe='255'\n"), + fmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::December, std::chrono::day{255}}); +#endif // defined(_AIX) + + // Use the global locale (fr_FR) +#if defined(__APPLE__) + check(SV("%b='jan'\t%B='janvier'\t%h='jan'\t%m='01'\t%Om='01'\t%d='00'\t%e=' 0'\t%Od='00'\t%Oe=' 0'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::January, std::chrono::day{0}}); + check(SV("%b='fév'\t%B='février'\t%h='fév'\t%m='02'\t%Om='02'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::February, std::chrono::day{1}}); + check(SV("%b='mar'\t%B='mars'\t%h='mar'\t%m='03'\t%Om='03'\t%d='09'\t%e=' 9'\t%Od='09'\t%Oe=' 9'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::March, std::chrono::day{9}}); + check(SV("%b='avr'\t%B='avril'\t%h='avr'\t%m='04'\t%Om='04'\t%d='10'\t%e='10'\t%Od='10'\t%Oe='10'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::April, std::chrono::day{10}}); + check(SV("%b='mai'\t%B='mai'\t%h='mai'\t%m='05'\t%Om='05'\t%d='28'\t%e='28'\t%Od='28'\t%Oe='28'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::May, std::chrono::day{28}}); + check(SV("%b='jui'\t%B='juin'\t%h='jui'\t%m='06'\t%Om='06'\t%d='29'\t%e='29'\t%Od='29'\t%Oe='29'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::June, std::chrono::day{29}}); + check(SV("%b='jul'\t%B='juillet'\t%h='jul'\t%m='07'\t%Om='07'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::July, std::chrono::day{30}}); + check(SV("%b='aoû'\t%B='août'\t%h='aoû'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::August, std::chrono::day{31}}); + check(SV("%b='sep'\t%B='septembre'\t%h='sep'\t%m='09'\t%Om='09'\t%d='32'\t%e='32'\t%Od='32'\t%Oe='32'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::September, std::chrono::day{32}}); + check(SV("%b='oct'\t%B='octobre'\t%h='oct'\t%m='10'\t%Om='10'\t%d='99'\t%e='99'\t%Od='99'\t%Oe='99'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::October, std::chrono::day{99}}); + check(SV("%b='nov'\t%B='novembre'\t%h='nov'\t%m='11'\t%Om='11'\t%d='100'\t%e='100'\t%Od='100'\t%Oe='100'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::November, std::chrono::day{100}}); + check(SV("%b='déc'\t%B='décembre'\t%h='déc'\t%m='12'\t%Om='12'\t%d='255'\t%e='255'\t%Od='255'\t%Oe='255'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::December, std::chrono::day{255}}); +#else // defined(__APPLE__) + check(SV("%b='janv.'\t%B='janvier'\t%h='janv.'\t%m='01'\t%Om='01'\t%d='00'\t%e=' 0'\t%Od='00'\t%Oe=' 0'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::January, std::chrono::day{0}}); + check(SV("%b='févr.'\t%B='février'\t%h='févr.'\t%m='02'\t%Om='02'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::February, std::chrono::day{1}}); + check(SV("%b='mars'\t%B='mars'\t%h='mars'\t%m='03'\t%Om='03'\t%d='09'\t%e=' 9'\t%Od='09'\t%Oe=' 9'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::March, std::chrono::day{9}}); + check( +# if defined(_WIN32) || defined(_AIX) + SV("%b='avr.'\t%B='avril'\t%h='avr.'\t%m='04'\t%Om='04'\t%d='10'\t%e='10'\t%Od='10'\t%Oe='10'\n"), +# else // defined(_WIN32) || defined(_AIX) + SV("%b='avril'\t%B='avril'\t%h='avril'\t%m='04'\t%Om='04'\t%d='10'\t%e='10'\t%Od='10'\t%Oe='10'\n"), +# endif // defined(_WIN32) || defined(_AIX) + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::April, std::chrono::day{10}}); + check(SV("%b='mai'\t%B='mai'\t%h='mai'\t%m='05'\t%Om='05'\t%d='28'\t%e='28'\t%Od='28'\t%Oe='28'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::May, std::chrono::day{28}}); + check(SV("%b='juin'\t%B='juin'\t%h='juin'\t%m='06'\t%Om='06'\t%d='29'\t%e='29'\t%Od='29'\t%Oe='29'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::June, std::chrono::day{29}}); + check(SV("%b='juil.'\t%B='juillet'\t%h='juil.'\t%m='07'\t%Om='07'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::July, std::chrono::day{30}}); + check(SV("%b='août'\t%B='août'\t%h='août'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::August, std::chrono::day{31}}); + check(SV("%b='sept.'\t%B='septembre'\t%h='sept.'\t%m='09'\t%Om='09'\t%d='32'\t%e='32'\t%Od='32'\t%Oe='32'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::September, std::chrono::day{32}}); + check(SV("%b='oct.'\t%B='octobre'\t%h='oct.'\t%m='10'\t%Om='10'\t%d='99'\t%e='99'\t%Od='99'\t%Oe='99'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::October, std::chrono::day{99}}); +# if defined(_AIX) + check(SV("%b='nov.'\t%B='novembre'\t%h='nov.'\t%m='11'\t%Om='11'\t%d='00'\t%e=' 0'\t%Od='00'\t%Oe=' 0'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::November, std::chrono::day{100}}); + check(SV("%b='déc.'\t%B='décembre'\t%h='déc.'\t%m='12'\t%Om='12'\t%d='55'\t%e='55'\t%Od='55'\t%Oe='55'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::December, std::chrono::day{255}}); +# else // defined(_AIX) + check(SV("%b='nov.'\t%B='novembre'\t%h='nov.'\t%m='11'\t%Om='11'\t%d='100'\t%e='100'\t%Od='100'\t%Oe='100'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::November, std::chrono::day{100}}); + check(SV("%b='déc.'\t%B='décembre'\t%h='déc.'\t%m='12'\t%Om='12'\t%d='255'\t%e='255'\t%Od='255'\t%Oe='255'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::December, std::chrono::day{255}}); +# endif // defined(_AIX) +#endif // defined(__APPLE__) + + // Use supplied locale (ja_JP) +#if defined(_WIN32) + check(loc, + SV("%b='1'\t%B='1月'\t%h='1'\t%m='01'\t%Om='01'\t%d='00'\t%e=' 0'\t%Od='〇'\t%Oe='〇'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::January, std::chrono::day{0}}); + check(loc, + SV("%b='2'\t%B='2月'\t%h='2'\t%m='02'\t%Om='02'\t%d='01'\t%e=' 1'\t%Od='一'\t%Oe='一'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::February, std::chrono::day{1}}); + check(loc, + SV("%b='3'\t%B='3月'\t%h='3'\t%m='03'\t%Om='03'\t%d='09'\t%e=' 9'\t%Od='九'\t%Oe='九'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::March, std::chrono::day{9}}); + check(loc, + SV("%b='4'\t%B='4月'\t%h='4'\t%m='04'\t%Om='04'\t%d='10'\t%e='10'\t%Od='十'\t%Oe='十'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::April, std::chrono::day{10}}); + check(loc, + SV("%b='5'\t%B='5月'\t%h='5'\t%m='05'\t%Om='05'\t%d='28'\t%e='28'\t%Od='二十八'\t%Oe='二十八'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::May, std::chrono::day{28}}); + check(loc, + SV("%b='6'\t%B='6月'\t%h='6'\t%m='06'\t%Om='06'\t%d='29'\t%e='29'\t%Od='二十九'\t%Oe='二十九'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::June, std::chrono::day{29}}); + check(loc, + SV("%b='7'\t%B='7月'\t%h='7'\t%m='07'\t%Om='07'\t%d='30'\t%e='30'\t%Od='三十'\t%Oe='三十'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::July, std::chrono::day{30}}); + check(loc, + SV("%b='8'\t%B='8月'\t%h='8'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='三十一'\t%Oe='三十一'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::August, std::chrono::day{31}}); + check(loc, + SV("%b='9'\t%B='9月'\t%h='9'\t%m='09'\t%Om='09'\t%d='32'\t%e='32'\t%Od='三十二'\t%Oe='三十二'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::September, std::chrono::day{32}}); + check(loc, + SV("%b='10'\t%B='10月'\t%h='10'\t%m='10'\t%Om='10'\t%d='99'\t%e='99'\t%Od='九十九'\t%Oe='九十九'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::October, std::chrono::day{99}}); + check(loc, + SV("%b='11'\t%B='11月'\t%h='11'\t%m='11'\t%Om='11'\t%d='100'\t%e='100'\t%Od='100'\t%Oe='100'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::November, std::chrono::day{100}}); + check(loc, + SV("%b='12'\t%B='12月'\t%h='12'\t%m='12'\t%Om='12'\t%d='255'\t%e='255'\t%Od='255'\t%Oe='255'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::December, std::chrono::day{255}}); +#elif defined(_AIX) // defined(_WIN32) + check(loc, + SV("%b='1月'\t%B='1月'\t%h='1月'\t%m='01'\t%Om='01'\t%d='00'\t%e=' 0'\t%Od='00'\t%Oe=' 0'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::January, std::chrono::day{0}}); + check(loc, + SV("%b='2月'\t%B='2月'\t%h='2月'\t%m='02'\t%Om='02'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::February, std::chrono::day{1}}); + check(loc, + SV("%b='3月'\t%B='3月'\t%h='3月'\t%m='03'\t%Om='03'\t%d='09'\t%e=' 9'\t%Od='09'\t%Oe=' 9'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::March, std::chrono::day{9}}); + check(loc, + SV("%b='4月'\t%B='4月'\t%h='4月'\t%m='04'\t%Om='04'\t%d='10'\t%e='10'\t%Od='10'\t%Oe='10'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::April, std::chrono::day{10}}); + check(loc, + SV("%b='5月'\t%B='5月'\t%h='5月'\t%m='05'\t%Om='05'\t%d='28'\t%e='28'\t%Od='28'\t%Oe='28'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::May, std::chrono::day{28}}); + check(loc, + SV("%b='6月'\t%B='6月'\t%h='6月'\t%m='06'\t%Om='06'\t%d='29'\t%e='29'\t%Od='29'\t%Oe='29'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::June, std::chrono::day{29}}); + check(loc, + SV("%b='7月'\t%B='7月'\t%h='7月'\t%m='07'\t%Om='07'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::July, std::chrono::day{30}}); + check(loc, + SV("%b='8月'\t%B='8月'\t%h='8月'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::August, std::chrono::day{31}}); + check(loc, + SV("%b='9月'\t%B='9月'\t%h='9月'\t%m='09'\t%Om='09'\t%d='32'\t%e='32'\t%Od='32'\t%Oe='32'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::September, std::chrono::day{32}}); + check(loc, + SV("%b='10月'\t%B='10月'\t%h='10月'\t%m='10'\t%Om='10'\t%d='99'\t%e='99'\t%Od='99'\t%Oe='99'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::October, std::chrono::day{99}}); + check(loc, + SV("%b='11月'\t%B='11月'\t%h='11月'\t%m='11'\t%Om='11'\t%d='00'\t%e=' 0'\t%Od='00'\t%Oe=' 0'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::November, std::chrono::day{100}}); + check(loc, + SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='12'\t%d='55'\t%e='55'\t%Od='55'\t%Oe='55'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::December, std::chrono::day{255}}); +#elif defined(__APPLE__) // defined(_WIN32) + check(loc, + SV("%b=' 1'\t%B='1月'\t%h=' 1'\t%m='01'\t%Om='01'\t%d='00'\t%e=' 0'\t%Od='00'\t%Oe=' 0'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::January, std::chrono::day{0}}); + check(loc, + SV("%b=' 2'\t%B='2月'\t%h=' 2'\t%m='02'\t%Om='02'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::February, std::chrono::day{1}}); + check(loc, + SV("%b=' 3'\t%B='3月'\t%h=' 3'\t%m='03'\t%Om='03'\t%d='09'\t%e=' 9'\t%Od='09'\t%Oe=' 9'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::March, std::chrono::day{9}}); + check(loc, + SV("%b=' 4'\t%B='4月'\t%h=' 4'\t%m='04'\t%Om='04'\t%d='10'\t%e='10'\t%Od='10'\t%Oe='10'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::April, std::chrono::day{10}}); + check(loc, + SV("%b=' 5'\t%B='5月'\t%h=' 5'\t%m='05'\t%Om='05'\t%d='28'\t%e='28'\t%Od='28'\t%Oe='28'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::May, std::chrono::day{28}}); + check(loc, + SV("%b=' 6'\t%B='6月'\t%h=' 6'\t%m='06'\t%Om='06'\t%d='29'\t%e='29'\t%Od='29'\t%Oe='29'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::June, std::chrono::day{29}}); + check(loc, + SV("%b=' 7'\t%B='7月'\t%h=' 7'\t%m='07'\t%Om='07'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::July, std::chrono::day{30}}); + check(loc, + SV("%b=' 8'\t%B='8月'\t%h=' 8'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::August, std::chrono::day{31}}); + check(loc, + SV("%b=' 9'\t%B='9月'\t%h=' 9'\t%m='09'\t%Om='09'\t%d='32'\t%e='32'\t%Od='32'\t%Oe='32'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::September, std::chrono::day{32}}); + check(loc, + SV("%b='10'\t%B='10月'\t%h='10'\t%m='10'\t%Om='10'\t%d='99'\t%e='99'\t%Od='99'\t%Oe='99'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::October, std::chrono::day{99}}); + check(loc, + SV("%b='11'\t%B='11月'\t%h='11'\t%m='11'\t%Om='11'\t%d='100'\t%e='100'\t%Od='100'\t%Oe='100'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::November, std::chrono::day{100}}); + check(loc, + SV("%b='12'\t%B='12月'\t%h='12'\t%m='12'\t%Om='12'\t%d='255'\t%e='255'\t%Od='255'\t%Oe='255'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::December, std::chrono::day{255}}); +#else // defined(_WIN32) + check(loc, + SV("%b=' 1月'\t%B='1月'\t%h=' 1月'\t%m='01'\t%Om='一'\t%d='00'\t%e=' 0'\t%Od='〇'\t%Oe='〇'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::January, std::chrono::day{0}}); + check(loc, + SV("%b=' 2月'\t%B='2月'\t%h=' 2月'\t%m='02'\t%Om='二'\t%d='01'\t%e=' 1'\t%Od='一'\t%Oe='一'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::February, std::chrono::day{1}}); + check(loc, + SV("%b=' 3月'\t%B='3月'\t%h=' 3月'\t%m='03'\t%Om='三'\t%d='09'\t%e=' 9'\t%Od='九'\t%Oe='九'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::March, std::chrono::day{9}}); + check(loc, + SV("%b=' 4月'\t%B='4月'\t%h=' 4月'\t%m='04'\t%Om='四'\t%d='10'\t%e='10'\t%Od='十'\t%Oe='十'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::April, std::chrono::day{10}}); + check(loc, + SV("%b=' 5月'\t%B='5月'\t%h=' 5月'\t%m='05'\t%Om='五'\t%d='28'\t%e='28'\t%Od='二十八'\t%Oe='二十八'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::May, std::chrono::day{28}}); + check(loc, + SV("%b=' 6月'\t%B='6月'\t%h=' 6月'\t%m='06'\t%Om='六'\t%d='29'\t%e='29'\t%Od='二十九'\t%Oe='二十九'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::June, std::chrono::day{29}}); + check(loc, + SV("%b=' 7月'\t%B='7月'\t%h=' 7月'\t%m='07'\t%Om='七'\t%d='30'\t%e='30'\t%Od='三十'\t%Oe='三十'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::July, std::chrono::day{30}}); + check(loc, + SV("%b=' 8月'\t%B='8月'\t%h=' 8月'\t%m='08'\t%Om='八'\t%d='31'\t%e='31'\t%Od='三十一'\t%Oe='三十一'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::August, std::chrono::day{31}}); + check(loc, + SV("%b=' 9月'\t%B='9月'\t%h=' 9月'\t%m='09'\t%Om='九'\t%d='32'\t%e='32'\t%Od='三十二'\t%Oe='三十二'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::September, std::chrono::day{32}}); + check(loc, + SV("%b='10月'\t%B='10月'\t%h='10月'\t%m='10'\t%Om='十'\t%d='99'\t%e='99'\t%Od='九十九'\t%Oe='九十九'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::October, std::chrono::day{99}}); + check(loc, + SV("%b='11月'\t%B='11月'\t%h='11月'\t%m='11'\t%Om='十一'\t%d='100'\t%e='100'\t%Od='100'\t%Oe='100'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::November, std::chrono::day{100}}); + check(loc, + SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='十二'\t%d='255'\t%e='255'\t%Od='255'\t%Oe='255'\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::December, std::chrono::day{255}}); +#endif // defined(_WIN32) + + std::locale::global(std::locale::classic()); +} + +template +static void test_valid_ymd_values() { + constexpr std::basic_string_view fmt = SV( + "{:" + "%%C='%C'%t" + "%%D='%D'%t" + "%%F='%F'%t" + "%%j='%j'%t" + "%%g='%g'%t" + "%%G='%G'%t" + "%%u='%u'%t" + "%%U='%U'%t" + "%%V='%V'%t" + "%%w='%w'%t" + "%%W='%W'%t" + "%%x='%x'%t" + "%%y='%y'%t" + "%%Y='%Y'%t" + "%%Ex='%Ex'%t" + "%%EC='%EC'%t" + "%%Ey='%Ey'%t" + "%%EY='%EY'%t" + "%%Ou='%Ou'%t" + "%%OU='%OU'%t" + "%%OV='%OV'%t" + "%%Ow='%Ow'%t" + "%%OW='%OW'%t" + "%%Oy='%Oy'%t" + "%n}"); + + constexpr std::basic_string_view lfmt = SV( + "{:L" + "%%C='%C'%t" + "%%D='%D'%t" + "%%F='%F'%t" + "%%j='%j'%t" + "%%g='%g'%t" + "%%G='%G'%t" + "%%u='%u'%t" + "%%U='%U'%t" + "%%V='%V'%t" + "%%w='%w'%t" + "%%W='%W'%t" + "%%x='%x'%t" + "%%y='%y'%t" + "%%Y='%Y'%t" + "%%Ex='%Ex'%t" + "%%EC='%EC'%t" + "%%Ey='%Ey'%t" + "%%EY='%EY'%t" + "%%Ou='%Ou'%t" + "%%OU='%OU'%t" + "%%OV='%OV'%t" + "%%Ow='%Ow'%t" + "%%OW='%OW'%t" + "%%Oy='%Oy'%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("%C='19'\t" + "%D='01/01/70'\t" + "%F='1970-01-01'\t" + "%j='001'\t" + "%g='70'\t" + "%G='1970'\t" + "%u='4'\t" + "%U='00'\t" + "%V='01'\t" + "%w='4'\t" + "%W='00'\t" + "%x='01/01/70'\t" + "%y='70'\t" + "%Y='1970'\t" + "%Ex='01/01/70'\t" + "%EC='19'\t" + "%Ey='70'\t" + "%EY='1970'\t" + "%Ou='4'\t" + "%OU='00'\t" + "%OV='01'\t" + "%Ow='4'\t" + "%OW='00'\t" + "%Oy='70'\t" + "\n"), + fmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::January, std::chrono::day{1}}); + + check( + SV("%C='20'\t" + "%D='05/29/04'\t" + "%F='2004-05-29'\t" + "%j='150'\t" + "%g='04'\t" + "%G='2004'\t" + "%u='6'\t" + "%U='21'\t" + "%V='22'\t" + "%w='6'\t" + "%W='21'\t" + "%x='05/29/04'\t" + "%y='04'\t" + "%Y='2004'\t" + "%Ex='05/29/04'\t" + "%EC='20'\t" + "%Ey='04'\t" + "%EY='2004'\t" + "%Ou='6'\t" + "%OU='21'\t" + "%OV='22'\t" + "%Ow='6'\t" + "%OW='21'\t" + "%Oy='04'\t" + "\n"), + fmt, + std::chrono::year_month_day{std::chrono::year{2004}, std::chrono::May, std::chrono::day{29}}); + + // Use the global locale (fr_FR) + check( + SV("%C='19'\t" + "%D='01/01/70'\t" + "%F='1970-01-01'\t" + "%j='001'\t" + "%g='70'\t" + "%G='1970'\t" + "%u='4'\t" + "%U='00'\t" + "%V='01'\t" + "%w='4'\t" + "%W='00'\t" +#if defined(__APPLE__) + "%x='01.01.1970'\t" +#else + "%x='01/01/1970'\t" +#endif + "%y='70'\t" + "%Y='1970'\t" +#if defined(__APPLE__) + "%Ex='01.01.1970'\t" +#else + "%Ex='01/01/1970'\t" +#endif + "%EC='19'\t" + "%Ey='70'\t" + "%EY='1970'\t" + "%Ou='4'\t" + "%OU='00'\t" + "%OV='01'\t" + "%Ow='4'\t" + "%OW='00'\t" + "%Oy='70'\t" + "\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::January, std::chrono::day{1}}); + + check( + SV("%C='20'\t" + "%D='05/29/04'\t" + "%F='2004-05-29'\t" + "%j='150'\t" + "%g='04'\t" + "%G='2004'\t" + "%u='6'\t" + "%U='21'\t" + "%V='22'\t" + "%w='6'\t" + "%W='21'\t" +#if defined(__APPLE__) + "%x='29.05.2004'\t" +#else + "%x='29/05/2004'\t" +#endif + "%y='04'\t" + "%Y='2004'\t" +#if defined(__APPLE__) + "%Ex='29.05.2004'\t" +#else + "%Ex='29/05/2004'\t" +#endif + "%EC='20'\t" + "%Ey='04'\t" + "%EY='2004'\t" + "%Ou='6'\t" + "%OU='21'\t" + "%OV='22'\t" + "%Ow='6'\t" + "%OW='21'\t" + "%Oy='04'\t" + "\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{2004}, std::chrono::May, std::chrono::day{29}}); + + // Use supplied locale (ja_JP) + check( + loc, + SV("%C='19'\t" + "%D='01/01/70'\t" + "%F='1970-01-01'\t" + "%j='001'\t" + "%g='70'\t" + "%G='1970'\t" + "%u='4'\t" + "%U='00'\t" + "%V='01'\t" + "%w='4'\t" + "%W='00'\t" +#if defined(__APPLE__) || defined(_AIX) + "%x='1970/01/01'\t" +#else // defined(__APPLE__) || defined(_AIX) + "%x='1970年01月01日'\t" +#endif // defined(__APPLE__) || defined(_AIX) + "%y='70'\t" + "%Y='1970'\t" +#if defined(__APPLE__) || defined(_AIX) + "%Ex='1970/01/01'\t" + "%EC='19'\t" + "%Ey='70'\t" + "%EY='1970'\t" + "%Ou='4'\t" + "%OU='00'\t" + "%OV='01'\t" + "%Ow='4'\t" + "%OW='00'\t" + "%Oy='70'\t" +#else // defined(__APPLE__) || defined(_AIX) + "%Ex='昭和45年01月01日'\t" + "%EC='昭和'\t" + "%Ey='45'\t" + "%EY='昭和45年'\t" + "%Ou='四'\t" + "%OU='〇'\t" + "%OV='一'\t" + "%Ow='四'\t" + "%OW='〇'\t" + "%Oy='七十'\t" +#endif // defined(__APPLE__) || defined(_AIX) + "\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::January, std::chrono::day{1}}); + + check( + loc, + SV("%C='20'\t" + "%D='05/29/04'\t" + "%F='2004-05-29'\t" + "%j='150'\t" + "%g='04'\t" + "%G='2004'\t" + "%u='6'\t" + "%U='21'\t" + "%V='22'\t" + "%w='6'\t" + "%W='21'\t" +#if defined(__APPLE__) || defined(_AIX) + "%x='2004/05/29'\t" +#else // defined(__APPLE__) || defined(_AIX) + "%x='2004年05月29日'\t" +#endif // defined(__APPLE__) || defined(_AIX) + "%y='04'\t" + "%Y='2004'\t" +#if defined(__APPLE__) || defined(_AIX) + "%Ex='2004/05/29'\t" + "%EC='20'\t" + "%Ey='04'\t" + "%EY='2004'\t" + "%Ou='6'\t" + "%OU='21'\t" + "%OV='22'\t" + "%Ow='6'\t" + "%OW='21'\t" + "%Oy='04'\t" +#else // defined(__APPLE__) || defined(_AIX) + "%Ex='平成16年05月29日'\t" + "%EC='平成'\t" + "%Ey='16'\t" + "%EY='平成16年'\t" + "%Ou='六'\t" + "%OU='二十一'\t" + "%OV='二十二'\t" + "%Ow='六'\t" + "%OW='二十一'\t" + "%Oy='四'\t" +#endif // defined(__APPLE__) || defined(_AIX) + "\n"), + lfmt, + std::chrono::year_month_day{std::chrono::year{2004}, std::chrono::May, std::chrono::day{29}}); + + std::locale::global(std::locale::classic()); +} + +template +static void test_valid_values() { + // Fields only using month and day. + test_valid_md_values(); + // Fields only using year, month, and day. + test_valid_ymd_values(); +} + +template +static void test() { + test_no_chrono_specs(); + test_invalid_values(); + test_valid_values(); + check_invalid_types( + {SV("a"), SV("A"), SV("b"), SV("B"), SV("C"), SV("d"), SV("D"), SV("e"), SV("EC"), + SV("Ex"), SV("Ey"), SV("EY"), SV("F"), SV("g"), SV("G"), SV("h"), SV("j"), SV("m"), + SV("Od"), SV("Oe"), SV("Om"), SV("Ou"), SV("OU"), SV("OV"), SV("Ow"), SV("OW"), SV("Oy"), + SV("u"), SV("U"), SV("V"), SV("w"), SV("W"), SV("x"), SV("y"), SV("Y")}, + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::January, std::chrono::day{31}}); + + check_exception("Expected '%' or '}' in the chrono format-string", + SV("{:A"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::January, std::chrono::day{31}}); + check_exception("The chrono-specs contains a '{'", + SV("{:%%{"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::January, std::chrono::day{31}}); + check_exception("End of input while parsing the modifier chrono conversion-spec", + SV("{:%"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::January, std::chrono::day{31}}); + check_exception("End of input while parsing the modifier E", + SV("{:%E"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::January, std::chrono::day{31}}); + check_exception("End of input while parsing the modifier O", + SV("{:%O"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::January, std::chrono::day{31}}); + + // Precision not allowed + check_exception("Expected '%' or '}' in the chrono format-string", + SV("{:.3}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::January, std::chrono::day{31}}); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.syn/formatter.year_month_day_last.pass.cpp b/libcxx/test/std/time/time.syn/formatter.year_month_day_last.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.syn/formatter.year_month_day_last.pass.cpp @@ -0,0 +1,929 @@ +//===----------------------------------------------------------------------===// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// template struct formatter; + +#include +#include + +#include +#include +#include +#include +#include + +#include "formatter_tests.h" +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "string_literal.h" +#include "test_macros.h" + +template +static void test_no_chrono_specs() { + // Valid year, valid month + check(SV("1970/Jan/last"), + SV("{}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{1}}}); + check(SV("*1970/Jan/last*"), + SV("{:*^15}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{1}}}); + check(SV("*1970/Jan/last"), + SV("{:*>14}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{1}}}); + + // Valid year, invalid month + check(SV("1970/0 is not a valid month/last"), + SV("{}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check(SV("*1970/0 is not a valid month/last*"), + SV("{:*^34}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check(SV("*1970/0 is not a valid month/last"), + SV("{:*>33}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + + // Invalid year, valid month + check( + SV("-32768 is not a valid year/Jan/last"), + SV("{}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + check( + SV("*-32768 is not a valid year/Jan/last*"), + SV("{:*^37}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + check( + SV("*-32768 is not a valid year/Jan/last"), + SV("{:*>36}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + + // Invalid year, invalid month + check( + SV("-32768 is not a valid year/0 is not a valid month/last"), + SV("{}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{0}}}); + check( + SV("*-32768 is not a valid year/0 is not a valid month/last*"), + SV("{:*^56}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{0}}}); + check( + SV("*-32768 is not a valid year/0 is not a valid month/last"), + SV("{:*>55}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{0}}}); +} + +// TODO FMT Should x throw? +template +static void test_invalid_values() { + // Test that %a, %A, %b, %B, %h, %j, %u, %U, %V, %w, %W, %Ou, %OU, %OV, %Ow, and %OW throw an exception. + check_exception( + "formatting a weekday name needs a valid weekday", + SV("{:%A}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check_exception( + "formatting a weekday name needs a valid weekday", + SV("{:%A}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + + check_exception( + "formatting a weekday name needs a valid weekday", + SV("{:%a}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check_exception( + "formatting a weekday name needs a valid weekday", + SV("{:%a}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + + check_exception( + "formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check_exception( + "formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{13}}}); + check_exception( + "formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{255}}}); + + check_exception( + "formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{200}}}); + check_exception( + "formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{13}}}); + check_exception( + "formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{255}}}); + + check_exception( + "formatting a month name from an invalid month number", + SV("{:%h}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check_exception( + "formatting a month name from an invalid month number", + SV("{:%h}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{13}}}); + check_exception( + "formatting a month name from an invalid month number", + SV("{:%h}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{255}}}); + + check_exception( + "formatting a day of year needs a valid date", + SV("{:%j}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check_exception( + "formatting a day of year needs a valid date", + SV("{:%j}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + + check_exception( + "formatting a weekday needs a valid weekday", + SV("{:%u}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check_exception( + "formatting a weekday needs a valid weekday", + SV("{:%u}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + + check_exception( + "formatting a week of year needs a valid date", + SV("{:%U}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check_exception( + "formatting a week of year needs a valid date", + SV("{:%U}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + + check_exception( + "formatting a week of year needs a valid date", + SV("{:%V}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check_exception( + "formatting a week of year needs a valid date", + SV("{:%V}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + + check_exception( + "formatting a weekday needs a valid weekday", + SV("{:%w}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check_exception( + "formatting a weekday needs a valid weekday", + SV("{:%w}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + + check_exception( + "formatting a week of year needs a valid date", + SV("{:%W}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check_exception( + "formatting a week of year needs a valid date", + SV("{:%W}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + + check_exception( + "formatting a weekday needs a valid weekday", + SV("{:%Ou}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check_exception( + "formatting a weekday needs a valid weekday", + SV("{:%Ou}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + + check_exception( + "formatting a week of year needs a valid date", + SV("{:%OU}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check_exception( + "formatting a week of year needs a valid date", + SV("{:%OU}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + + check_exception( + "formatting a week of year needs a valid date", + SV("{:%OV}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check_exception( + "formatting a week of year needs a valid date", + SV("{:%OV}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + + check_exception( + "formatting a weekday needs a valid weekday", + SV("{:%Ow}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check_exception( + "formatting a weekday needs a valid weekday", + SV("{:%Ow}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + + check_exception( + "formatting a week of year needs a valid date", + SV("{:%OW}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check_exception( + "formatting a week of year needs a valid date", + SV("{:%OW}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); +} + +template +static void test_valid_md_values() { + constexpr std::basic_string_view fmt = + SV("{:%%b='%b'%t%%B='%B'%t%%h='%h'%t%%m='%m'%t%%Om='%Om'%t%%d='%d'%t%%e='%e'%t%%Od='%Od'%t%%Oe='%Oe'%n}"); + constexpr std::basic_string_view lfmt = + SV("{:L%%b='%b'%t%%B='%B'%t%%h='%h'%t%%m='%m'%t%%Om='%Om'%t%%d='%d'%t%%e='%e'%t%%Od='%Od'%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("%b='Jan'\t%B='January'\t%h='Jan'\t%m='01'\t%Om='01'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + fmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::January}}); + check(SV("%b='Feb'\t%B='February'\t%h='Feb'\t%m='02'\t%Om='02'\t%d='28'\t%e='28'\t%Od='28'\t%Oe='28'\n"), + fmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::February}}); + check(SV("%b='Mar'\t%B='March'\t%h='Mar'\t%m='03'\t%Om='03'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + fmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::March}}); + check(SV("%b='Apr'\t%B='April'\t%h='Apr'\t%m='04'\t%Om='04'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + fmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::April}}); + check(SV("%b='May'\t%B='May'\t%h='May'\t%m='05'\t%Om='05'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + fmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::May}}); + check(SV("%b='Jun'\t%B='June'\t%h='Jun'\t%m='06'\t%Om='06'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + fmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::June}}); + check(SV("%b='Jul'\t%B='July'\t%h='Jul'\t%m='07'\t%Om='07'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + fmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::July}}); + check(SV("%b='Aug'\t%B='August'\t%h='Aug'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + fmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::August}}); + check(SV("%b='Sep'\t%B='September'\t%h='Sep'\t%m='09'\t%Om='09'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + fmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::September}}); + check(SV("%b='Oct'\t%B='October'\t%h='Oct'\t%m='10'\t%Om='10'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + fmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::October}}); + check(SV("%b='Nov'\t%B='November'\t%h='Nov'\t%m='11'\t%Om='11'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + fmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::November}}); + check(SV("%b='Dec'\t%B='December'\t%h='Dec'\t%m='12'\t%Om='12'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + fmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::December}}); + + // Use the global locale (fr_FR) +#if defined(__APPLE__) + check(SV("%b='jan'\t%B='janvier'\t%h='jan'\t%m='01'\t%Om='01'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::January}}); + check(SV("%b='fév'\t%B='février'\t%h='fév'\t%m='02'\t%Om='02'\t%d='28'\t%e='28'\t%Od='28'\t%Oe='28'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::February}}); + check(SV("%b='mar'\t%B='mars'\t%h='mar'\t%m='03'\t%Om='03'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::March}}); + check(SV("%b='avr'\t%B='avril'\t%h='avr'\t%m='04'\t%Om='04'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::April}}); + check(SV("%b='mai'\t%B='mai'\t%h='mai'\t%m='05'\t%Om='05'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::May}}); + check(SV("%b='jui'\t%B='juin'\t%h='jui'\t%m='06'\t%Om='06'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::June}}); + check(SV("%b='jul'\t%B='juillet'\t%h='jul'\t%m='07'\t%Om='07'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::July}}); + check(SV("%b='aoû'\t%B='août'\t%h='aoû'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::August}}); + check(SV("%b='sep'\t%B='septembre'\t%h='sep'\t%m='09'\t%Om='09'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::September}}); + check(SV("%b='oct'\t%B='octobre'\t%h='oct'\t%m='10'\t%Om='10'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::October}}); + check(SV("%b='nov'\t%B='novembre'\t%h='nov'\t%m='11'\t%Om='11'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::November}}); + check(SV("%b='déc'\t%B='décembre'\t%h='déc'\t%m='12'\t%Om='12'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::December}}); +#else // defined(__APPLE__) + check(SV("%b='janv.'\t%B='janvier'\t%h='janv.'\t%m='01'\t%Om='01'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::January}}); + check(SV("%b='févr.'\t%B='février'\t%h='févr.'\t%m='02'\t%Om='02'\t%d='28'\t%e='28'\t%Od='28'\t%Oe='28'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::February}}); + check(SV("%b='mars'\t%B='mars'\t%h='mars'\t%m='03'\t%Om='03'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::March}}); + check( +# if defined(_WIN32) || defined(_AIX) + SV("%b='avr.'\t%B='avril'\t%h='avr.'\t%m='04'\t%Om='04'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), +# else // defined(_WIN32) || defined(_AIX) + SV("%b='avril'\t%B='avril'\t%h='avril'\t%m='04'\t%Om='04'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), +# endif // defined(_WIN32) || defined(_AIX) + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::April}}); + check(SV("%b='mai'\t%B='mai'\t%h='mai'\t%m='05'\t%Om='05'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::May}}); + check(SV("%b='juin'\t%B='juin'\t%h='juin'\t%m='06'\t%Om='06'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::June}}); + check(SV("%b='juil.'\t%B='juillet'\t%h='juil.'\t%m='07'\t%Om='07'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::July}}); + check(SV("%b='août'\t%B='août'\t%h='août'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::August}}); + check(SV("%b='sept.'\t%B='septembre'\t%h='sept.'\t%m='09'\t%Om='09'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::September}}); + check(SV("%b='oct.'\t%B='octobre'\t%h='oct.'\t%m='10'\t%Om='10'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::October}}); + check(SV("%b='nov.'\t%B='novembre'\t%h='nov.'\t%m='11'\t%Om='11'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::November}}); + check(SV("%b='déc.'\t%B='décembre'\t%h='déc.'\t%m='12'\t%Om='12'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::December}}); +#endif // defined(__APPLE__) + + // Use supplied locale (ja_JP) +#if defined(_WIN32) + check(loc, + SV("%b='1'\t%B='1月'\t%h='1'\t%m='01'\t%Om='01'\t%d='00'\t%e=' 0'\t%Od='〇'\t%Oe='〇'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::January}}); + check(loc, + SV("%b='2'\t%B='2月'\t%h='2'\t%m='02'\t%Om='02'\t%d='01'\t%e=' 1'\t%Od='一'\t%Oe='一'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::February}}); + check(loc, + SV("%b='3'\t%B='3月'\t%h='3'\t%m='03'\t%Om='03'\t%d='09'\t%e=' 9'\t%Od='九'\t%Oe='九'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::March}}); + check(loc, + SV("%b='4'\t%B='4月'\t%h='4'\t%m='04'\t%Om='04'\t%d='10'\t%e='10'\t%Od='十'\t%Oe='十'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::April}}); + check(loc, + SV("%b='5'\t%B='5月'\t%h='5'\t%m='05'\t%Om='05'\t%d='28'\t%e='28'\t%Od='二十八'\t%Oe='二十八'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::May}}); + check(loc, + SV("%b='6'\t%B='6月'\t%h='6'\t%m='06'\t%Om='06'\t%d='30'\t%e='30'\t%Od='二十九'\t%Oe='二十九'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::June}}); + check(loc, + SV("%b='7'\t%B='7月'\t%h='7'\t%m='07'\t%Om='07'\t%d='31'\t%e='31'\t%Od='三十'\t%Oe='三十'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::July}}); + check(loc, + SV("%b='8'\t%B='8月'\t%h='8'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='三十一'\t%Oe='三十一'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::August}}); + check(loc, + SV("%b='9'\t%B='9月'\t%h='9'\t%m='09'\t%Om='09'\t%d='32'\t%e='32'\t%Od='三十二'\t%Oe='三十二'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::September}}); + check(loc, + SV("%b='10'\t%B='10月'\t%h='10'\t%m='10'\t%Om='10'\t%d='99'\t%e='99'\t%Od='九十九'\t%Oe='九十九'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::October}}); + check(loc, + SV("%b='11'\t%B='11月'\t%h='11'\t%m='11'\t%Om='11'\t%d='100'\t%e='100'\t%Od='100'\t%Oe='100'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::November}}); + check(loc, + SV("%b='12'\t%B='12月'\t%h='12'\t%m='12'\t%Om='12'\t%d='255'\t%e='255'\t%Od='255'\t%Oe='255'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::December}}); +#elif defined(_AIX) // defined(_WIN32) + check(loc, + SV("%b='1月'\t%B='1月'\t%h='1月'\t%m='01'\t%Om='01'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::January}}); + check(loc, + SV("%b='2月'\t%B='2月'\t%h='2月'\t%m='02'\t%Om='02'\t%d='28'\t%e='28'\t%Od='28'\t%Oe='28'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::February}}); + check(loc, + SV("%b='3月'\t%B='3月'\t%h='3月'\t%m='03'\t%Om='03'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::March}}); + check(loc, + SV("%b='4月'\t%B='4月'\t%h='4月'\t%m='04'\t%Om='04'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::April}}); + check(loc, + SV("%b='5月'\t%B='5月'\t%h='5月'\t%m='05'\t%Om='05'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::May}}); + check(loc, + SV("%b='6月'\t%B='6月'\t%h='6月'\t%m='06'\t%Om='06'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::June}}); + check(loc, + SV("%b='7月'\t%B='7月'\t%h='7月'\t%m='07'\t%Om='07'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::July}}); + check(loc, + SV("%b='8月'\t%B='8月'\t%h='8月'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::August}}); + check(loc, + SV("%b='9月'\t%B='9月'\t%h='9月'\t%m='09'\t%Om='09'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::September}}); + check(loc, + SV("%b='10月'\t%B='10月'\t%h='10月'\t%m='10'\t%Om='10'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::October}}); + check(loc, + SV("%b='11月'\t%B='11月'\t%h='11月'\t%m='11'\t%Om='11'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::November}}); + check(loc, + SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='12'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::December}}); +#elif defined(__APPLE__) // defined(_WIN32) + check(loc, + SV("%b=' 1'\t%B='1月'\t%h=' 1'\t%m='01'\t%Om='01'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::January}}); + check(loc, + SV("%b=' 2'\t%B='2月'\t%h=' 2'\t%m='02'\t%Om='02'\t%d='28'\t%e='28'\t%Od='28'\t%Oe='28'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::February}}); + check(loc, + SV("%b=' 3'\t%B='3月'\t%h=' 3'\t%m='03'\t%Om='03'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::March}}); + check(loc, + SV("%b=' 4'\t%B='4月'\t%h=' 4'\t%m='04'\t%Om='04'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::April}}); + check(loc, + SV("%b=' 5'\t%B='5月'\t%h=' 5'\t%m='05'\t%Om='05'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::May}}); + check(loc, + SV("%b=' 6'\t%B='6月'\t%h=' 6'\t%m='06'\t%Om='06'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::June}}); + check(loc, + SV("%b=' 7'\t%B='7月'\t%h=' 7'\t%m='07'\t%Om='07'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::July}}); + check(loc, + SV("%b=' 8'\t%B='8月'\t%h=' 8'\t%m='08'\t%Om='08'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::August}}); + check(loc, + SV("%b=' 9'\t%B='9月'\t%h=' 9'\t%m='09'\t%Om='09'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::September}}); + check(loc, + SV("%b='10'\t%B='10月'\t%h='10'\t%m='10'\t%Om='10'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::October}}); + check(loc, + SV("%b='11'\t%B='11月'\t%h='11'\t%m='11'\t%Om='11'\t%d='30'\t%e='30'\t%Od='30'\t%Oe='30'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::November}}); + check(loc, + SV("%b='12'\t%B='12月'\t%h='12'\t%m='12'\t%Om='12'\t%d='31'\t%e='31'\t%Od='31'\t%Oe='31'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::December}}); +#else // defined(_WIN32) + check(loc, + SV("%b=' 1月'\t%B='1月'\t%h=' 1月'\t%m='01'\t%Om='一'\t%d='31'\t%e='31'\t%Od='三十一'\t%Oe='三十一'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::January}}); + check(loc, + SV("%b=' 2月'\t%B='2月'\t%h=' 2月'\t%m='02'\t%Om='二'\t%d='28'\t%e='28'\t%Od='二十八'\t%Oe='二十八'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::February}}); + check(loc, + SV("%b=' 3月'\t%B='3月'\t%h=' 3月'\t%m='03'\t%Om='三'\t%d='31'\t%e='31'\t%Od='三十一'\t%Oe='三十一'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::March}}); + check(loc, + SV("%b=' 4月'\t%B='4月'\t%h=' 4月'\t%m='04'\t%Om='四'\t%d='30'\t%e='30'\t%Od='三十'\t%Oe='三十'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::April}}); + check(loc, + SV("%b=' 5月'\t%B='5月'\t%h=' 5月'\t%m='05'\t%Om='五'\t%d='31'\t%e='31'\t%Od='三十一'\t%Oe='三十一'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::May}}); + check(loc, + SV("%b=' 6月'\t%B='6月'\t%h=' 6月'\t%m='06'\t%Om='六'\t%d='30'\t%e='30'\t%Od='三十'\t%Oe='三十'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::June}}); + check(loc, + SV("%b=' 7月'\t%B='7月'\t%h=' 7月'\t%m='07'\t%Om='七'\t%d='31'\t%e='31'\t%Od='三十一'\t%Oe='三十一'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::July}}); + check(loc, + SV("%b=' 8月'\t%B='8月'\t%h=' 8月'\t%m='08'\t%Om='八'\t%d='31'\t%e='31'\t%Od='三十一'\t%Oe='三十一'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::August}}); + check(loc, + SV("%b=' 9月'\t%B='9月'\t%h=' 9月'\t%m='09'\t%Om='九'\t%d='30'\t%e='30'\t%Od='三十'\t%Oe='三十'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::September}}); + check(loc, + SV("%b='10月'\t%B='10月'\t%h='10月'\t%m='10'\t%Om='十'\t%d='31'\t%e='31'\t%Od='三十一'\t%Oe='三十一'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::October}}); + check(loc, + SV("%b='11月'\t%B='11月'\t%h='11月'\t%m='11'\t%Om='十一'\t%d='30'\t%e='30'\t%Od='三十'\t%Oe='三十'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::November}}); + check(loc, + SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='十二'\t%d='31'\t%e='31'\t%Od='三十一'\t%Oe='三十一'\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::December}}); +#endif // defined(_WIN32) + + std::locale::global(std::locale::classic()); +} + +template +static void test_valid_ymd_values() { + constexpr std::basic_string_view fmt = SV( + "{:" + "%%C='%C'%t" + "%%D='%D'%t" + "%%F='%F'%t" + "%%j='%j'%t" + "%%g='%g'%t" + "%%G='%G'%t" + "%%u='%u'%t" + "%%U='%U'%t" + "%%V='%V'%t" + "%%w='%w'%t" + "%%W='%W'%t" + "%%x='%x'%t" + "%%y='%y'%t" + "%%Y='%Y'%t" + "%%Ex='%Ex'%t" + "%%EC='%EC'%t" + "%%Ey='%Ey'%t" + "%%EY='%EY'%t" + "%%Ou='%Ou'%t" + "%%OU='%OU'%t" + "%%OV='%OV'%t" + "%%Ow='%Ow'%t" + "%%OW='%OW'%t" + "%%Oy='%Oy'%t" + "%n}"); + + constexpr std::basic_string_view lfmt = SV( + "{:L" + "%%C='%C'%t" + "%%D='%D'%t" + "%%F='%F'%t" + "%%j='%j'%t" + "%%g='%g'%t" + "%%G='%G'%t" + "%%u='%u'%t" + "%%U='%U'%t" + "%%V='%V'%t" + "%%w='%w'%t" + "%%W='%W'%t" + "%%x='%x'%t" + "%%y='%y'%t" + "%%Y='%Y'%t" + "%%Ex='%Ex'%t" + "%%EC='%EC'%t" + "%%Ey='%Ey'%t" + "%%EY='%EY'%t" + "%%Ou='%Ou'%t" + "%%OU='%OU'%t" + "%%OV='%OV'%t" + "%%Ow='%Ow'%t" + "%%OW='%OW'%t" + "%%Oy='%Oy'%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("%C='19'\t" + "%D='01/31/70'\t" + "%F='1970-01-31'\t" + "%j='031'\t" + "%g='70'\t" + "%G='1970'\t" + "%u='6'\t" + "%U='04'\t" + "%V='05'\t" + "%w='6'\t" + "%W='04'\t" + "%x='01/31/70'\t" + "%y='70'\t" + "%Y='1970'\t" + "%Ex='01/31/70'\t" + "%EC='19'\t" + "%Ey='70'\t" + "%EY='1970'\t" + "%Ou='6'\t" + "%OU='04'\t" + "%OV='05'\t" + "%Ow='6'\t" + "%OW='04'\t" + "%Oy='70'\t" + "\n"), + fmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::January}}); + + check( + SV("%C='20'\t" + "%D='05/31/04'\t" + "%F='2004-05-31'\t" + "%j='152'\t" + "%g='04'\t" + "%G='2004'\t" + "%u='1'\t" + "%U='22'\t" + "%V='23'\t" + "%w='1'\t" + "%W='22'\t" + "%x='05/31/04'\t" + "%y='04'\t" + "%Y='2004'\t" + "%Ex='05/31/04'\t" + "%EC='20'\t" + "%Ey='04'\t" + "%EY='2004'\t" + "%Ou='1'\t" + "%OU='22'\t" + "%OV='23'\t" + "%Ow='1'\t" + "%OW='22'\t" + "%Oy='04'\t" + "\n"), + fmt, + std::chrono::year_month_day_last{std::chrono::year{2004}, std::chrono::month_day_last{std::chrono::May}}); + + // Use the global locale (fr_FR) + check( + SV("%C='19'\t" + "%D='01/31/70'\t" + "%F='1970-01-31'\t" + "%j='031'\t" + "%g='70'\t" + "%G='1970'\t" + "%u='6'\t" + "%U='04'\t" + "%V='05'\t" + "%w='6'\t" + "%W='04'\t" +#if defined(__APPLE__) + "%x='31.01.1970'\t" +#else + "%x='31/01/1970'\t" +#endif + "%y='70'\t" + "%Y='1970'\t" +#if defined(__APPLE__) + "%Ex='31.01.1970'\t" +#else + "%Ex='31/01/1970'\t" +#endif + "%EC='19'\t" + "%Ey='70'\t" + "%EY='1970'\t" + "%Ou='6'\t" + "%OU='04'\t" + "%OV='05'\t" + "%Ow='6'\t" + "%OW='04'\t" + "%Oy='70'\t" + "\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::January}}); + + check( + SV("%C='20'\t" + "%D='05/31/04'\t" + "%F='2004-05-31'\t" + "%j='152'\t" + "%g='04'\t" + "%G='2004'\t" + "%u='1'\t" + "%U='22'\t" + "%V='23'\t" + "%w='1'\t" + "%W='22'\t" +#if defined(__APPLE__) + "%x='31.05.2004'\t" +#else + "%x='31/05/2004'\t" +#endif + "%y='04'\t" + "%Y='2004'\t" +#if defined(__APPLE__) + "%Ex='31.05.2004'\t" +#else + "%Ex='31/05/2004'\t" +#endif + "%EC='20'\t" + "%Ey='04'\t" + "%EY='2004'\t" + "%Ou='1'\t" + "%OU='22'\t" + "%OV='23'\t" + "%Ow='1'\t" + "%OW='22'\t" + "%Oy='04'\t" + "\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{2004}, std::chrono::month_day_last{std::chrono::May}}); + + // Use supplied locale (ja_JP) + check( + loc, + SV("%C='19'\t" + "%D='01/31/70'\t" + "%F='1970-01-31'\t" + "%j='031'\t" + "%g='70'\t" + "%G='1970'\t" + "%u='6'\t" + "%U='04'\t" + "%V='05'\t" + "%w='6'\t" + "%W='04'\t" +#if defined(__APPLE__) || defined(_AIX) + "%x='1970/01/31'\t" +#else // defined(__APPLE__) || defined(_AIX) + "%x='1970年01月31日'\t" +#endif // defined(__APPLE__) || defined(_AIX) + "%y='70'\t" + "%Y='1970'\t" +#if defined(__APPLE__) || defined(_AIX) + "%Ex='1970/01/31'\t" + "%EC='19'\t" + "%Ey='70'\t" + "%EY='1970'\t" + "%Ou='6'\t" + "%OU='04'\t" + "%OV='05'\t" + "%Ow='6'\t" + "%OW='04'\t" + "%Oy='70'\t" +#else // defined(__APPLE__) || defined(_AIX) + "%Ex='昭和45年01月31日'\t" + "%EC='昭和'\t" + "%Ey='45'\t" + "%EY='昭和45年'\t" + "%Ou='六'\t" + "%OU='四'\t" + "%OV='五'\t" + "%Ow='六'\t" + "%OW='四'\t" + "%Oy='七十'\t" +#endif // defined(__APPLE__) || defined(_AIX) + "\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::January}}); + + check( + loc, + SV("%C='20'\t" + "%D='05/31/04'\t" + "%F='2004-05-31'\t" + "%j='152'\t" + "%g='04'\t" + "%G='2004'\t" + "%u='1'\t" + "%U='22'\t" + "%V='23'\t" + "%w='1'\t" + "%W='22'\t" +#if defined(__APPLE__) || defined(_AIX) + "%x='2004/05/31'\t" +#else // defined(__APPLE__) || defined(_AIX) + "%x='2004年05月31日'\t" +#endif // defined(__APPLE__) || defined(_AIX) + "%y='04'\t" + "%Y='2004'\t" +#if defined(__APPLE__) || defined(_AIX) + "%Ex='2004/05/31'\t" + "%EC='20'\t" + "%Ey='04'\t" + "%EY='2004'\t" + "%Ou='1'\t" + "%OU='22'\t" + "%OV='23'\t" + "%Ow='1'\t" + "%OW='22'\t" + "%Oy='04'\t" +#else // defined(__APPLE__) || defined(_AIX) + "%Ex='平成16年05月31日'\t" + "%EC='平成'\t" + "%Ey='16'\t" + "%EY='平成16年'\t" + "%Ou='一'\t" + "%OU='二十二'\t" + "%OV='二十三'\t" + "%Ow='一'\t" + "%OW='二十二'\t" + "%Oy='四'\t" +#endif // defined(__APPLE__) || defined(_AIX) + "\n"), + lfmt, + std::chrono::year_month_day_last{std::chrono::year{2004}, std::chrono::month_day_last{std::chrono::May}}); + + std::locale::global(std::locale::classic()); +} + +template +static void test_valid_values() { + // Fields only using month and day. + test_valid_md_values(); + // Fields only using year, month, and day. + test_valid_ymd_values(); +} + +template +static void test() { + test_no_chrono_specs(); + test_invalid_values(); + test_valid_values(); + check_invalid_types( + {SV("a"), SV("A"), SV("b"), SV("B"), SV("C"), SV("d"), SV("D"), SV("e"), SV("EC"), + SV("Ex"), SV("Ey"), SV("EY"), SV("F"), SV("g"), SV("G"), SV("h"), SV("j"), SV("m"), + SV("Od"), SV("Oe"), SV("Om"), SV("Ou"), SV("OU"), SV("OV"), SV("Ow"), SV("OW"), SV("Oy"), + SV("u"), SV("U"), SV("V"), SV("w"), SV("W"), SV("x"), SV("y"), SV("Y")}, + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::January}}); + + check_exception( + "Expected '%' or '}' in the chrono format-string", + SV("{:A"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::January}}); + check_exception( + "The chrono-specs contains a '{'", + SV("{:%%{"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::January}}); + check_exception( + "End of input while parsing the modifier chrono conversion-spec", + SV("{:%"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::January}}); + check_exception( + "End of input while parsing the modifier E", + SV("{:%E"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::January}}); + check_exception( + "End of input while parsing the modifier O", + SV("{:%O"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::January}}); + + // Precision not allowed + check_exception( + "Expected '%' or '}' in the chrono format-string", + SV("{:.3}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::January}}); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.syn/formatter.year_month_weekday.pass.cpp b/libcxx/test/std/time/time.syn/formatter.year_month_weekday.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.syn/formatter.year_month_weekday.pass.cpp @@ -0,0 +1,732 @@ +//===----------------------------------------------------------------------===// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// template struct formatter; + +#include +#include + +#include +#include +#include +#include +#include + +#include "formatter_tests.h" +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "string_literal.h" +#include "test_macros.h" + +template +static void test_no_chrono_specs() { + // Valid year, valid month, valid day, valid index + check(SV("1970/Jan/Mon[1]"), + SV("{}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check(SV("*1970/Jan/Mon[1]"), + SV("{:*>16}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check(SV("*1970/Jan/Mon[1]*"), + SV("{:*^17}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + + // Valid year, valid month, valid day, invalid index + check(SV("1970/Jan/Mon[7 is not a valid index]"), + SV("{}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}}); + + // Valid year, valid month, invalid day, valid index + check(SV("1970/Jan/13 is not a valid weekday[1]"), + SV("{}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); + + // Valid year, valid month, invalid day, invalid index + check(SV("1970/Jan/13 is not a valid weekday[7 is not a valid index]"), + SV("{}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 7}}); + + // Valid year, invalid month, valid day, invalid index + check(SV("1970/0 is not a valid month/Mon[7 is not a valid index]"), + SV("{}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}}); + + // Valid year, invalid month, invalid day, valid index + check(SV("1970/0 is not a valid month/13 is not a valid weekday[1]"), + SV("{}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); + + // Valid year, invalid month, invalid day, invalid index + check(SV("1970/0 is not a valid month/13 is not a valid weekday[7 is not a valid index]"), + SV("{}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 7}}); + + // Invalid year, valid month, valid day, valid index + check( + SV("-32768 is not a valid year/Jan/Mon[1]"), + SV("{}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + + // Invalid year, valid month, valid day, invalid index + check( + SV("-32768 is not a valid year/Jan/Mon[7 is not a valid index]"), + SV("{}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}}); + + // Invalid year, valid month, invalid day, valid index + check( + SV("-32768 is not a valid year/Jan/13 is not a valid weekday[1]"), + SV("{}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); + + // Invalid year, valid month, invalid day, invalid index + check( + SV("-32768 is not a valid year/Jan/13 is not a valid weekday[7 is not a valid index]"), + SV("{}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 7}}); + + // Invalid year, invalid month, valid day, invalid index + check( + SV("-32768 is not a valid year/0 is not a valid month/Mon[7 is not a valid index]"), + SV("{}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}}); + + // Invalid year, invalid month, invalid day, valid index + check( + SV("-32768 is not a valid year/0 is not a valid month/13 is not a valid weekday[1]"), + SV("{}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); + + // Invalid year, invalid month, invalid day, invalid index + check( + SV("-32768 is not a valid year/0 is not a valid month/13 is not a valid weekday[7 is not a valid index]"), + SV("{}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 7}}); +} + +// TODO FMT Should x throw? +template +static void test_invalid_values() { + // Test that %a, %A, %b, %B, %h, %j, %u, %U, %V, %w, %W, %Ou, %OU, %OV, %Ow, and %OW throw an exception. + check_exception( + "formatting a weekday name needs a valid weekday", + SV("{:%a}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); + + check_exception( + "formatting a weekday name needs a valid weekday", + SV("{:%A}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); + + check_exception( + "formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + + check_exception( + "formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + + check_exception( + "formatting a month name from an invalid month number", + SV("{:%h}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + + check_exception( + "formatting a day of year needs a valid date", + SV("{:%j}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}}); + check_exception( + "formatting a day of year needs a valid date", + SV("{:%j}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); + check_exception( + "formatting a day of year needs a valid date", + SV("{:%j}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check_exception( + "formatting a day of year needs a valid date", + SV("{:%j}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + + check_exception( + "formatting a weekday needs a valid weekday", + SV("{:%u}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); + + check_exception( + "formatting a week of year needs a valid date", + SV("{:%U}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}}); + check_exception( + "formatting a week of year needs a valid date", + SV("{:%U}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); + check_exception( + "formatting a week of year needs a valid date", + SV("{:%U}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check_exception( + "formatting a week of year needs a valid date", + SV("{:%U}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + + check_exception( + "formatting a week of year needs a valid date", + SV("{:%V}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}}); + check_exception( + "formatting a week of year needs a valid date", + SV("{:%V}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); + check_exception( + "formatting a week of year needs a valid date", + SV("{:%V}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check_exception( + "formatting a week of year needs a valid date", + SV("{:%V}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + + check_exception( + "formatting a weekday needs a valid weekday", + SV("{:%w}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); + + check_exception( + "formatting a week of year needs a valid date", + SV("{:%W}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}}); + check_exception( + "formatting a week of year needs a valid date", + SV("{:%W}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); + check_exception( + "formatting a week of year needs a valid date", + SV("{:%W}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check_exception( + "formatting a week of year needs a valid date", + SV("{:%W}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); +} + +template +static void test_valid_md_values() { + constexpr std::basic_string_view fmt = + SV("{:%%b='%b'%t%%B='%B'%t%%h='%h'%t%%m='%m'%t%%Om='%Om'%t%%d='%d'%t%%e='%e'%t%%Od='%Od'%t%%Oe='%Oe'%n}"); + constexpr std::basic_string_view lfmt = + SV("{:L%%b='%b'%t%%B='%B'%t%%h='%h'%t%%m='%m'%t%%Om='%Om'%t%%d='%d'%t%%e='%e'%t%%Od='%Od'%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("%b='Jan'\t%B='January'\t%h='Jan'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), + fmt, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); + check(SV("%b='Dec'\t%B='December'\t%h='Dec'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"), + fmt, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}}); + + // Use the global locale (fr_FR) +#if defined(__APPLE__) + check(SV("%b='jan'\t%B='janvier'\t%h='jan'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), + lfmt, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); + + check(SV("%b='déc'\t%B='décembre'\t%h='déc'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"), + lfmt, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}}); + +#else // defined(__APPLE__) + check(SV("%b='janv.'\t%B='janvier'\t%h='janv.'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), + lfmt, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); + check(SV("%b='déc.'\t%B='décembre'\t%h='déc.'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"), + lfmt, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}}); + +#endif // defined(__APPLE__) + + // Use supplied locale (ja_JP) +#if defined(_WIN32) + check(loc, + SV("%b='1'\t%B='1月'\t%h='1'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='一'\t%Oe='一'\n"), + lfmt, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); + + check(loc, + SV("%b='12'\t%B='12月'\t%h='12'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"), + lfmt, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}}); + +#elif defined(_AIX) // defined(_WIN32) + check(loc, + SV("%b='1月'\t%B='1月'\t%h='1月'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), + lfmt, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); + + check(loc, + SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"), + lfmt, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}}); + +#elif defined(__APPLE__) // defined(_WIN32) + check(loc, + SV("%b=' 1'\t%B='1月'\t%h=' 1'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), + lfmt, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); + + check(loc, + SV("%b='12'\t%B='12月'\t%h='12'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"), + lfmt, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}}); + +#else // defined(_WIN32) + check(loc, + SV("%b=' 1月'\t%B='1月'\t%h=' 1月'\t%m='01'\t%Om='一'\t%d='01'\t%e=' 1'\t%Od='一'\t%Oe='一'\n"), + lfmt, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); + + check(loc, + SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='十二'\t%d='20'\t%e='20'\t%Od='二十'\t%Oe='二十'\n"), + lfmt, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}}); + +#endif // defined(_WIN32) + + std::locale::global(std::locale::classic()); +} + +template +static void test_valid_ymd_values() { + constexpr std::basic_string_view fmt = SV( + "{:" + "%%C='%C'%t" + "%%D='%D'%t" + "%%F='%F'%t" + "%%j='%j'%t" + "%%g='%g'%t" + "%%G='%G'%t" + "%%u='%u'%t" + "%%U='%U'%t" + "%%V='%V'%t" + "%%w='%w'%t" + "%%W='%W'%t" + "%%x='%x'%t" + "%%y='%y'%t" + "%%Y='%Y'%t" + "%%Ex='%Ex'%t" + "%%EC='%EC'%t" + "%%Ey='%Ey'%t" + "%%EY='%EY'%t" + "%%Ou='%Ou'%t" + "%%OU='%OU'%t" + "%%OV='%OV'%t" + "%%Ow='%Ow'%t" + "%%OW='%OW'%t" + "%%Oy='%Oy'%t" + "%n}"); + + constexpr std::basic_string_view lfmt = SV( + "{:L" + "%%C='%C'%t" + "%%D='%D'%t" + "%%F='%F'%t" + "%%j='%j'%t" + "%%g='%g'%t" + "%%G='%G'%t" + "%%u='%u'%t" + "%%U='%U'%t" + "%%V='%V'%t" + "%%w='%w'%t" + "%%W='%W'%t" + "%%x='%x'%t" + "%%y='%y'%t" + "%%Y='%Y'%t" + "%%Ex='%Ex'%t" + "%%EC='%EC'%t" + "%%Ey='%Ey'%t" + "%%EY='%EY'%t" + "%%Ou='%Ou'%t" + "%%OU='%OU'%t" + "%%OV='%OV'%t" + "%%Ow='%Ow'%t" + "%%OW='%OW'%t" + "%%Oy='%Oy'%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("%C='19'\t" + "%D='01/01/70'\t" + "%F='1970-01-01'\t" + "%j='001'\t" + "%g='70'\t" + "%G='1970'\t" + "%u='4'\t" + "%U='00'\t" + "%V='01'\t" + "%w='4'\t" + "%W='00'\t" + "%x='01/01/70'\t" + "%y='70'\t" + "%Y='1970'\t" + "%Ex='01/01/70'\t" + "%EC='19'\t" + "%Ey='70'\t" + "%EY='1970'\t" + "%Ou='4'\t" + "%OU='00'\t" + "%OV='01'\t" + "%Ow='4'\t" + "%OW='00'\t" + "%Oy='70'\t" + "\n"), + fmt, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); + + check( + SV("%C='20'\t" + "%D='05/29/04'\t" + "%F='2004-05-29'\t" + "%j='150'\t" + "%g='04'\t" + "%G='2004'\t" + "%u='6'\t" + "%U='21'\t" + "%V='22'\t" + "%w='6'\t" + "%W='21'\t" + "%x='05/29/04'\t" + "%y='04'\t" + "%Y='2004'\t" + "%Ex='05/29/04'\t" + "%EC='20'\t" + "%Ey='04'\t" + "%EY='2004'\t" + "%Ou='6'\t" + "%OU='21'\t" + "%OV='22'\t" + "%Ow='6'\t" + "%OW='21'\t" + "%Oy='04'\t" + "\n"), + fmt, + std::chrono::year_month_weekday{ + std::chrono::year{2004}, std::chrono::May, std::chrono::weekday_indexed{std::chrono::weekday{6}, 5}}); + + // Use the global locale (fr_FR) + check( + SV("%C='19'\t" + "%D='01/01/70'\t" + "%F='1970-01-01'\t" + "%j='001'\t" + "%g='70'\t" + "%G='1970'\t" + "%u='4'\t" + "%U='00'\t" + "%V='01'\t" + "%w='4'\t" + "%W='00'\t" +#if defined(__APPLE__) + "%x='01.01.1970'\t" +#else + "%x='01/01/1970'\t" +#endif + "%y='70'\t" + "%Y='1970'\t" +#if defined(__APPLE__) + "%Ex='01.01.1970'\t" +#else + "%Ex='01/01/1970'\t" +#endif + "%EC='19'\t" + "%Ey='70'\t" + "%EY='1970'\t" + "%Ou='4'\t" + "%OU='00'\t" + "%OV='01'\t" + "%Ow='4'\t" + "%OW='00'\t" + "%Oy='70'\t" + "\n"), + lfmt, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); + + check( + SV("%C='20'\t" + "%D='05/29/04'\t" + "%F='2004-05-29'\t" + "%j='150'\t" + "%g='04'\t" + "%G='2004'\t" + "%u='6'\t" + "%U='21'\t" + "%V='22'\t" + "%w='6'\t" + "%W='21'\t" +#if defined(__APPLE__) + "%x='29.05.2004'\t" +#else + "%x='29/05/2004'\t" +#endif + "%y='04'\t" + "%Y='2004'\t" +#if defined(__APPLE__) + "%Ex='29.05.2004'\t" +#else + "%Ex='29/05/2004'\t" +#endif + "%EC='20'\t" + "%Ey='04'\t" + "%EY='2004'\t" + "%Ou='6'\t" + "%OU='21'\t" + "%OV='22'\t" + "%Ow='6'\t" + "%OW='21'\t" + "%Oy='04'\t" + "\n"), + lfmt, + std::chrono::year_month_weekday{ + std::chrono::year{2004}, std::chrono::May, std::chrono::weekday_indexed{std::chrono::weekday{6}, 5}}); + + // Use supplied locale (ja_JP) + check( + loc, + SV("%C='19'\t" + "%D='01/01/70'\t" + "%F='1970-01-01'\t" + "%j='001'\t" + "%g='70'\t" + "%G='1970'\t" + "%u='4'\t" + "%U='00'\t" + "%V='01'\t" + "%w='4'\t" + "%W='00'\t" +#if defined(__APPLE__) || defined(_AIX) + "%x='1970/01/01'\t" +#else // defined(__APPLE__) || defined(_AIX) + "%x='1970年01月01日'\t" +#endif // defined(__APPLE__) || defined(_AIX) + "%y='70'\t" + "%Y='1970'\t" +#if defined(__APPLE__) || defined(_AIX) + "%Ex='1970/01/01'\t" + "%EC='19'\t" + "%Ey='70'\t" + "%EY='1970'\t" + "%Ou='4'\t" + "%OU='00'\t" + "%OV='01'\t" + "%Ow='4'\t" + "%OW='00'\t" + "%Oy='70'\t" +#else // defined(__APPLE__) || defined(_AIX) + "%Ex='昭和45年01月01日'\t" + "%EC='昭和'\t" + "%Ey='45'\t" + "%EY='昭和45年'\t" + "%Ou='四'\t" + "%OU='〇'\t" + "%OV='一'\t" + "%Ow='四'\t" + "%OW='〇'\t" + "%Oy='七十'\t" +#endif // defined(__APPLE__) || defined(_AIX) + "\n"), + lfmt, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); + + check( + loc, + SV("%C='20'\t" + "%D='05/29/04'\t" + "%F='2004-05-29'\t" + "%j='150'\t" + "%g='04'\t" + "%G='2004'\t" + "%u='6'\t" + "%U='21'\t" + "%V='22'\t" + "%w='6'\t" + "%W='21'\t" +#if defined(__APPLE__) || defined(_AIX) + "%x='2004/05/29'\t" +#else // defined(__APPLE__) || defined(_AIX) + "%x='2004年05月29日'\t" +#endif // defined(__APPLE__) || defined(_AIX) + "%y='04'\t" + "%Y='2004'\t" +#if defined(__APPLE__) || defined(_AIX) + "%Ex='2004/05/29'\t" + "%EC='20'\t" + "%Ey='04'\t" + "%EY='2004'\t" + "%Ou='6'\t" + "%OU='21'\t" + "%OV='22'\t" + "%Ow='6'\t" + "%OW='21'\t" + "%Oy='04'\t" +#else // defined(__APPLE__) || defined(_AIX) + "%Ex='平成16年05月29日'\t" + "%EC='平成'\t" + "%Ey='16'\t" + "%EY='平成16年'\t" + "%Ou='六'\t" + "%OU='二十一'\t" + "%OV='二十二'\t" + "%Ow='六'\t" + "%OW='二十一'\t" + "%Oy='四'\t" +#endif // defined(__APPLE__) || defined(_AIX) + "\n"), + lfmt, + std::chrono::year_month_weekday{ + std::chrono::year{2004}, std::chrono::May, std::chrono::weekday_indexed{std::chrono::weekday{6}, 5}}); + + std::locale::global(std::locale::classic()); +} + +template +static void test_valid_values() { + // Fields only using month and day. + test_valid_md_values(); + // Fields only using year, month, and day. + test_valid_ymd_values(); +} + +template +static void test() { + test_no_chrono_specs(); + test_invalid_values(); + test_valid_values(); + check_invalid_types( + {SV("a"), SV("A"), SV("b"), SV("B"), SV("C"), SV("d"), SV("D"), SV("e"), SV("EC"), + SV("Ex"), SV("Ey"), SV("EY"), SV("F"), SV("g"), SV("G"), SV("h"), SV("j"), SV("m"), + SV("Od"), SV("Oe"), SV("Om"), SV("Ou"), SV("OU"), SV("OV"), SV("Ow"), SV("OW"), SV("Oy"), + SV("u"), SV("U"), SV("V"), SV("w"), SV("W"), SV("x"), SV("y"), SV("Y")}, + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + + check_exception( + "Expected '%' or '}' in the chrono format-string", + SV("{:A"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check_exception( + "The chrono-specs contains a '{'", + SV("{:%%{"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check_exception( + "End of input while parsing the modifier chrono conversion-spec", + SV("{:%"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check_exception( + "End of input while parsing the modifier E", + SV("{:%E"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check_exception( + "End of input while parsing the modifier O", + SV("{:%O"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + + // Precision not allowed + check_exception( + "Expected '%' or '}' in the chrono format-string", + SV("{:.3}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.syn/formatter.year_month_weekday_last.pass.cpp b/libcxx/test/std/time/time.syn/formatter.year_month_weekday_last.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/time/time.syn/formatter.year_month_weekday_last.pass.cpp @@ -0,0 +1,243 @@ +//===----------------------------------------------------------------------===// +// 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 + +// REQUIRES: locale.fr_FR.UTF-8 +// REQUIRES: locale.ja_JP.UTF-8 + +// + +// template struct formatter; + +#include +#include + +#include +#include +#include +#include +#include + +#include "formatter_tests.h" +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "string_literal.h" +#include "test_macros.h" + +template +static void test_no_chrono_specs() { + // Valid + check(SV("1970/Jan/Mon[last]"), + SV("{}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + check(SV("*1970/Jan/Mon[last]*"), + SV("{:*^20}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + check(SV("*1970/Jan/Mon[last]"), + SV("{:*>19}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + + // Invalid + check(SV("1970/Jan/8 is not a valid weekday[last]"), + SV("{}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{8}}}); + check(SV("1970/0 is not a valid month/Mon[last]"), + SV("{}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + check(SV("-32768 is not a valid year/Jan/Mon[last]"), + SV("{}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{1}}}); +} + +template +static void test_invalid_values() { + // *** Invalid weekday *** + + // Weekday name conversion + check_exception( + "formatting a weekday name needs a valid weekday", + SV("{:%a}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{8}}}); + check_exception( + "formatting a weekday name needs a valid weekday", + SV("{:%A}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{8}}}); + + // Weekday conversion + check_exception( + "formatting a weekday needs a valid weekday", + SV("{:%u}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{8}}}); + check_exception( + "formatting a weekday needs a valid weekday", + SV("{:%w}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{8}}}); + check_exception( + "formatting a weekday needs a valid weekday", + SV("{:%Ou}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{8}}}); + check_exception( + "formatting a weekday needs a valid weekday", + SV("{:%Ow}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{8}}}); + + // Day of year field + check_exception( + "formatting a day of year needs a valid date", + SV("{:%j}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{8}}}); + + // Month name conversion + check(SV("Jan"), + SV("{:%b}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{8}}}); + check(SV("Jan"), + SV("{:%h}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{8}}}); + check(SV("January"), + SV("{:%B}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{8}}}); + + // *** Invalid month *** + + // Weekday name conversion + check(SV("Mon"), + SV("{:%a}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + check(SV("Monday"), + SV("{:%A}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + // Weekday conversion + check(SV("1"), + SV("{:%u}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + check(SV("1"), + SV("{:%w}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + check(SV("1"), + SV("{:%Ou}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + check(SV("1"), + SV("{:%Ow}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + + // Day of year field + check_exception( + "formatting a day of year needs a valid date", + SV("{:%j}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + + // Month name conversion + check_exception( + "formatting a month name from an invalid month number", + SV("{:%b}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + check_exception( + "formatting a month name from an invalid month number", + SV("{:%h}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + check_exception( + "formatting a month name from an invalid month number", + SV("{:%B}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + + // *** Invalid year *** + + // Weekday name conversion + check(SV("Mon"), + SV("{:%a}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + check(SV("Monday"), + SV("{:%A}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + + // Weekday conversion + check(SV("1"), + SV("{:%u}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + check(SV("1"), + SV("{:%w}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + check(SV("1"), + SV("{:%Ou}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + check(SV("1"), + SV("{:%Ow}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + + // Day of year field + check_exception( + "formatting a day of year needs a valid date", + SV("{:%j}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + + // Month name conversion + check(SV("Jan"), + SV("{:%b}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + check(SV("Jan"), + SV("{:%h}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{1}}}); + check(SV("January"), + SV("{:%B}"), + std::chrono::year_month_weekday_last{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_last{std::chrono::weekday{1}}}); +} + +template +static void test() { + test_no_chrono_specs(); + test_invalid_values(); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp b/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp --- a/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp +++ b/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp @@ -146,19 +146,19 @@ assert_is_formattable(); assert_is_formattable(); - assert_is_not_formattable(); - assert_is_not_formattable(); - - assert_is_not_formattable(); - assert_is_not_formattable(); - assert_is_not_formattable(); - assert_is_not_formattable(); - - assert_is_not_formattable(); - assert_is_not_formattable(); - assert_is_not_formattable(); - assert_is_not_formattable(); - assert_is_not_formattable(); + assert_is_formattable(); + assert_is_formattable(); + + assert_is_formattable(); + assert_is_formattable(); + assert_is_formattable(); + assert_is_formattable(); + + assert_is_formattable(); + assert_is_formattable(); + assert_is_formattable(); + assert_is_formattable(); + assert_is_formattable(); assert_is_not_formattable, CharT>();