1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14, c++17 10 // UNSUPPORTED: no-localization 11 // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME 12 13 // TODO FMT This test should not require std::to_chars(floating-point) 14 // XFAIL: availability-fp_to_chars-missing 15 16 // REQUIRES: locale.fr_FR.UTF-8 17 // REQUIRES: locale.ja_JP.UTF-8 18 19 // <chrono> 20 21 // template<class charT> struct formatter<chrono::year_month_weekday, charT>; 22 23 #include <chrono> 24 #include <format> 25 26 #include <cassert> 27 #include <concepts> 28 #include <locale> 29 #include <iostream> 30 #include <type_traits> 31 32 #include "formatter_tests.h" 33 #include "make_string.h" 34 #include "platform_support.h" // locale name macros 35 #include "string_literal.h" 36 #include "test_macros.h" 37 38 template <class CharT> 39 static void test_no_chrono_specs() { 40 // Valid year, valid month, valid day, valid index 41 check(SV("1970/Jan/Mon[1]"), 42 SV("{}"), 43 std::chrono::year_month_weekday{ 44 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 45 check(SV("*1970/Jan/Mon[1]"), 46 SV("{:*>16}"), 47 std::chrono::year_month_weekday{ 48 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 49 check(SV("*1970/Jan/Mon[1]*"), 50 SV("{:*^17}"), 51 std::chrono::year_month_weekday{ 52 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 53 54 // Valid year, valid month, valid day, invalid index 55 check(SV("1970/Jan/Mon[7 is not a valid index]"), 56 SV("{}"), 57 std::chrono::year_month_weekday{ 58 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}}); 59 60 // Valid year, valid month, invalid day, valid index 61 check(SV("1970/Jan/13 is not a valid weekday[1]"), 62 SV("{}"), 63 std::chrono::year_month_weekday{ 64 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); 65 66 // Valid year, valid month, invalid day, invalid index 67 check(SV("1970/Jan/13 is not a valid weekday[7 is not a valid index]"), 68 SV("{}"), 69 std::chrono::year_month_weekday{ 70 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 7}}); 71 72 // Valid year, invalid month, valid day, invalid index 73 check(SV("1970/0 is not a valid month/Mon[7 is not a valid index]"), 74 SV("{}"), 75 std::chrono::year_month_weekday{ 76 std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}}); 77 78 // Valid year, invalid month, invalid day, valid index 79 check(SV("1970/0 is not a valid month/13 is not a valid weekday[1]"), 80 SV("{}"), 81 std::chrono::year_month_weekday{ 82 std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); 83 84 // Valid year, invalid month, invalid day, invalid index 85 check(SV("1970/0 is not a valid month/13 is not a valid weekday[7 is not a valid index]"), 86 SV("{}"), 87 std::chrono::year_month_weekday{ 88 std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 7}}); 89 90 // Invalid year, valid month, valid day, valid index 91 check( 92 SV("-32768 is not a valid year/Jan/Mon[1]"), 93 SV("{}"), 94 std::chrono::year_month_weekday{ 95 std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 96 97 // Invalid year, valid month, valid day, invalid index 98 check( 99 SV("-32768 is not a valid year/Jan/Mon[7 is not a valid index]"), 100 SV("{}"), 101 std::chrono::year_month_weekday{ 102 std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}}); 103 104 // Invalid year, valid month, invalid day, valid index 105 check( 106 SV("-32768 is not a valid year/Jan/13 is not a valid weekday[1]"), 107 SV("{}"), 108 std::chrono::year_month_weekday{ 109 std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); 110 111 // Invalid year, valid month, invalid day, invalid index 112 check( 113 SV("-32768 is not a valid year/Jan/13 is not a valid weekday[7 is not a valid index]"), 114 SV("{}"), 115 std::chrono::year_month_weekday{ 116 std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 7}}); 117 118 // Invalid year, invalid month, valid day, invalid index 119 check( 120 SV("-32768 is not a valid year/0 is not a valid month/Mon[7 is not a valid index]"), 121 SV("{}"), 122 std::chrono::year_month_weekday{ 123 std::chrono::year{-32768}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}}); 124 125 // Invalid year, invalid month, invalid day, valid index 126 check( 127 SV("-32768 is not a valid year/0 is not a valid month/13 is not a valid weekday[1]"), 128 SV("{}"), 129 std::chrono::year_month_weekday{ 130 std::chrono::year{-32768}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); 131 132 // Invalid year, invalid month, invalid day, invalid index 133 check( 134 SV("-32768 is not a valid year/0 is not a valid month/13 is not a valid weekday[7 is not a valid index]"), 135 SV("{}"), 136 std::chrono::year_month_weekday{ 137 std::chrono::year{-32768}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 7}}); 138 } 139 140 // TODO FMT Should x throw? 141 template <class CharT> 142 static void test_invalid_values() { 143 // Test that %a, %A, %b, %B, %h, %j, %u, %U, %V, %w, %W, %Ou, %OU, %OV, %Ow, and %OW throw an exception. 144 check_exception( 145 "Formatting a weekday name needs a valid weekday", 146 SV("{:%a}"), 147 std::chrono::year_month_weekday{ 148 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); 149 150 check_exception( 151 "Formatting a weekday name needs a valid weekday", 152 SV("{:%A}"), 153 std::chrono::year_month_weekday{ 154 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); 155 156 check_exception( 157 "Formatting a month name from an invalid month number", 158 SV("{:%b}"), 159 std::chrono::year_month_weekday{ 160 std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 161 162 check_exception( 163 "Formatting a month name from an invalid month number", 164 SV("{:%B}"), 165 std::chrono::year_month_weekday{ 166 std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 167 168 check_exception( 169 "Formatting a month name from an invalid month number", 170 SV("{:%h}"), 171 std::chrono::year_month_weekday{ 172 std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 173 174 check_exception( 175 "Formatting a day of year needs a valid date", 176 SV("{:%j}"), 177 std::chrono::year_month_weekday{ 178 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}}); 179 check_exception( 180 "Formatting a day of year needs a valid date", 181 SV("{:%j}"), 182 std::chrono::year_month_weekday{ 183 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); 184 check_exception( 185 "Formatting a day of year needs a valid date", 186 SV("{:%j}"), 187 std::chrono::year_month_weekday{ 188 std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 189 check_exception( 190 "Formatting a day of year needs a valid date", 191 SV("{:%j}"), 192 std::chrono::year_month_weekday{ 193 std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 194 195 check_exception( 196 "Formatting a weekday needs a valid weekday", 197 SV("{:%u}"), 198 std::chrono::year_month_weekday{ 199 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); 200 201 check_exception( 202 "Formatting a week of year needs a valid date", 203 SV("{:%U}"), 204 std::chrono::year_month_weekday{ 205 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}}); 206 check_exception( 207 "Formatting a week of year needs a valid date", 208 SV("{:%U}"), 209 std::chrono::year_month_weekday{ 210 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); 211 check_exception( 212 "Formatting a week of year needs a valid date", 213 SV("{:%U}"), 214 std::chrono::year_month_weekday{ 215 std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 216 check_exception( 217 "Formatting a week of year needs a valid date", 218 SV("{:%U}"), 219 std::chrono::year_month_weekday{ 220 std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 221 222 check_exception( 223 "Formatting a week of year needs a valid date", 224 SV("{:%V}"), 225 std::chrono::year_month_weekday{ 226 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}}); 227 check_exception( 228 "Formatting a week of year needs a valid date", 229 SV("{:%V}"), 230 std::chrono::year_month_weekday{ 231 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); 232 check_exception( 233 "Formatting a week of year needs a valid date", 234 SV("{:%V}"), 235 std::chrono::year_month_weekday{ 236 std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 237 check_exception( 238 "Formatting a week of year needs a valid date", 239 SV("{:%V}"), 240 std::chrono::year_month_weekday{ 241 std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 242 243 check_exception( 244 "Formatting a weekday needs a valid weekday", 245 SV("{:%w}"), 246 std::chrono::year_month_weekday{ 247 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); 248 249 check_exception( 250 "Formatting a week of year needs a valid date", 251 SV("{:%W}"), 252 std::chrono::year_month_weekday{ 253 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 7}}); 254 check_exception( 255 "Formatting a week of year needs a valid date", 256 SV("{:%W}"), 257 std::chrono::year_month_weekday{ 258 std::chrono::year{1970}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{13}, 1}}); 259 check_exception( 260 "Formatting a week of year needs a valid date", 261 SV("{:%W}"), 262 std::chrono::year_month_weekday{ 263 std::chrono::year{1970}, std::chrono::month{0}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 264 check_exception( 265 "Formatting a week of year needs a valid date", 266 SV("{:%W}"), 267 std::chrono::year_month_weekday{ 268 std::chrono::year{-32768}, std::chrono::month{1}, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 269 } 270 271 template <class CharT> 272 static void test_valid_md_values() { 273 constexpr std::basic_string_view<CharT> fmt = 274 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}"); 275 constexpr std::basic_string_view<CharT> lfmt = 276 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}"); 277 278 const std::locale loc(LOCALE_ja_JP_UTF_8); 279 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8)); 280 281 // Non localized output using C-locale 282 283 check(SV("%b='Jan'\t%B='January'\t%h='Jan'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), 284 fmt, 285 std::chrono::year_month_weekday{ 286 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); 287 check(SV("%b='Dec'\t%B='December'\t%h='Dec'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"), 288 fmt, 289 std::chrono::year_month_weekday{ 290 std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}}); 291 292 // Use the global locale (fr_FR) 293 #if defined(__APPLE__) 294 check(SV("%b='jan'\t%B='janvier'\t%h='jan'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), 295 lfmt, 296 std::chrono::year_month_weekday{ 297 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); 298 299 check(SV("%b='déc'\t%B='décembre'\t%h='déc'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"), 300 lfmt, 301 std::chrono::year_month_weekday{ 302 std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}}); 303 304 #else // defined(__APPLE__) 305 check(SV("%b='janv.'\t%B='janvier'\t%h='janv.'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), 306 lfmt, 307 std::chrono::year_month_weekday{ 308 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); 309 check(SV("%b='déc.'\t%B='décembre'\t%h='déc.'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"), 310 lfmt, 311 std::chrono::year_month_weekday{ 312 std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}}); 313 314 #endif // defined(__APPLE__) 315 316 // Use supplied locale (ja_JP) 317 #if defined(_WIN32) 318 check(loc, 319 SV("%b='1'\t%B='1月'\t%h='1'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), 320 lfmt, 321 std::chrono::year_month_weekday{ 322 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); 323 324 check(loc, 325 SV("%b='12'\t%B='12月'\t%h='12'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"), 326 lfmt, 327 std::chrono::year_month_weekday{ 328 std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}}); 329 330 #elif defined(_AIX) // defined(_WIN32) 331 check(loc, 332 SV("%b='1月'\t%B='1月'\t%h='1月'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), 333 lfmt, 334 std::chrono::year_month_weekday{ 335 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); 336 337 check(loc, 338 SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"), 339 lfmt, 340 std::chrono::year_month_weekday{ 341 std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}}); 342 343 #elif defined(__APPLE__) // defined(_WIN32) 344 check(loc, 345 SV("%b=' 1'\t%B='1月'\t%h=' 1'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), 346 lfmt, 347 std::chrono::year_month_weekday{ 348 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); 349 350 check(loc, 351 SV("%b='12'\t%B='12月'\t%h='12'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"), 352 lfmt, 353 std::chrono::year_month_weekday{ 354 std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}}); 355 356 #elif defined(__FreeBSD__) // defined(_WIN32) 357 check(loc, 358 SV("%b=' 1月'\t%B='1月'\t%h=' 1月'\t%m='01'\t%Om='01'\t%d='01'\t%e=' 1'\t%Od='01'\t%Oe=' 1'\n"), 359 lfmt, 360 std::chrono::year_month_weekday{ 361 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); 362 363 check(loc, 364 SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='12'\t%d='20'\t%e='20'\t%Od='20'\t%Oe='20'\n"), 365 lfmt, 366 std::chrono::year_month_weekday{ 367 std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}}); 368 #else // defined(_WIN32) 369 check(loc, 370 SV("%b=' 1月'\t%B='1月'\t%h=' 1月'\t%m='01'\t%Om='一'\t%d='01'\t%e=' 1'\t%Od='一'\t%Oe='一'\n"), 371 lfmt, 372 std::chrono::year_month_weekday{ 373 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); 374 375 check(loc, 376 SV("%b='12月'\t%B='12月'\t%h='12月'\t%m='12'\t%Om='十二'\t%d='20'\t%e='20'\t%Od='二十'\t%Oe='二十'\n"), 377 lfmt, 378 std::chrono::year_month_weekday{ 379 std::chrono::year{1970}, std::chrono::December, std::chrono::weekday_indexed{std::chrono::weekday{7}, 3}}); 380 381 #endif // defined(_WIN32) 382 383 std::locale::global(std::locale::classic()); 384 } 385 386 template <class CharT> 387 static void test_valid_ymd_values() { 388 constexpr std::basic_string_view<CharT> fmt = SV( 389 "{:" 390 "%%C='%C'%t" 391 "%%D='%D'%t" 392 "%%F='%F'%t" 393 "%%j='%j'%t" 394 "%%g='%g'%t" 395 "%%G='%G'%t" 396 "%%u='%u'%t" 397 "%%U='%U'%t" 398 "%%V='%V'%t" 399 "%%w='%w'%t" 400 "%%W='%W'%t" 401 "%%x='%x'%t" 402 "%%y='%y'%t" 403 "%%Y='%Y'%t" 404 "%%Ex='%Ex'%t" 405 "%%EC='%EC'%t" 406 "%%Ey='%Ey'%t" 407 "%%EY='%EY'%t" 408 "%%Ou='%Ou'%t" 409 "%%OU='%OU'%t" 410 "%%OV='%OV'%t" 411 "%%Ow='%Ow'%t" 412 "%%OW='%OW'%t" 413 "%%Oy='%Oy'%t" 414 "%n}"); 415 416 constexpr std::basic_string_view<CharT> lfmt = SV( 417 "{:L" 418 "%%C='%C'%t" 419 "%%D='%D'%t" 420 "%%F='%F'%t" 421 "%%j='%j'%t" 422 "%%g='%g'%t" 423 "%%G='%G'%t" 424 "%%u='%u'%t" 425 "%%U='%U'%t" 426 "%%V='%V'%t" 427 "%%w='%w'%t" 428 "%%W='%W'%t" 429 "%%x='%x'%t" 430 "%%y='%y'%t" 431 "%%Y='%Y'%t" 432 "%%Ex='%Ex'%t" 433 "%%EC='%EC'%t" 434 "%%Ey='%Ey'%t" 435 "%%EY='%EY'%t" 436 "%%Ou='%Ou'%t" 437 "%%OU='%OU'%t" 438 "%%OV='%OV'%t" 439 "%%Ow='%Ow'%t" 440 "%%OW='%OW'%t" 441 "%%Oy='%Oy'%t" 442 "%n}"); 443 444 const std::locale loc(LOCALE_ja_JP_UTF_8); 445 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8)); 446 447 // Non localized output using C-locale 448 check( 449 SV("%C='19'\t" 450 "%D='01/01/70'\t" 451 "%F='1970-01-01'\t" 452 "%j='001'\t" 453 "%g='70'\t" 454 "%G='1970'\t" 455 "%u='4'\t" 456 "%U='00'\t" 457 "%V='01'\t" 458 "%w='4'\t" 459 "%W='00'\t" 460 "%x='01/01/70'\t" 461 "%y='70'\t" 462 "%Y='1970'\t" 463 "%Ex='01/01/70'\t" 464 "%EC='19'\t" 465 "%Ey='70'\t" 466 "%EY='1970'\t" 467 "%Ou='4'\t" 468 "%OU='00'\t" 469 "%OV='01'\t" 470 "%Ow='4'\t" 471 "%OW='00'\t" 472 "%Oy='70'\t" 473 "\n"), 474 fmt, 475 std::chrono::year_month_weekday{ 476 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); 477 478 check( 479 SV("%C='20'\t" 480 "%D='05/29/04'\t" 481 "%F='2004-05-29'\t" 482 "%j='150'\t" 483 "%g='04'\t" 484 "%G='2004'\t" 485 "%u='6'\t" 486 "%U='21'\t" 487 "%V='22'\t" 488 "%w='6'\t" 489 "%W='21'\t" 490 "%x='05/29/04'\t" 491 "%y='04'\t" 492 "%Y='2004'\t" 493 "%Ex='05/29/04'\t" 494 "%EC='20'\t" 495 "%Ey='04'\t" 496 "%EY='2004'\t" 497 "%Ou='6'\t" 498 "%OU='21'\t" 499 "%OV='22'\t" 500 "%Ow='6'\t" 501 "%OW='21'\t" 502 "%Oy='04'\t" 503 "\n"), 504 fmt, 505 std::chrono::year_month_weekday{ 506 std::chrono::year{2004}, std::chrono::May, std::chrono::weekday_indexed{std::chrono::weekday{6}, 5}}); 507 508 // Use the global locale (fr_FR) 509 check( 510 SV("%C='19'\t" 511 "%D='01/01/70'\t" 512 "%F='1970-01-01'\t" 513 "%j='001'\t" 514 "%g='70'\t" 515 "%G='1970'\t" 516 "%u='4'\t" 517 "%U='00'\t" 518 "%V='01'\t" 519 "%w='4'\t" 520 "%W='00'\t" 521 #if defined(__APPLE__) || defined(__FreeBSD__) 522 "%x='01.01.1970'\t" 523 #else 524 "%x='01/01/1970'\t" 525 #endif 526 "%y='70'\t" 527 "%Y='1970'\t" 528 #if defined(__APPLE__) || defined(__FreeBSD__) 529 "%Ex='01.01.1970'\t" 530 #else 531 "%Ex='01/01/1970'\t" 532 #endif 533 "%EC='19'\t" 534 "%Ey='70'\t" 535 "%EY='1970'\t" 536 "%Ou='4'\t" 537 "%OU='00'\t" 538 "%OV='01'\t" 539 "%Ow='4'\t" 540 "%OW='00'\t" 541 "%Oy='70'\t" 542 "\n"), 543 lfmt, 544 std::chrono::year_month_weekday{ 545 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); 546 547 check( 548 SV("%C='20'\t" 549 "%D='05/29/04'\t" 550 "%F='2004-05-29'\t" 551 "%j='150'\t" 552 "%g='04'\t" 553 "%G='2004'\t" 554 "%u='6'\t" 555 "%U='21'\t" 556 "%V='22'\t" 557 "%w='6'\t" 558 "%W='21'\t" 559 #if defined(__APPLE__) || defined(__FreeBSD__) 560 "%x='29.05.2004'\t" 561 #else 562 "%x='29/05/2004'\t" 563 #endif 564 "%y='04'\t" 565 "%Y='2004'\t" 566 #if defined(__APPLE__) || defined(__FreeBSD__) 567 "%Ex='29.05.2004'\t" 568 #else 569 "%Ex='29/05/2004'\t" 570 #endif 571 "%EC='20'\t" 572 "%Ey='04'\t" 573 "%EY='2004'\t" 574 "%Ou='6'\t" 575 "%OU='21'\t" 576 "%OV='22'\t" 577 "%Ow='6'\t" 578 "%OW='21'\t" 579 "%Oy='04'\t" 580 "\n"), 581 lfmt, 582 std::chrono::year_month_weekday{ 583 std::chrono::year{2004}, std::chrono::May, std::chrono::weekday_indexed{std::chrono::weekday{6}, 5}}); 584 585 // Use supplied locale (ja_JP) 586 check( 587 loc, 588 SV("%C='19'\t" 589 "%D='01/01/70'\t" 590 "%F='1970-01-01'\t" 591 "%j='001'\t" 592 "%g='70'\t" 593 "%G='1970'\t" 594 "%u='4'\t" 595 "%U='00'\t" 596 "%V='01'\t" 597 "%w='4'\t" 598 "%W='00'\t" 599 #if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 600 "%x='1970/01/01'\t" 601 #else // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 602 "%x='1970年01月01日'\t" 603 #endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 604 "%y='70'\t" 605 "%Y='1970'\t" 606 #if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 607 "%Ex='1970/01/01'\t" 608 "%EC='19'\t" 609 "%Ey='70'\t" 610 "%EY='1970'\t" 611 "%Ou='4'\t" 612 "%OU='00'\t" 613 "%OV='01'\t" 614 "%Ow='4'\t" 615 "%OW='00'\t" 616 "%Oy='70'\t" 617 #else // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 618 "%Ex='昭和45年01月01日'\t" 619 "%EC='昭和'\t" 620 "%Ey='45'\t" 621 "%EY='昭和45年'\t" 622 "%Ou='四'\t" 623 "%OU='〇'\t" 624 "%OV='一'\t" 625 "%Ow='四'\t" 626 "%OW='〇'\t" 627 "%Oy='七十'\t" 628 #endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 629 "\n"), 630 lfmt, 631 std::chrono::year_month_weekday{ 632 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{4}, 1}}); 633 634 check( 635 loc, 636 SV("%C='20'\t" 637 "%D='05/29/04'\t" 638 "%F='2004-05-29'\t" 639 "%j='150'\t" 640 "%g='04'\t" 641 "%G='2004'\t" 642 "%u='6'\t" 643 "%U='21'\t" 644 "%V='22'\t" 645 "%w='6'\t" 646 "%W='21'\t" 647 #if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 648 "%x='2004/05/29'\t" 649 #else // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 650 "%x='2004年05月29日'\t" 651 #endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 652 "%y='04'\t" 653 "%Y='2004'\t" 654 #if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 655 "%Ex='2004/05/29'\t" 656 "%EC='20'\t" 657 "%Ey='04'\t" 658 "%EY='2004'\t" 659 "%Ou='6'\t" 660 "%OU='21'\t" 661 "%OV='22'\t" 662 "%Ow='6'\t" 663 "%OW='21'\t" 664 "%Oy='04'\t" 665 #else // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 666 "%Ex='平成16年05月29日'\t" 667 "%EC='平成'\t" 668 "%Ey='16'\t" 669 "%EY='平成16年'\t" 670 "%Ou='六'\t" 671 "%OU='二十一'\t" 672 "%OV='二十二'\t" 673 "%Ow='六'\t" 674 "%OW='二十一'\t" 675 "%Oy='四'\t" 676 #endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 677 "\n"), 678 lfmt, 679 std::chrono::year_month_weekday{ 680 std::chrono::year{2004}, std::chrono::May, std::chrono::weekday_indexed{std::chrono::weekday{6}, 5}}); 681 682 std::locale::global(std::locale::classic()); 683 } 684 685 template <class CharT> 686 static void test_valid_values() { 687 // Fields only using month and day. 688 test_valid_md_values<CharT>(); 689 // Fields only using year, month, and day. 690 test_valid_ymd_values<CharT>(); 691 } 692 693 template <class CharT> 694 static void test() { 695 test_no_chrono_specs<CharT>(); 696 test_invalid_values<CharT>(); 697 test_valid_values<CharT>(); 698 check_invalid_types<CharT>( 699 {SV("a"), SV("A"), SV("b"), SV("B"), SV("C"), SV("d"), SV("D"), SV("e"), SV("EC"), 700 SV("Ex"), SV("Ey"), SV("EY"), SV("F"), SV("g"), SV("G"), SV("h"), SV("j"), SV("m"), 701 SV("Od"), SV("Oe"), SV("Om"), SV("Ou"), SV("OU"), SV("OV"), SV("Ow"), SV("OW"), SV("Oy"), 702 SV("u"), SV("U"), SV("V"), SV("w"), SV("W"), SV("x"), SV("y"), SV("Y")}, 703 std::chrono::year_month_weekday{ 704 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 705 706 check_exception( 707 "The format specifier expects a '%' or a '}'", 708 SV("{:A"), 709 std::chrono::year_month_weekday{ 710 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 711 check_exception( 712 "The chrono specifiers contain a '{'", 713 SV("{:%%{"), 714 std::chrono::year_month_weekday{ 715 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 716 check_exception( 717 "End of input while parsing a conversion specifier", 718 SV("{:%"), 719 std::chrono::year_month_weekday{ 720 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 721 check_exception( 722 "End of input while parsing the modifier E", 723 SV("{:%E"), 724 std::chrono::year_month_weekday{ 725 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 726 check_exception( 727 "End of input while parsing the modifier O", 728 SV("{:%O"), 729 std::chrono::year_month_weekday{ 730 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 731 732 // Precision not allowed 733 check_exception( 734 "The format specifier expects a '%' or a '}'", 735 SV("{:.3}"), 736 std::chrono::year_month_weekday{ 737 std::chrono::year{1970}, std::chrono::January, std::chrono::weekday_indexed{std::chrono::weekday{1}, 1}}); 738 } 739 740 int main(int, char**) { 741 test<char>(); 742 743 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 744 test<wchar_t>(); 745 #endif 746 747 return 0; 748 } 749