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,Not assigned,, `[time.syn] `_,"Formatter ``chrono::local_info``",A ```` implementation,Not assigned,, 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 it 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; // XXX test when set to 0, what happens. + __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,103 @@ 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 __day_of_year_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() ; + + return (__value.year().ok() && __value.month().ok() && __value.weekday().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 +465,16 @@ // Note that the behaviour what the precision does isn't specified. __specs.__precision_ = -1; } else { + // Before weekday since the error is more specific 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 value"); + + if (__specs.__chrono_.__day_of_year_ && !__formatter::__day_of_year_ok(__value)) + std::__throw_format_error("formatting a day of year needs a valid value"); + 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,93 @@ 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 not test for ok()... + 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,6 +243,7 @@ break; case _CharT('j'): + __parser_.__day_of_year_ = true; __format_spec::__validate_date_or_duration(__flags); break; @@ -267,6 +268,8 @@ [[fallthrough]]; case _CharT('u'): case _CharT('w'): + __parser_.__weekday_ = true; + __validate_weekday(__flags); __format_spec::__validate_weekday(__flags); break; @@ -378,6 +381,7 @@ 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 @@ -178,6 +178,8 @@ __alignment __alignment_ : 3; bool __locale_specific_form_ : 1; bool __weekday_name_ : 1; + bool __weekday_ : 1; + bool __day_of_year_ : 1; bool __month_name_ : 1; }; @@ -301,10 +303,13 @@ _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_, + .__month_name_ = __month_name_}, .__width_{__get_width(__ctx)}, .__precision_{__get_precision(__ctx)}, .__fill_{__fill_}}; @@ -317,12 +322,16 @@ 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 __month_name_ : 1 {false}; - uint8_t __reserved_1_ : 6 {0}; + uint8_t __reserved_1_ : 4 {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); // XXX incosisten, synpsis differs + // 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/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,123 @@ +//===----------------------------------------------------------------------===// +// +// 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")); +#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**) { + using namespace std::literals::chrono_literals; + + 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 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 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 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 + 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 + 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 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 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 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 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 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,467 @@ +//===----------------------------------------------------------------------===// +// 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}}); + 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}}); + + // Use the global locale (fr_FR) +#if defined(__APPLE__) + check(SV("%b='jan'\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év'\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='mar'\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(SV("%b='avr'\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"), + 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='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='jui'\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%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='sep'\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}}); + 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 + 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 + 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}}); + 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(__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='一'\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='二'\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='三'\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='四'\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='五'\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='六'\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='七'\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='八'\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='九'\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='十'\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='十一'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\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='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='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\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}}); +#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,276 @@ +//===----------------------------------------------------------------------===// +// 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("{:*^11}"), std::chrono::month_day_last{std::chrono::month{1}}); + check(SV("*Jan[last]"), SV("{:*>10}"), 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("{:*^30}"), 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) + 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( +#ifdef _WIN32 + SV("%b='avr.'\t%B='avril'\t%h='avr.'\t%m='04'\t%Om='04'\n"), +#else + SV("%b='avril'\t%B='avril'\t%h='avril'\t%m='04'\t%Om='04'\n"), +#endif + 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}); + + // 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}); +#else + 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 + + 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,554 @@ +//===----------------------------------------------------------------------===// +// 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) + 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( +#ifdef _WIN32 + SV("%b='avr.'\t%B='avril'\t%h='avr.'\t%m='04'\t%Om='04'\n"), +#else + SV("%b='avril'\t%B='avril'\t%h='avril'\t%m='04'\t%Om='04'\n"), +#endif + 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}}); + + // 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}}); +#else + 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 + + 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) + 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}}); + + // 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 + 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 + + 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,311 @@ +//===----------------------------------------------------------------------===// +// 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) + 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}); + + // 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 + 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 + + 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}"); + + // 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}); + } + + { // 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) + 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}); + + // 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,249 @@ +//===----------------------------------------------------------------------===// +// 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) + 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)}); + + // 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 + 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 + + 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)); + + // 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)}); + + 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,142 @@ +//===----------------------------------------------------------------------===// +// 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 + 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}}); +} +#if 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{200}); + check_exception("formatting a month name from an invalid month number", SV("{:%b}"), std::chrono::month{13}); + check_exception("formatting a month name from an invalid month number", SV("{:%b}"), std::chrono::month{255}); + + check_exception("formatting a month name from an invalid month number", SV("{:%h}"), std::chrono::month{0}); + check_exception("formatting a month name from an invalid month number", SV("{:%h}"), std::chrono::month{13}); + check_exception("formatting a month name from an invalid month number", SV("{:%h}"), std::chrono::month{255}); + + check_exception("formatting a month name from an invalid month number", SV("{:%B}"), std::chrono::month{0}); + check_exception("formatting a month name from an invalid month number", SV("{:%B}"), std::chrono::month{13}); + check_exception("formatting a month name from an invalid month number", SV("{:%B}"), std::chrono::month{255}); + + constexpr string_literal fmt{"{:%%b='%b'%t%%B='%B'%t%%h='%h'%t%%m='%m'%t%%Om='%Om'%n}"}; + constexpr string_literal lfmt{"{: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::January); + check(SV("%b='Feb'\t%B='February'\t%h='Feb'\t%m='02'\t%Om='02'\n"), fmt,std::chrono::February); + check(SV("%b='Mar'\t%B='March'\t%h='Mar'\t%m='03'\t%Om='03'\n"), fmt,std::chrono::March); + check(SV("%b='Apr'\t%B='April'\t%h='Apr'\t%m='04'\t%Om='04'\n"), fmt,std::chrono::April); + check(SV("%b='May'\t%B='May'\t%h='May'\t%m='05'\t%Om='05'\n"), fmt,std::chrono::May); + check(SV("%b='Jun'\t%B='June'\t%h='Jun'\t%m='06'\t%Om='06'\n"), fmt,std::chrono::June); + check(SV("%b='Jul'\t%B='July'\t%h='Jul'\t%m='07'\t%Om='07'\n"), fmt,std::chrono::July); + check(SV("%b='Aug'\t%B='August'\t%h='Aug'\t%m='08'\t%Om='08'\n"), fmt,std::chrono::August); + check(SV("%b='Sep'\t%B='September'\t%h='Sep'\t%m='09'\t%Om='09'\n"), fmt,std::chrono::September); + check(SV("%b='Oct'\t%B='October'\t%h='Oct'\t%m='10'\t%Om='10'\n"), fmt,std::chrono::October); + check(SV("%b='Nov'\t%B='November'\t%h='Nov'\t%m='11'\t%Om='11'\n"), fmt,std::chrono::November); + check(SV("%b='Dec'\t%B='December'\t%h='Dec'\t%m='12'\t%Om='12'\n"), fmt,std::chrono::December); + + // Use the global locale (fr_FR) + check(SV("%b='janv.'\t%B='janvier'\t%h='janv.'\t%m='01'\t%Om='01'\n"), lfmt,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::February); + check(SV("%b='mars'\t%B='mars'\t%h='mars'\t%m='03'\t%Om='03'\n"), lfmt,std::chrono::March); + check(SV("%b='avril'\t%B='avril'\t%h='avril'\t%m='04'\t%Om='04'\n"), lfmt,std::chrono::April); + check(SV("%b='mai'\t%B='mai'\t%h='mai'\t%m='05'\t%Om='05'\n"), lfmt,std::chrono::May); + check(SV("%b='juin'\t%B='juin'\t%h='juin'\t%m='06'\t%Om='06'\n"), lfmt,std::chrono::June); + check(SV("%b='juil.'\t%B='juillet'\t%h='juil.'\t%m='07'\t%Om='07'\n"), lfmt,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::August); + check(SV("%b='sept.'\t%B='septembre'\t%h='sept.'\t%m='09'\t%Om='09'\n"), lfmt,std::chrono::September); + check(SV("%b='oct.'\t%B='octobre'\t%h='oct.'\t%m='10'\t%Om='10'\n"), lfmt,std::chrono::October); + check(SV("%b='nov.'\t%B='novembre'\t%h='nov.'\t%m='11'\t%Om='11'\n"), lfmt,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::December); + + // Use supplied locale (ja_JP) + check(loc, SV("%b=' 1月'\t%B='1月'\t%h=' 1月'\t%m='01'\t%Om='一'\n"), lfmt,std::chrono::January); + check(loc, SV("%b=' 2月'\t%B='2月'\t%h=' 2月'\t%m='02'\t%Om='二'\n"), lfmt,std::chrono::February); + check(loc, SV("%b=' 3月'\t%B='3月'\t%h=' 3月'\t%m='03'\t%Om='三'\n"), lfmt,std::chrono::March); + check(loc, SV("%b=' 4月'\t%B='4月'\t%h=' 4月'\t%m='04'\t%Om='四'\n"), lfmt,std::chrono::April); + check(loc, SV("%b=' 5月'\t%B='5月'\t%h=' 5月'\t%m='05'\t%Om='五'\n"), lfmt,std::chrono::May); + check(loc, SV("%b=' 6月'\t%B='6月'\t%h=' 6月'\t%m='06'\t%Om='六'\n"), lfmt,std::chrono::June); + check(loc, SV("%b=' 7月'\t%B='7月'\t%h=' 7月'\t%m='07'\t%Om='七'\n"), lfmt,std::chrono::July); + check(loc, SV("%b=' 8月'\t%B='8月'\t%h=' 8月'\t%m='08'\t%Om='八'\n"), lfmt,std::chrono::August); + check(loc, SV("%b=' 9月'\t%B='9月'\t%h=' 9月'\t%m='09'\t%Om='九'\n"), lfmt,std::chrono::September); + check(loc, SV("%b='10月'\t%B='10月'\t%h='10月'\t%m='10'\t%Om='十'\n"), lfmt,std::chrono::October); + check(loc, SV("%b='11月'\t%B='11月'\t%h='11月'\t%m='11'\t%Om='十一'\n"), lfmt,std::chrono::November); + check(loc, SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='十二'\n"), lfmt,std::chrono::December); + + std::locale::global(std::locale::classic()); +} +#endif +template +static void test() { + test_no_chrono_specs(); +#if 0 + test_valid_values(); + check_invalid_types({SV("b"), SV("B"), SV("h"), SV("m"), SV("Om")}, std::chrono::January); + + check_exception("Expected '%' or '}' in the chrono format-string", SV("{:A"), std::chrono::January); + check_exception("The chrono-specs contains a '{'", SV("{:%%{"), std::chrono::January); + check_exception("End of input while parsing the modifier chrono conversion-spec", SV("{:%"), std::chrono::January); + check_exception("End of input while parsing the modifier E", SV("{:%E"), std::chrono::January); + check_exception("End of input while parsing the modifier O", SV("{:%O"), std::chrono::January); + + // Precision not allowed + check_exception("Expected '%' or '}' in the chrono format-string", SV("{:.3}"), std::chrono::January); +#endif +} + +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,198 @@ +//===----------------------------------------------------------------------===// +// 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-01-01"), + SV("{}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{1}}); + check(SV("*1970-01-01*"), + SV("{:*^12}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{1}}); + check(SV("*1970-01-01"), + SV("{:*>11}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{1}}); + + // Invalid month_day + check(SV("1970-00-01 is not a valid date"), + SV("{}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{1}}); + check(SV("*1970-00-01 is not a valid date*"), + SV("{:*^32}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{1}}); + + // Not a leap year + check(SV("1970-02-29 is not a valid date"), + SV("{}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{29}}); +} + +template +static void test_valid_values() { + // *** Invalid day *** + + // Weekday name conversion + 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{0}}); + + // Weekday conversion + check_exception("formatting a weekday needs a valid value", + 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 value", + 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 value", + 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 value", + SV("{:%Ow}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + + // Day of year field + check_exception("formatting a day of year needs a valid value", + SV("{:%j}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + + // Month name conversion + check(SV("Jan"), + SV("{:%b}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + check(SV("Jan"), + SV("{:%h}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + check(SV("January"), + SV("{:%B}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{0}}); + + // *** Invalid month *** + + // Weekday name conversion + 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{1}}); + 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{1}}); + + // Weekday conversion + check_exception("formatting a weekday needs a valid value", + SV("{:%u}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{1}}); + check_exception("formatting a weekday needs a valid value", + SV("{:%w}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{1}}); + check_exception("formatting a weekday needs a valid value", + SV("{:%Ou}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{1}}); + check_exception("formatting a weekday needs a valid value", + SV("{:%Ow}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{1}}); + + // Day of year field + check_exception("formatting a day of year needs a valid value", + SV("{:%j}"), + std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{1}}); + + // Month name conversion + 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{1}}); + 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{1}}); + 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{1}}); + + // *** Invalid year *** + + // Weekday name conversion + 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{1}}); + 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{1}}); + + // Weekday conversion + check_exception("formatting a weekday needs a valid value", + SV("{:%u}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{1}}); + check_exception("formatting a weekday needs a valid value", + SV("{:%w}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{1}}); + check_exception("formatting a weekday needs a valid value", + SV("{:%Ou}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{1}}); + check_exception("formatting a weekday needs a valid value", + SV("{:%Ow}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{1}}); + + // Day of year field + check_exception("formatting a day of year needs a valid value", + SV("{:%j}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{1}}); + + // Month name conversion + check(SV("Jan"), + SV("{:%b}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{1}}); + check(SV("Jan"), + SV("{:%h}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{1}}); + check(SV("January"), + SV("{:%B}"), + std::chrono::year_month_day{std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::day{1}}); +} + +template +static void test() { + test_no_chrono_specs(); + test_valid_values(); +} + +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,200 @@ +//===----------------------------------------------------------------------===// +// 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[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("{:*^16}"), + 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}}}); + + // Invalid month_day + /* + check( SV("1970-00-01 is not a valid date"), SV("{}"),std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + check( SV("*1970-00-01 is not a valid date*"), SV("{:*^32}"),std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + + // Not a leap year + check( SV("1970-02-29 is not a valid date"), SV("{}"),std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{2}}});*/ +} + +template +static void test_valid_values() { + // *** Invalid day *** + /* + // Weekday name conversion + 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{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{1}}}); + + // Weekday conversion + check_exception("formatting a weekday needs a valid value", SV("{:%u}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{1}}}); + check_exception("formatting a weekday needs a valid value", SV("{:%w}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{1}}}); + check_exception("formatting a weekday needs a valid value", SV("{:%Ou}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{1}}}); + check_exception("formatting a weekday needs a valid value", SV("{:%Ow}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{1}}}); + + // Day of year field + check_exception("formatting a day of year needs a valid value", SV("{:%j}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{1}}}); + + // Month name conversion + check( SV("Jan"), SV("{:%b}"),std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{1}}}); + check( SV("Jan"), SV("{:%h}"),std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{1}}}); + check( SV("January"), SV("{:%B}"),std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{1}}}); +*/ + // *** Invalid month *** + + // Weekday name conversion + 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{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + + // Weekday conversion + check_exception( + "formatting a weekday needs a valid value", + 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 value", + 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 value", + 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 value", + SV("{:%Ow}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + + // Day of year field + check_exception( + "formatting a day of year needs a valid value", + SV("{:%j}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + + // Month name conversion + 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("{:%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("{:%B}"), + std::chrono::year_month_day_last{std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::month{0}}}); + + // *** Invalid year *** + + // Weekday name conversion + 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{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + + // Weekday conversion + check_exception( + "formatting a weekday needs a valid value", + 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 weekday needs a valid value", + 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 value", + 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 weekday needs a valid value", + SV("{:%Ow}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + + // Day of year field + check_exception( + "formatting a day of year needs a valid value", + SV("{:%j}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + + // Month name conversion + check( + SV("Jan"), + SV("{:%b}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + check( + SV("Jan"), + SV("{:%h}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); + check( + SV("January"), + SV("{:%B}"), + std::chrono::year_month_day_last{std::chrono::year{-32768}, std::chrono::month_day_last{std::chrono::month{1}}}); +} + +template +static void test() { + test_no_chrono_specs(); + test_valid_values(); +} + +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,297 @@ +//===----------------------------------------------------------------------===// +// 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[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("{:*^17}"), + 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}}); + + // Invalid + check(SV("1970/Jan/Mon[0 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}, 0}}); + check(SV("1970/Jan/8 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{8}, 1}}); + check(SV("1970/0 is not a valid month/Mon[1]"), + SV("{}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + 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}}); +} + +template +static void test_invalid_values() { + // *** Invalid index *** + // + // + // invalid index does not lead to invalid dates... needs more tests +#if 0 + // Weekday name conversion + check( SV("Mon"), SV("{:%a}"),std::chrono::year_month_weekday{std::chrono::year{1970}, std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday{1}, 0}}); + check( SV("Monday"), SV("{:%A}"),std::chrono::year_month_weekday{std::chrono::year{1970}, std::chrono::month{0}, + std::chrono::weekday_indexed{std::chrono::weekday{1}, 0}}); + // Weekday conversion + check( SV("1"), SV("{:%u}"),std::chrono::year_month_weekday{std::chrono::year{1970}, std::chrono::month{0}, + std::chrono::weekday_indexed{std::chrono::weekday{1}, 0}}); + check( SV("1"), SV("{:%w}"),std::chrono::year_month_weekday{std::chrono::year{1970}, std::chrono::month{0}, + std::chrono::weekday_indexed{std::chrono::weekday{1}, 0}}); + check( SV("1"), SV("{:%Ou}"),std::chrono::year_month_weekday{std::chrono::year{1970}, std::chrono::month{0}, + std::chrono::weekday_indexed{std::chrono::weekday{1}, 0}}); + check( SV("1"), SV("{:%Ow}"),std::chrono::year_month_weekday{std::chrono::year{1970}, std::chrono::month{0}, + std::chrono::weekday_indexed{std::chrono::weekday{1}, 0}}); + + // Day of year field + check_exception("formatting a day of year needs a valid value", SV("{:%j}"), + std::chrono::year_month_weekday{std::chrono::year{1970}, std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}); + + // Month name conversion + check( SV("Jan"), SV("{:%b}"),std::chrono::year_month_weekday{std::chrono::year{1970}, std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}); + check( SV("Jan"), SV("{:%h}"),std::chrono::year_month_weekday{std::chrono::year{1970}, std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}); + check( SV("January"), SV("{:%B}"),std::chrono::year_month_weekday{std::chrono::year{1970}, std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday{8}, 0}}); + + // XXX what about an index 5 for a non existing day? + // January 1970 only has 4 mondays + check( SV("January"), SV("{:%F %j}"),std::chrono::year_month_weekday{std::chrono::year{1970}, std::chrono::month{1}, + std::chrono::weekday_indexed{std::chrono::weekday{1}, 5}}); +#endif + // *** Invalid weekday *** + + // Weekday name conversion + 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{8}, 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{8}, 1}}); + + // Weekday conversion + check_exception( + "formatting a weekday needs a valid value", + SV("{:%u}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 1}}); + check_exception( + "formatting a weekday needs a valid value", + SV("{:%w}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 1}}); + check_exception( + "formatting a weekday needs a valid value", + SV("{:%Ou}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 1}}); + check_exception( + "formatting a weekday needs a valid value", + SV("{:%Ow}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 1}}); + + // Day of year field + check_exception( + "formatting a day of year needs a valid value", + SV("{:%j}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 1}}); + + // Month name conversion + check(SV("Jan"), + SV("{:%b}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 1}}); + check(SV("Jan"), + SV("{:%h}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 1}}); + check(SV("January"), + SV("{:%B}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{8}, 1}}); + + // *** Invalid month *** + + // Weekday name conversion + check(SV("Mon"), + SV("{:%a}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check(SV("Monday"), + SV("{:%A}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + // Weekday conversion + check(SV("1"), + 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(SV("1"), + 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(SV("1"), + SV("{:%Ou}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check(SV("1"), + SV("{:%Ow}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + + // Day of year field + check_exception( + "formatting a day of year needs a valid value", + SV("{:%j}"), + std::chrono::year_month_weekday{ + std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + + // Month name conversion + 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 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}}); + + // *** Invalid year *** + + // Weekday name conversion + check( + SV("Mon"), + SV("{:%a}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check( + SV("Monday"), + SV("{:%A}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + + // Weekday conversion + check( + SV("1"), + 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( + SV("1"), + SV("{:%w}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check( + SV("1"), + SV("{:%Ou}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check( + SV("1"), + SV("{:%Ow}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + + // Day of year field + check_exception( + "formatting a day of year needs a valid value", + SV("{:%j}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + + // Month name conversion + check( + SV("Jan"), + SV("{:%b}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check( + SV("Jan"), + SV("{:%h}"), + std::chrono::year_month_weekday{ + std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); + check( + SV("January"), + SV("{:%B}"), + 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() { + test_no_chrono_specs(); + test_invalid_values(); +} + +int main(int, char**) { + test(); + + // add test where year wraps to the next year for all fields + +#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 value", + 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 value", + 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 value", + 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 value", + 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 value", + 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 value", + 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 value", + 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 @@ -144,19 +144,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>(); diff --git a/libcxx/utils/ci/buildkite-pipeline.yml b/libcxx/utils/ci/buildkite-pipeline.yml --- a/libcxx/utils/ci/buildkite-pipeline.yml +++ b/libcxx/utils/ci/buildkite-pipeline.yml @@ -79,23 +79,6 @@ # - wait - - label: "GCC ${GCC_STABLE_VERSION} / C++latest" - command: "libcxx/utils/ci/run-buildbot generic-gcc" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "gcc-${GCC_STABLE_VERSION}" - CXX: "g++-${GCC_STABLE_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - label: "C++2b" command: "libcxx/utils/ci/run-buildbot generic-cxx2b" artifact_paths: @@ -113,841 +96,62 @@ limit: 2 timeout_in_minutes: 120 - - label: "Modular build" - command: "libcxx/utils/ci/run-buildbot generic-modules" + - label: "Clang-cl (DLL)" + command: "bash libcxx/utils/ci/run-buildbot clang-cl-dll" artifact_paths: - "**/test-results.xml" - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" agents: - queue: "libcxx-builders" - os: "linux" + queue: "windows" retry: automatic: - exit_status: -1 # Agent was lost limit: 2 timeout_in_minutes: 120 - - label: "C++11" - command: "libcxx/utils/ci/run-buildbot generic-cxx11" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "C++03" - command: "libcxx/utils/ci/run-buildbot generic-cxx03" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - # - # All other supported configurations of libc++. - # - - wait - - - label: "C++20" + - label: "MacOS x86_64" command: "libcxx/utils/ci/run-buildbot generic-cxx20" artifact_paths: - "**/test-results.xml" - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "C++17" - command: "libcxx/utils/ci/run-buildbot generic-cxx17" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "C++14" - command: "libcxx/utils/ci/run-buildbot generic-cxx14" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - # Tests with the supported compilers. - - label: "GCC ${GCC_STABLE_VERSION} / C++11" - command: "libcxx/utils/ci/run-buildbot generic-gcc-cxx11" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "gcc-${GCC_STABLE_VERSION}" - CXX: "g++-${GCC_STABLE_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Clang 14" - command: "libcxx/utils/ci/run-buildbot generic-cxx2b" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-14" - CXX: "clang++-14" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Clang 15" - command: "libcxx/utils/ci/run-buildbot generic-cxx2b" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-15" - CXX: "clang++-15" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - # Tests with the sanitizers. - - group: "Sanitizers" - steps: - - label: "ASAN" - command: "libcxx/utils/ci/run-buildbot generic-asan" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "TSAN" - command: "libcxx/utils/ci/run-buildbot generic-tsan" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "UBSAN" - command: "libcxx/utils/ci/run-buildbot generic-ubsan" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "MSAN" - command: "libcxx/utils/ci/run-buildbot generic-msan" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - # Tests with the various supported ways to build libc++. - - label: "Bootstrapping build" - command: "libcxx/utils/ci/run-buildbot bootstrapping-build" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - - "**/crash_diagnostics/*" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - LLVM_SYMBOLIZER_PATH: "/usr/bin/llvm-symbolizer-${LLVM_HEAD_VERSION}" - CLANG_CRASH_DIAGNOSTICS_DIR: "crash_diagnostics" agents: queue: "libcxx-builders" - os: "linux" + os: "macos" + arch: "x86_64" retry: automatic: - exit_status: -1 # Agent was lost limit: 2 timeout_in_minutes: 120 - # Tests with various build configurations. - - label: "Static libraries" - command: "libcxx/utils/ci/run-buildbot generic-static" + - label: "AArch64" + command: "libcxx/utils/ci/run-buildbot aarch64" artifact_paths: - "**/test-results.xml" - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" agents: - queue: "libcxx-builders" - os: "linux" + queue: "libcxx-builders-linaro-arm" + arch: "aarch64" retry: automatic: - exit_status: -1 # Agent was lost limit: 2 timeout_in_minutes: 120 - - label: "Shared library with merged ABI and unwinder libraries" - command: "libcxx/utils/ci/run-buildbot generic-merged" + - label: "AIX (32-bit)" + command: "libcxx/utils/ci/run-buildbot aix" artifact_paths: - "**/test-results.xml" - "**/*.abilist" env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" + CC: "clang" + CXX: "clang++" + OBJECT_MODE: "32" agents: - queue: "libcxx-builders" - os: "linux" + queue: libcxx-builders + os: aix retry: automatic: - exit_status: -1 # Agent was lost limit: 2 timeout_in_minutes: 120 - - - label: "Assertions enabled" - command: "libcxx/utils/ci/run-buildbot generic-assertions" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Debug mode" - command: "libcxx/utils/ci/run-buildbot generic-debug-mode" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "No transitive includes" - command: "libcxx/utils/ci/run-buildbot generic-no-transitive-includes" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "With LLVM's libunwind" - command: "libcxx/utils/ci/run-buildbot generic-with_llvm_unwinder" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - group: "Parts disabled" - steps: - - label: "No threads" - command: "libcxx/utils/ci/run-buildbot generic-no-threads" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "No filesystem" - command: "libcxx/utils/ci/run-buildbot generic-no-filesystem" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "No random device" - command: "libcxx/utils/ci/run-buildbot generic-no-random_device" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "No locale" - command: "libcxx/utils/ci/run-buildbot generic-no-localization" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "No Unicode" - command: "libcxx/utils/ci/run-buildbot generic-no-unicode" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "No wide characters" - command: "libcxx/utils/ci/run-buildbot generic-no-wide-characters" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "No experimental features" - command: "libcxx/utils/ci/run-buildbot generic-no-experimental" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "No exceptions" - command: "libcxx/utils/ci/run-buildbot generic-noexceptions" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Unstable ABI" - command: "libcxx/utils/ci/run-buildbot generic-abi-unstable" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - # Other non-testing CI jobs - - label: "Benchmarks" - command: "libcxx/utils/ci/run-buildbot benchmarks" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang-${LLVM_HEAD_VERSION}" - CXX: "clang++-${LLVM_HEAD_VERSION}" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - # Tests on non-Unix platforms - - group: ":windows: Windows" - steps: - - label: "Clang-cl (DLL)" - command: "bash libcxx/utils/ci/run-buildbot clang-cl-dll" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "windows" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Clang-cl (Static)" - command: "bash libcxx/utils/ci/run-buildbot clang-cl-static" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "windows" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Clang-cl (no vcruntime exceptions)" - command: "bash libcxx/utils/ci/run-buildbot clang-cl-no-vcruntime" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "windows" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - - - label: "MinGW (DLL, x86_64)" - command: "bash libcxx/utils/ci/run-buildbot mingw-dll" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "windows" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "MinGW (Static, x86_64)" - command: "bash libcxx/utils/ci/run-buildbot mingw-static" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "windows" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "MinGW (DLL, i686)" - command: "bash libcxx/utils/ci/run-buildbot mingw-dll-i686" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "windows" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - group: ":apple: Apple" - steps: - - label: "MacOS x86_64" - command: "libcxx/utils/ci/run-buildbot generic-cxx20" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders" - os: "macos" - arch: "x86_64" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "MacOS arm64" - command: "libcxx/utils/ci/run-buildbot generic-cxx20" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders" - os: "macos" - arch: "arm64" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - # Build with the configuration we use to generate libc++.dylib on Apple platforms - - label: "Apple system" - command: "libcxx/utils/ci/run-buildbot apple-system" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders" - os: "macos" - arch: "arm64" # This can technically run on any architecture, but we have more resources on arm64 so we pin this job to arm64 - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - # Test back-deployment to older Apple platforms - - label: "Apple back-deployment macosx10.9" - command: "libcxx/utils/ci/run-buildbot apple-system-backdeployment-10.9" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders" - os: "macos" - arch: "x86_64" # We need to use x86_64 for back-deployment CI on this target since macOS didn't support arm64 back then. - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Apple back-deployment macosx10.15" - command: "libcxx/utils/ci/run-buildbot apple-system-backdeployment-10.15" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders" - os: "macos" - arch: "x86_64" # We need to use x86_64 for back-deployment CI on this target since macOS didn't support arm64 back then. - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Apple back-deployment macosx11.0 arm64" - command: "libcxx/utils/ci/run-buildbot apple-system-backdeployment-11.0" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders" - os: "macos" - arch: "arm64" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Apple back-deployment with assertions enabled" - command: "libcxx/utils/ci/run-buildbot apple-system-backdeployment-assertions-11.0" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders" - os: "macos" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - group: "ARM" - steps: - - label: "AArch64" - command: "libcxx/utils/ci/run-buildbot aarch64" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders-linaro-arm" - arch: "aarch64" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "AArch64 -fno-exceptions" - command: "libcxx/utils/ci/run-buildbot aarch64-noexceptions" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders-linaro-arm" - arch: "aarch64" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Armv8" - command: "libcxx/utils/ci/run-buildbot armv8" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders-linaro-arm" - arch: "armv8l" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Armv8 -fno-exceptions" - command: "libcxx/utils/ci/run-buildbot armv8-noexceptions" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders-linaro-arm" - arch: "armv8l" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Armv7" - command: "libcxx/utils/ci/run-buildbot armv7" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders-linaro-arm" - arch: "armv8l" # Compiling for v7, running on v8 hardware - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Armv7 -fno-exceptions" - command: "libcxx/utils/ci/run-buildbot armv7-noexceptions" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders-linaro-arm" - arch: "armv8l" # Compiling for v7, running on v8 hardware - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - group: "AIX" - steps: - - label: "AIX (32-bit)" - command: "libcxx/utils/ci/run-buildbot aix" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang" - CXX: "clang++" - OBJECT_MODE: "32" - agents: - queue: libcxx-builders - os: aix - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "AIX (64-bit)" - command: "libcxx/utils/ci/run-buildbot aix" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - env: - CC: "clang" - CXX: "clang++" - OBJECT_MODE: "64" - agents: - queue: libcxx-builders - os: aix - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120