13eb4f16bSMark de Wever //===----------------------------------------------------------------------===// 2*6a54dfbfSLouis Dionne // 33eb4f16bSMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43eb4f16bSMark de Wever // See https://llvm.org/LICENSE.txt for license information. 53eb4f16bSMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63eb4f16bSMark de Wever // 73eb4f16bSMark de Wever //===----------------------------------------------------------------------===// 83eb4f16bSMark de Wever 93eb4f16bSMark de Wever // UNSUPPORTED: c++03, c++11, c++14, c++17 103eb4f16bSMark de Wever // UNSUPPORTED: no-localization 11520c7fbbSLouis Dionne // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME 123b00bae9SLouis Dionne 133d334df5SLouis Dionne // TODO FMT This test should not require std::to_chars(floating-point) 14f0fc8c48SLouis Dionne // XFAIL: availability-fp_to_chars-missing 153d334df5SLouis Dionne 163eb4f16bSMark de Wever // REQUIRES: locale.fr_FR.UTF-8 173eb4f16bSMark de Wever // REQUIRES: locale.ja_JP.UTF-8 183eb4f16bSMark de Wever 193eb4f16bSMark de Wever // <chrono> 203eb4f16bSMark de Wever 213eb4f16bSMark de Wever // template<class charT> struct formatter<chrono::year, charT>; 223eb4f16bSMark de Wever 233eb4f16bSMark de Wever #include <chrono> 243eb4f16bSMark de Wever #include <format> 253eb4f16bSMark de Wever 263eb4f16bSMark de Wever #include <cassert> 273eb4f16bSMark de Wever #include <concepts> 283eb4f16bSMark de Wever #include <locale> 293eb4f16bSMark de Wever #include <iostream> 303eb4f16bSMark de Wever #include <type_traits> 313eb4f16bSMark de Wever 323eb4f16bSMark de Wever #include "formatter_tests.h" 333eb4f16bSMark de Wever #include "make_string.h" 343eb4f16bSMark de Wever #include "platform_support.h" // locale name macros 353eb4f16bSMark de Wever #include "string_literal.h" 363eb4f16bSMark de Wever #include "test_macros.h" 373eb4f16bSMark de Wever 383eb4f16bSMark de Wever template <class CharT> 393eb4f16bSMark de Wever static void test_no_chrono_specs() { 403eb4f16bSMark de Wever check(SV("-32767"), SV("{}"), std::chrono::year{-32'767}); 413eb4f16bSMark de Wever check(SV("-1000"), SV("{}"), std::chrono::year{-1000}); 423eb4f16bSMark de Wever check(SV("-0100"), SV("{}"), std::chrono::year{-100}); 433eb4f16bSMark de Wever check(SV("-0010"), SV("{}"), std::chrono::year{-10}); 443eb4f16bSMark de Wever check(SV("-0001"), SV("{}"), std::chrono::year{-1}); 453eb4f16bSMark de Wever check(SV("0000"), SV("{}"), std::chrono::year{0}); 463eb4f16bSMark de Wever check(SV("0001"), SV("{}"), std::chrono::year{1}); 473eb4f16bSMark de Wever check(SV("0010"), SV("{}"), std::chrono::year{10}); 483eb4f16bSMark de Wever check(SV("0100"), SV("{}"), std::chrono::year{100}); 493eb4f16bSMark de Wever check(SV("1000"), SV("{}"), std::chrono::year{1000}); 503eb4f16bSMark de Wever check(SV("32727"), SV("{}"), std::chrono::year{32'727}); 513eb4f16bSMark de Wever 523eb4f16bSMark de Wever // Invalid year 533eb4f16bSMark de Wever check(SV("-32768 is not a valid year"), SV("{}"), std::chrono::year{-32'768}); 543eb4f16bSMark de Wever check(SV("-32768 is not a valid year"), SV("{}"), std::chrono::year{32'768}); 553eb4f16bSMark de Wever } 563eb4f16bSMark de Wever 573eb4f16bSMark de Wever template <class CharT> 583eb4f16bSMark de Wever static void test_valid_values() { 593eb4f16bSMark de Wever constexpr std::basic_string_view<CharT> fmt = SV( 603eb4f16bSMark de Wever "{:" 613eb4f16bSMark de Wever "%%C='%C'%t" 623eb4f16bSMark de Wever "%%EC='%EC'%t" 633eb4f16bSMark de Wever "%%y='%y'%t" 643eb4f16bSMark de Wever "%%Ey='%Ey'%t" 653eb4f16bSMark de Wever "%%Oy='%Oy'%t" 663eb4f16bSMark de Wever "%%Y='%Y'%t" 673eb4f16bSMark de Wever "%%EY='%EY'%t" 683eb4f16bSMark de Wever "%n}"); 693eb4f16bSMark de Wever constexpr std::basic_string_view<CharT> lfmt = SV( 703eb4f16bSMark de Wever "{:L" 713eb4f16bSMark de Wever "%%C='%C'%t" 723eb4f16bSMark de Wever "%%EC='%EC'%t" 733eb4f16bSMark de Wever "%%y='%y'%t" 743eb4f16bSMark de Wever "%%Ey='%Ey'%t" 753eb4f16bSMark de Wever "%%Oy='%Oy'%t" 763eb4f16bSMark de Wever "%%Y='%Y'%t" 773eb4f16bSMark de Wever "%%EY='%EY'%t" 783eb4f16bSMark de Wever "%n}"); 793eb4f16bSMark de Wever 803eb4f16bSMark de Wever const std::locale loc(LOCALE_ja_JP_UTF_8); 813eb4f16bSMark de Wever std::locale::global(std::locale(LOCALE_fr_FR_UTF_8)); 823eb4f16bSMark de Wever 833eb4f16bSMark de Wever // Non localized output using C-locale 843eb4f16bSMark de Wever check(SV("%C='00'\t" 858f01029bSMark de Wever #if defined(__APPLE__) || defined(_WIN32) || defined(__FreeBSD__) 863eb4f16bSMark de Wever "%EC='00'\t" 873eb4f16bSMark de Wever #else 883eb4f16bSMark de Wever "%EC='0'\t" 893eb4f16bSMark de Wever #endif 903eb4f16bSMark de Wever "%y='00'\t" 913eb4f16bSMark de Wever "%Ey='00'\t" 923eb4f16bSMark de Wever "%Oy='00'\t" 933eb4f16bSMark de Wever "%Y='0000'\t" 948f01029bSMark de Wever #if defined(__APPLE__) || defined(_WIN32) || defined(__FreeBSD__) 953eb4f16bSMark de Wever "%EY='0000'\t" 963eb4f16bSMark de Wever #elif defined(_AIX) 973eb4f16bSMark de Wever "%EY=''\t" 983eb4f16bSMark de Wever #else 993eb4f16bSMark de Wever "%EY='0'\t" 1003eb4f16bSMark de Wever #endif 1013eb4f16bSMark de Wever "\n"), 1023eb4f16bSMark de Wever fmt, 1033eb4f16bSMark de Wever std::chrono::year{0}); 1043eb4f16bSMark de Wever 1053eb4f16bSMark de Wever check(SV("%C='19'\t" 1063eb4f16bSMark de Wever "%EC='19'\t" 1073eb4f16bSMark de Wever "%y='70'\t" 1083eb4f16bSMark de Wever "%Ey='70'\t" 1093eb4f16bSMark de Wever "%Oy='70'\t" 1103eb4f16bSMark de Wever "%Y='1970'\t" 1113eb4f16bSMark de Wever "%EY='1970'\t" 1123eb4f16bSMark de Wever "\n"), 1133eb4f16bSMark de Wever fmt, 1143eb4f16bSMark de Wever std::chrono::year{1970}); 1153eb4f16bSMark de Wever 1163eb4f16bSMark de Wever check(SV("%C='20'\t" 1173eb4f16bSMark de Wever "%EC='20'\t" 1183eb4f16bSMark de Wever "%y='38'\t" 1193eb4f16bSMark de Wever "%Ey='38'\t" 1203eb4f16bSMark de Wever "%Oy='38'\t" 1213eb4f16bSMark de Wever "%Y='2038'\t" 1223eb4f16bSMark de Wever "%EY='2038'\t" 1233eb4f16bSMark de Wever "\n"), 1243eb4f16bSMark de Wever fmt, 1253eb4f16bSMark de Wever std::chrono::year{2038}); 1263eb4f16bSMark de Wever 1273eb4f16bSMark de Wever // Use the global locale (fr_FR) 1283eb4f16bSMark de Wever check(SV("%C='00'\t" 1298f01029bSMark de Wever #if defined(__APPLE__) || defined(_WIN32) || defined(__FreeBSD__) 1303eb4f16bSMark de Wever "%EC='00'\t" 1313eb4f16bSMark de Wever #else 1323eb4f16bSMark de Wever "%EC='0'\t" 1333eb4f16bSMark de Wever #endif 1343eb4f16bSMark de Wever "%y='00'\t" 1353eb4f16bSMark de Wever "%Ey='00'\t" 1363eb4f16bSMark de Wever "%Oy='00'\t" 1373eb4f16bSMark de Wever "%Y='0000'\t" 1388f01029bSMark de Wever #if defined(__APPLE__) || defined(_WIN32) || defined(__FreeBSD__) 1393eb4f16bSMark de Wever "%EY='0000'\t" 1403eb4f16bSMark de Wever #elif defined(_AIX) 1413eb4f16bSMark de Wever "%EY=''\t" 1423eb4f16bSMark de Wever #else 1433eb4f16bSMark de Wever "%EY='0'\t" 1443eb4f16bSMark de Wever #endif 1453eb4f16bSMark de Wever "\n"), 1463eb4f16bSMark de Wever lfmt, 1473eb4f16bSMark de Wever std::chrono::year{0}); 1483eb4f16bSMark de Wever 1493eb4f16bSMark de Wever check(SV("%C='19'\t" 1503eb4f16bSMark de Wever "%EC='19'\t" 1513eb4f16bSMark de Wever "%y='70'\t" 1523eb4f16bSMark de Wever "%Ey='70'\t" 1533eb4f16bSMark de Wever "%Oy='70'\t" 1543eb4f16bSMark de Wever "%Y='1970'\t" 1553eb4f16bSMark de Wever "%EY='1970'\t" 1563eb4f16bSMark de Wever "\n"), 1573eb4f16bSMark de Wever lfmt, 1583eb4f16bSMark de Wever std::chrono::year{1970}); 1593eb4f16bSMark de Wever 1603eb4f16bSMark de Wever check(SV("%C='20'\t" 1613eb4f16bSMark de Wever "%EC='20'\t" 1623eb4f16bSMark de Wever "%y='38'\t" 1633eb4f16bSMark de Wever "%Ey='38'\t" 1643eb4f16bSMark de Wever "%Oy='38'\t" 1653eb4f16bSMark de Wever "%Y='2038'\t" 1663eb4f16bSMark de Wever "%EY='2038'\t" 1673eb4f16bSMark de Wever "\n"), 1683eb4f16bSMark de Wever lfmt, 1693eb4f16bSMark de Wever std::chrono::year{2038}); 1703eb4f16bSMark de Wever 1713eb4f16bSMark de Wever // Use supplied locale (ja_JP). This locale has a different alternate. 1728f01029bSMark de Wever #if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 1733eb4f16bSMark de Wever 1743eb4f16bSMark de Wever check(SV("%C='00'\t" 1758f01029bSMark de Wever # if defined(__APPLE__) || defined(_WIN32) || defined(__FreeBSD__) 1763eb4f16bSMark de Wever "%EC='00'\t" 1773eb4f16bSMark de Wever # else 1783eb4f16bSMark de Wever "%EC='0'\t" 1793eb4f16bSMark de Wever # endif 1803eb4f16bSMark de Wever "%y='00'\t" 1813eb4f16bSMark de Wever "%Ey='00'\t" 1823eb4f16bSMark de Wever "%Oy='00'\t" 1833eb4f16bSMark de Wever "%Y='0000'\t" 1843eb4f16bSMark de Wever # if defined(_AIX) 1853eb4f16bSMark de Wever "%EY=''\t" 1863eb4f16bSMark de Wever # else 1873eb4f16bSMark de Wever "%EY='0000'\t" 1883eb4f16bSMark de Wever # endif 1893eb4f16bSMark de Wever "\n"), 1903eb4f16bSMark de Wever lfmt, 1913eb4f16bSMark de Wever std::chrono::year{0}); 1923eb4f16bSMark de Wever 1933eb4f16bSMark de Wever check(SV("%C='19'\t" 1943eb4f16bSMark de Wever "%EC='19'\t" 1953eb4f16bSMark de Wever "%y='70'\t" 1963eb4f16bSMark de Wever "%Ey='70'\t" 1973eb4f16bSMark de Wever "%Oy='70'\t" 1983eb4f16bSMark de Wever "%Y='1970'\t" 1993eb4f16bSMark de Wever "%EY='1970'\t" 2003eb4f16bSMark de Wever "\n"), 2013eb4f16bSMark de Wever lfmt, 2023eb4f16bSMark de Wever std::chrono::year{1970}); 2033eb4f16bSMark de Wever 2043eb4f16bSMark de Wever check(SV("%C='20'\t" 2053eb4f16bSMark de Wever "%EC='20'\t" 2063eb4f16bSMark de Wever "%y='38'\t" 2073eb4f16bSMark de Wever "%Ey='38'\t" 2083eb4f16bSMark de Wever "%Oy='38'\t" 2093eb4f16bSMark de Wever "%Y='2038'\t" 2103eb4f16bSMark de Wever "%EY='2038'\t" 2113eb4f16bSMark de Wever "\n"), 2123eb4f16bSMark de Wever lfmt, 2133eb4f16bSMark de Wever std::chrono::year{2038}); 2143eb4f16bSMark de Wever 2158f01029bSMark de Wever #else // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 2163eb4f16bSMark de Wever check(loc, 2173eb4f16bSMark de Wever SV("%C='00'\t" 2183eb4f16bSMark de Wever "%EC='紀元前'\t" 2193eb4f16bSMark de Wever "%y='00'\t" 2203eb4f16bSMark de Wever // https://sourceware.org/bugzilla/show_bug.cgi?id=23758 2213eb4f16bSMark de Wever # if defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29 2223eb4f16bSMark de Wever "%Ey='1'\t" 2233eb4f16bSMark de Wever # else 2243eb4f16bSMark de Wever "%Ey='01'\t" 2253eb4f16bSMark de Wever # endif 2263eb4f16bSMark de Wever "%Oy='〇'\t" 2273eb4f16bSMark de Wever "%Y='0000'\t" 2283eb4f16bSMark de Wever // https://sourceware.org/bugzilla/show_bug.cgi?id=23758 2293eb4f16bSMark de Wever # if defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29 2303eb4f16bSMark de Wever "%EY='紀元前1年'\t" 2313eb4f16bSMark de Wever # else 2323eb4f16bSMark de Wever "%EY='紀元前01年'\t" 2333eb4f16bSMark de Wever # endif 2343eb4f16bSMark de Wever "\n"), 2353eb4f16bSMark de Wever lfmt, 2363eb4f16bSMark de Wever std::chrono::year{0}); 2373eb4f16bSMark de Wever 2383eb4f16bSMark de Wever check(loc, 2393eb4f16bSMark de Wever SV("%C='19'\t" 2403eb4f16bSMark de Wever "%EC='昭和'\t" 2413eb4f16bSMark de Wever "%y='70'\t" 2423eb4f16bSMark de Wever "%Ey='45'\t" 2433eb4f16bSMark de Wever "%Oy='七十'\t" 2443eb4f16bSMark de Wever "%Y='1970'\t" 2453eb4f16bSMark de Wever "%EY='昭和45年'\t" 2463eb4f16bSMark de Wever "\n"), 2473eb4f16bSMark de Wever lfmt, 2483eb4f16bSMark de Wever std::chrono::year{1970}); 2493eb4f16bSMark de Wever 2503eb4f16bSMark de Wever // Note this test will fail if the Reiwa era ends before 2038. 2513eb4f16bSMark de Wever check(loc, 2523eb4f16bSMark de Wever SV("%C='20'\t" 2533eb4f16bSMark de Wever "%EC='令和'\t" 2543eb4f16bSMark de Wever "%y='38'\t" 2553eb4f16bSMark de Wever "%Ey='20'\t" 2563eb4f16bSMark de Wever "%Oy='三十八'\t" 2573eb4f16bSMark de Wever "%Y='2038'\t" 2583eb4f16bSMark de Wever "%EY='令和20年'\t" 2593eb4f16bSMark de Wever "\n"), 2603eb4f16bSMark de Wever lfmt, 2613eb4f16bSMark de Wever std::chrono::year{2038}); 2628f01029bSMark de Wever #endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__) 2633eb4f16bSMark de Wever 2643eb4f16bSMark de Wever std::locale::global(std::locale::classic()); 2653eb4f16bSMark de Wever } 2663eb4f16bSMark de Wever 2673eb4f16bSMark de Wever template <class CharT> 2683eb4f16bSMark de Wever static void test_padding() { 2693eb4f16bSMark de Wever constexpr std::basic_string_view<CharT> fmt = SV("{:%%C='%C'%t%%y='%y'%t%%Y='%Y'%t%n}"); 2703eb4f16bSMark de Wever check(SV("%C='-100'\t%y='99'\t%Y='-9999'\t\n"), fmt, std::chrono::year{-9'999}); 2713eb4f16bSMark de Wever check(SV("%C='-10'\t%y='99'\t%Y='-0999'\t\n"), fmt, std::chrono::year{-999}); 2723eb4f16bSMark de Wever check(SV("%C='-1'\t%y='99'\t%Y='-0099'\t\n"), fmt, std::chrono::year{-99}); 2733eb4f16bSMark de Wever check(SV("%C='-1'\t%y='09'\t%Y='-0009'\t\n"), fmt, std::chrono::year{-9}); 2743eb4f16bSMark de Wever check(SV("%C='00'\t%y='00'\t%Y='0000'\t\n"), fmt, std::chrono::year{0}); 2753eb4f16bSMark de Wever check(SV("%C='00'\t%y='09'\t%Y='0009'\t\n"), fmt, std::chrono::year{9}); 2763eb4f16bSMark de Wever check(SV("%C='00'\t%y='99'\t%Y='0099'\t\n"), fmt, std::chrono::year{99}); 2773eb4f16bSMark de Wever check(SV("%C='09'\t%y='99'\t%Y='0999'\t\n"), fmt, std::chrono::year{999}); 2783eb4f16bSMark de Wever check(SV("%C='99'\t%y='99'\t%Y='9999'\t\n"), fmt, std::chrono::year{9'999}); 2793eb4f16bSMark de Wever check(SV("%C='100'\t%y='00'\t%Y='10000'\t\n"), fmt, std::chrono::year{10'000}); 2803eb4f16bSMark de Wever } 2813eb4f16bSMark de Wever 2823eb4f16bSMark de Wever template <class CharT> 2833eb4f16bSMark de Wever static void test() { 2843eb4f16bSMark de Wever test_no_chrono_specs<CharT>(); 2853eb4f16bSMark de Wever test_valid_values<CharT>(); 2863eb4f16bSMark de Wever test_padding<CharT>(); 2873eb4f16bSMark de Wever check_invalid_types<CharT>( 2883eb4f16bSMark de Wever {SV("C"), SV("y"), SV("Y"), SV("EC"), SV("Ey"), SV("EY"), SV("Oy")}, std::chrono::year{1970}); 2893eb4f16bSMark de Wever 290402eb2efSMark de Wever check_exception("The format specifier expects a '%' or a '}'", SV("{:A"), std::chrono::year{1970}); 291402eb2efSMark de Wever check_exception("The chrono specifiers contain a '{'", SV("{:%%{"), std::chrono::year{1970}); 292402eb2efSMark de Wever check_exception("End of input while parsing a conversion specifier", SV("{:%"), std::chrono::year{1970}); 2933eb4f16bSMark de Wever check_exception("End of input while parsing the modifier E", SV("{:%E"), std::chrono::year{1970}); 2943eb4f16bSMark de Wever check_exception("End of input while parsing the modifier O", SV("{:%O"), std::chrono::year{1970}); 2953eb4f16bSMark de Wever 2963eb4f16bSMark de Wever // Precision not allowed 297402eb2efSMark de Wever check_exception("The format specifier expects a '%' or a '}'", SV("{:.3}"), std::chrono::year{1970}); 2983eb4f16bSMark de Wever } 2993eb4f16bSMark de Wever 3003eb4f16bSMark de Wever int main(int, char**) { 3013eb4f16bSMark de Wever test<char>(); 3023eb4f16bSMark de Wever 3033eb4f16bSMark de Wever #ifndef TEST_HAS_NO_WIDE_CHARACTERS 3043eb4f16bSMark de Wever test<wchar_t>(); 3053eb4f16bSMark de Wever #endif 3063eb4f16bSMark de Wever 3073eb4f16bSMark de Wever return 0; 3083eb4f16bSMark de Wever } 309