1105fef5dSMark de Wever //===----------------------------------------------------------------------===// 2*6a54dfbfSLouis Dionne // 3105fef5dSMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4105fef5dSMark de Wever // See https://llvm.org/LICENSE.txt for license information. 5105fef5dSMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6105fef5dSMark de Wever // 7105fef5dSMark de Wever //===----------------------------------------------------------------------===// 8105fef5dSMark de Wever 9105fef5dSMark de Wever // UNSUPPORTED: c++03, c++11, c++14, c++17 10105fef5dSMark de Wever // UNSUPPORTED: no-localization 11520c7fbbSLouis Dionne // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME 12105fef5dSMark de Wever 133d334df5SLouis Dionne // TODO FMT This test should not require std::to_chars(floating-point) 14f0fc8c48SLouis Dionne // XFAIL: availability-fp_to_chars-missing 153d334df5SLouis Dionne 16105fef5dSMark de Wever // REQUIRES: locale.fr_FR.UTF-8 17105fef5dSMark de Wever // REQUIRES: locale.ja_JP.UTF-8 18105fef5dSMark de Wever 19105fef5dSMark de Wever // <chrono> 20105fef5dSMark de Wever 21105fef5dSMark de Wever // template<class charT> struct formatter<chrono::year_month, charT>; 22105fef5dSMark de Wever 23105fef5dSMark de Wever #include <chrono> 24105fef5dSMark de Wever #include <format> 25105fef5dSMark de Wever 26105fef5dSMark de Wever #include <cassert> 27105fef5dSMark de Wever #include <concepts> 28105fef5dSMark de Wever #include <locale> 29105fef5dSMark de Wever #include <iostream> 30105fef5dSMark de Wever #include <type_traits> 31105fef5dSMark de Wever 32105fef5dSMark de Wever #include "formatter_tests.h" 33105fef5dSMark de Wever #include "make_string.h" 34105fef5dSMark de Wever #include "platform_support.h" // locale name macros 35105fef5dSMark de Wever #include "string_literal.h" 36105fef5dSMark de Wever #include "test_macros.h" 37105fef5dSMark de Wever 38105fef5dSMark de Wever template <class CharT> 39105fef5dSMark de Wever static void test_no_chrono_specs() { 40105fef5dSMark de Wever // Valid month 41105fef5dSMark de Wever check(SV("1970/Jan"), SV("{}"), std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{1}}); 42105fef5dSMark de Wever check(SV("*1970/Jan*"), SV("{:*^10}"), std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{1}}); 43105fef5dSMark de Wever check(SV("*1970/Jan"), SV("{:*>9}"), std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{1}}); 44105fef5dSMark de Wever 45105fef5dSMark de Wever // Invalid month_day 46105fef5dSMark de Wever check(SV("1970/0 is not a valid month"), 47105fef5dSMark de Wever SV("{}"), 48105fef5dSMark de Wever std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{0}}); 49105fef5dSMark de Wever check(SV("*1970/0 is not a valid month*"), 50105fef5dSMark de Wever SV("{:*^29}"), 51105fef5dSMark de Wever std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{0}}); 52105fef5dSMark de Wever } 53105fef5dSMark de Wever 54105fef5dSMark de Wever template <class CharT> 55105fef5dSMark de Wever static void test_invalid_values() { 56105fef5dSMark de Wever // Test that %b and %B throw an exception. 57402eb2efSMark de Wever check_exception("Formatting a month name from an invalid month number", 58105fef5dSMark de Wever SV("{:%b}"), 59105fef5dSMark de Wever std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{0}}); 60105fef5dSMark de Wever 61402eb2efSMark de Wever check_exception("Formatting a month name from an invalid month number", 62105fef5dSMark de Wever SV("{:%B}"), 63105fef5dSMark de Wever std::chrono::year_month{std::chrono::year{1970}, std::chrono::month{0}}); 64105fef5dSMark de Wever } 65105fef5dSMark de Wever 66105fef5dSMark de Wever template <class CharT> 67105fef5dSMark de Wever static void test_valid_values() { 68105fef5dSMark de Wever constexpr std::basic_string_view<CharT> fmt = SV( 69105fef5dSMark de Wever "{:" 70105fef5dSMark de Wever "%%b='%b'%t" 71105fef5dSMark de Wever "%%B='%B'%t" 72105fef5dSMark de Wever "%%C='%C'%t" 73105fef5dSMark de Wever "%%h='%h'%t" 74105fef5dSMark de Wever "%%y='%y'%t" 75105fef5dSMark de Wever "%%Y='%Y'%t" 76105fef5dSMark de Wever "%%EC='%EC'%t" 77105fef5dSMark de Wever "%%Ey='%Ey'%t" 78105fef5dSMark de Wever "%%EY='%EY'%t" 79105fef5dSMark de Wever "%%Oy='%Oy'%t" 80105fef5dSMark de Wever "%n}"); 81105fef5dSMark de Wever 82105fef5dSMark de Wever constexpr std::basic_string_view<CharT> lfmt = SV( 83105fef5dSMark de Wever "{:L" 84105fef5dSMark de Wever "%%b='%b'%t" 85105fef5dSMark de Wever "%%B='%B'%t" 86105fef5dSMark de Wever "%%C='%C'%t" 87105fef5dSMark de Wever "%%h='%h'%t" 88105fef5dSMark de Wever "%%y='%y'%t" 89105fef5dSMark de Wever "%%Y='%Y'%t" 90105fef5dSMark de Wever "%%EC='%EC'%t" 91105fef5dSMark de Wever "%%Ey='%Ey'%t" 92105fef5dSMark de Wever "%%EY='%EY'%t" 93105fef5dSMark de Wever "%%Oy='%Oy'%t" 94105fef5dSMark de Wever "%n}"); 95105fef5dSMark de Wever 96105fef5dSMark de Wever const std::locale loc(LOCALE_ja_JP_UTF_8); 97105fef5dSMark de Wever std::locale::global(std::locale(LOCALE_fr_FR_UTF_8)); 98105fef5dSMark de Wever 99105fef5dSMark de Wever // Non localized output using C-locale 100105fef5dSMark de Wever check(SV("%b='Jan'\t" 101105fef5dSMark de Wever "%B='January'\t" 102105fef5dSMark de Wever "%C='19'\t" 103105fef5dSMark de Wever "%h='Jan'\t" 104105fef5dSMark de Wever "%y='70'\t" 105105fef5dSMark de Wever "%Y='1970'\t" 106105fef5dSMark de Wever "%EC='19'\t" 107105fef5dSMark de Wever "%Ey='70'\t" 108105fef5dSMark de Wever "%EY='1970'\t" 109105fef5dSMark de Wever "%Oy='70'\t" 110105fef5dSMark de Wever "\n"), 111105fef5dSMark de Wever fmt, 112105fef5dSMark de Wever std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); 113105fef5dSMark de Wever 114105fef5dSMark de Wever check(SV("%b='May'\t" 115105fef5dSMark de Wever "%B='May'\t" 116105fef5dSMark de Wever "%C='20'\t" 117105fef5dSMark de Wever "%h='May'\t" 118105fef5dSMark de Wever "%y='04'\t" 119105fef5dSMark de Wever "%Y='2004'\t" 120105fef5dSMark de Wever "%EC='20'\t" 121105fef5dSMark de Wever "%Ey='04'\t" 122105fef5dSMark de Wever "%EY='2004'\t" 123105fef5dSMark de Wever "%Oy='04'\t" 124105fef5dSMark de Wever "\n"), 125105fef5dSMark de Wever fmt, 126105fef5dSMark de Wever std::chrono::year_month{std::chrono::year{2004}, std::chrono::May}); 127105fef5dSMark de Wever 128105fef5dSMark de Wever // Use the global locale (fr_FR) 129105fef5dSMark de Wever check(SV( 130105fef5dSMark de Wever #if defined(__APPLE__) 131105fef5dSMark de Wever "%b='jan'\t" 132105fef5dSMark de Wever #else 133105fef5dSMark de Wever "%b='janv.'\t" 134105fef5dSMark de Wever #endif 135105fef5dSMark de Wever "%B='janvier'\t" 136105fef5dSMark de Wever "%C='19'\t" 137105fef5dSMark de Wever #if defined(__APPLE__) 138105fef5dSMark de Wever "%h='jan'\t" 139105fef5dSMark de Wever #else 140105fef5dSMark de Wever "%h='janv.'\t" 141105fef5dSMark de Wever #endif 142105fef5dSMark de Wever "%y='70'\t" 143105fef5dSMark de Wever "%Y='1970'\t" 144105fef5dSMark de Wever "%EC='19'\t" 145105fef5dSMark de Wever "%Ey='70'\t" 146105fef5dSMark de Wever "%EY='1970'\t" 147105fef5dSMark de Wever "%Oy='70'\t" 148105fef5dSMark de Wever "\n"), 149105fef5dSMark de Wever lfmt, 150105fef5dSMark de Wever std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); 151105fef5dSMark de Wever 152105fef5dSMark de Wever check(SV("%b='mai'\t" 153105fef5dSMark de Wever "%B='mai'\t" 154105fef5dSMark de Wever "%C='20'\t" 155105fef5dSMark de Wever "%h='mai'\t" 156105fef5dSMark de Wever "%y='04'\t" 157105fef5dSMark de Wever "%Y='2004'\t" 158105fef5dSMark de Wever "%EC='20'\t" 159105fef5dSMark de Wever "%Ey='04'\t" 160105fef5dSMark de Wever "%EY='2004'\t" 161105fef5dSMark de Wever "%Oy='04'\t" 162105fef5dSMark de Wever "\n"), 163105fef5dSMark de Wever lfmt, 164105fef5dSMark de Wever std::chrono::year_month{std::chrono::year{2004}, std::chrono::May}); 165105fef5dSMark de Wever 166105fef5dSMark de Wever // Use supplied locale (ja_JP) 167105fef5dSMark de Wever check(loc, 168105fef5dSMark de Wever SV( 169105fef5dSMark de Wever #if defined(_WIN32) 170105fef5dSMark de Wever "%b='1'\t" 171105fef5dSMark de Wever #elif defined(_AIX) // defined(_WIN32) 172105fef5dSMark de Wever "%b='1月'\t" 173105fef5dSMark de Wever #elif defined(__APPLE__) // defined(_WIN32) 174105fef5dSMark de Wever "%b=' 1'\t" 175105fef5dSMark de Wever #else // defined(_WIN32) 176105fef5dSMark de Wever "%b=' 1月'\t" 177105fef5dSMark de Wever #endif // defined(_WIN32) 178105fef5dSMark de Wever "%B='1月'\t" 179105fef5dSMark de Wever "%C='19'\t" 180105fef5dSMark de Wever #if defined(_WIN32) 181105fef5dSMark de Wever "%h='1'\t" 182105fef5dSMark de Wever #elif defined(_AIX) // defined(_WIN32) 183105fef5dSMark de Wever "%h='1月'\t" 184105fef5dSMark de Wever #elif defined(__APPLE__) // defined(_WIN32) 185105fef5dSMark de Wever "%h=' 1'\t" 186105fef5dSMark de Wever #else // defined(_WIN32) 187105fef5dSMark de Wever "%h=' 1月'\t" 188105fef5dSMark de Wever #endif // defined(_WIN32) 189105fef5dSMark de Wever "%y='70'\t" 190105fef5dSMark de Wever "%Y='1970'\t" 1918f01029bSMark de Wever #if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 192105fef5dSMark de Wever "%EC='19'\t" 193105fef5dSMark de Wever "%Ey='70'\t" 194105fef5dSMark de Wever "%EY='1970'\t" 195105fef5dSMark de Wever "%Oy='70'\t" 1968f01029bSMark de Wever #else // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 197105fef5dSMark de Wever "%EC='昭和'\t" 198105fef5dSMark de Wever "%Ey='45'\t" 199105fef5dSMark de Wever "%EY='昭和45年'\t" 200105fef5dSMark de Wever "%Oy='七十'\t" 2018f01029bSMark de Wever #endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 202105fef5dSMark de Wever "\n"), 203105fef5dSMark de Wever lfmt, 204105fef5dSMark de Wever std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); 205105fef5dSMark de Wever 206105fef5dSMark de Wever check(loc, 207105fef5dSMark de Wever SV( 208105fef5dSMark de Wever 209105fef5dSMark de Wever #if defined(_WIN32) 210105fef5dSMark de Wever "%b='5'\t" 211105fef5dSMark de Wever #elif defined(_AIX) // defined(_WIN32) 212105fef5dSMark de Wever "%b='5月'\t" 213105fef5dSMark de Wever #elif defined(__APPLE__) // defined(_WIN32) 214105fef5dSMark de Wever "%b=' 5'\t" 215105fef5dSMark de Wever #else // defined(_WIN32) 216105fef5dSMark de Wever "%b=' 5月'\t" 217105fef5dSMark de Wever #endif // defined(_WIN32) 218105fef5dSMark de Wever "%B='5月'\t" 219105fef5dSMark de Wever "%C='20'\t" 220105fef5dSMark de Wever #if defined(_WIN32) 221105fef5dSMark de Wever "%h='5'\t" 222105fef5dSMark de Wever #elif defined(_AIX) // defined(_WIN32) 223105fef5dSMark de Wever "%h='5月'\t" 224105fef5dSMark de Wever #elif defined(__APPLE__) // defined(_WIN32) 225105fef5dSMark de Wever "%h=' 5'\t" 226105fef5dSMark de Wever #else // defined(_WIN32) 227105fef5dSMark de Wever "%h=' 5月'\t" 228105fef5dSMark de Wever #endif // defined(_WIN32) 229105fef5dSMark de Wever "%y='04'\t" 230105fef5dSMark de Wever "%Y='2004'\t" 2318f01029bSMark de Wever #if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 232105fef5dSMark de Wever "%EC='20'\t" 233105fef5dSMark de Wever "%Ey='04'\t" 234105fef5dSMark de Wever "%EY='2004'\t" 235105fef5dSMark de Wever "%Oy='04'\t" 2368f01029bSMark de Wever #else // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 237105fef5dSMark de Wever "%EC='平成'\t" 238105fef5dSMark de Wever "%Ey='16'\t" 239105fef5dSMark de Wever "%EY='平成16年'\t" 240105fef5dSMark de Wever "%Oy='四'\t" 2418f01029bSMark de Wever #endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 242105fef5dSMark de Wever "\n"), 243105fef5dSMark de Wever lfmt, 244105fef5dSMark de Wever std::chrono::year_month{std::chrono::year{2004}, std::chrono::May}); 245105fef5dSMark de Wever 246105fef5dSMark de Wever std::locale::global(std::locale::classic()); 247105fef5dSMark de Wever } 248105fef5dSMark de Wever 249105fef5dSMark de Wever template <class CharT> 250105fef5dSMark de Wever static void test() { 251105fef5dSMark de Wever test_no_chrono_specs<CharT>(); 252105fef5dSMark de Wever test_invalid_values<CharT>(); 253105fef5dSMark de Wever test_valid_values<CharT>(); 254105fef5dSMark de Wever 255105fef5dSMark de Wever check_invalid_types<CharT>( 256105fef5dSMark de Wever {SV("b"), SV("B"), SV("C"), SV("EC"), SV("Ey"), SV("EY"), SV("h"), SV("m"), SV("Om"), SV("Oy"), SV("y"), SV("Y")}, 257105fef5dSMark de Wever std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); 258105fef5dSMark de Wever 259402eb2efSMark de Wever check_exception("The format specifier expects a '%' or a '}'", 260105fef5dSMark de Wever SV("{:A"), 261105fef5dSMark de Wever std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); 262402eb2efSMark de Wever check_exception("The chrono specifiers contain a '{'", 263105fef5dSMark de Wever SV("{:%%{"), 264105fef5dSMark de Wever std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); 265402eb2efSMark de Wever check_exception("End of input while parsing a conversion specifier", 266105fef5dSMark de Wever SV("{:%"), 267105fef5dSMark de Wever std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); 268105fef5dSMark de Wever check_exception("End of input while parsing the modifier E", 269105fef5dSMark de Wever SV("{:%E"), 270105fef5dSMark de Wever std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); 271105fef5dSMark de Wever check_exception("End of input while parsing the modifier O", 272105fef5dSMark de Wever SV("{:%O"), 273105fef5dSMark de Wever std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); 274105fef5dSMark de Wever 275105fef5dSMark de Wever // Precision not allowed 276402eb2efSMark de Wever check_exception("The format specifier expects a '%' or a '}'", 277105fef5dSMark de Wever SV("{:.3}"), 278105fef5dSMark de Wever std::chrono::year_month{std::chrono::year{1970}, std::chrono::January}); 279105fef5dSMark de Wever } 280105fef5dSMark de Wever 281105fef5dSMark de Wever int main(int, char**) { 282105fef5dSMark de Wever test<char>(); 283105fef5dSMark de Wever 284105fef5dSMark de Wever #ifndef TEST_HAS_NO_WIDE_CHARACTERS 285105fef5dSMark de Wever test<wchar_t>(); 286105fef5dSMark de Wever #endif 287105fef5dSMark de Wever 288105fef5dSMark de Wever return 0; 289105fef5dSMark de Wever } 290