xref: /llvm-project/libcxx/test/std/time/time.syn/formatter.year.pass.cpp (revision 6a54dfbfe534276d644d7f9c027f0deeb748dd53)
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