xref: /llvm-project/libcxx/test/std/time/time.syn/formatter.hh_mm_ss.pass.cpp (revision 6a54dfbfe534276d644d7f9c027f0deeb748dd53)
17f5d130aSMark de Wever //===----------------------------------------------------------------------===//
2*6a54dfbfSLouis Dionne //
37f5d130aSMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47f5d130aSMark de Wever // See https://llvm.org/LICENSE.txt for license information.
57f5d130aSMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67f5d130aSMark de Wever //
77f5d130aSMark de Wever //===----------------------------------------------------------------------===//
87f5d130aSMark de Wever 
97f5d130aSMark de Wever // UNSUPPORTED: c++03, c++11, c++14, c++17
107f5d130aSMark de Wever // UNSUPPORTED: no-localization
11520c7fbbSLouis Dionne // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
127f5d130aSMark de Wever 
13f0fc8c48SLouis Dionne // XFAIL: availability-fp_to_chars-missing
143d334df5SLouis Dionne 
157f5d130aSMark de Wever // REQUIRES: locale.fr_FR.UTF-8
167f5d130aSMark de Wever // REQUIRES: locale.ja_JP.UTF-8
177f5d130aSMark de Wever 
187f5d130aSMark de Wever // <chrono>
197f5d130aSMark de Wever 
207f5d130aSMark de Wever // template<class Rep, class Period, class charT>
217f5d130aSMark de Wever //   struct formatter<chrono::hh_mm_ss<duration<Rep, Period>>, charT>;
227f5d130aSMark de Wever 
237f5d130aSMark de Wever #include <chrono>
247f5d130aSMark de Wever #include <format>
257f5d130aSMark de Wever 
267f5d130aSMark de Wever #include <cassert>
277f5d130aSMark de Wever #include <concepts>
287f5d130aSMark de Wever #include <locale>
297f5d130aSMark de Wever #include <iostream>
30e655d8a5SNikolas Klauser #include <ratio>
317f5d130aSMark de Wever #include <type_traits>
327f5d130aSMark de Wever 
337f5d130aSMark de Wever #include "formatter_tests.h"
347f5d130aSMark de Wever #include "make_string.h"
357f5d130aSMark de Wever #include "platform_support.h" // locale name macros
367f5d130aSMark de Wever #include "string_literal.h"
377f5d130aSMark de Wever #include "test_macros.h"
387f5d130aSMark de Wever 
397f5d130aSMark de Wever template <class CharT>
407f5d130aSMark de Wever static void test_no_chrono_specs() {
417f5d130aSMark de Wever   using namespace std::literals::chrono_literals;
427f5d130aSMark de Wever 
437f5d130aSMark de Wever   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
447f5d130aSMark de Wever 
457f5d130aSMark de Wever   // Non localized output
467f5d130aSMark de Wever   check(SV("00:00:00.000"), SV("{}"), std::chrono::hh_mm_ss{0ms});
477f5d130aSMark de Wever   check(SV("*00:00:00.000*"), SV("{:*^14}"), std::chrono::hh_mm_ss{0ms});
487f5d130aSMark de Wever   check(SV("*00:00:00.000"), SV("{:*>13}"), std::chrono::hh_mm_ss{0ms});
497f5d130aSMark de Wever 
507f5d130aSMark de Wever   std::locale::global(std::locale::classic());
517f5d130aSMark de Wever }
527f5d130aSMark de Wever 
537f5d130aSMark de Wever template <class CharT>
547f5d130aSMark de Wever static void test_valid_values() {
557f5d130aSMark de Wever   using namespace std::literals::chrono_literals;
567f5d130aSMark de Wever 
577f5d130aSMark de Wever   constexpr std::basic_string_view<CharT> fmt = SV(
587f5d130aSMark de Wever       "{:"
597f5d130aSMark de Wever       "%%H='%H'%t"
607f5d130aSMark de Wever       "%%OH='%OH'%t"
617f5d130aSMark de Wever       "%%I='%I'%t"
627f5d130aSMark de Wever       "%%OI='%OI'%t"
637f5d130aSMark de Wever       "%%M='%M'%t"
647f5d130aSMark de Wever       "%%OM='%OM'%t"
657f5d130aSMark de Wever       "%%S='%S'%t"
667f5d130aSMark de Wever       "%%OS='%OS'%t"
677f5d130aSMark de Wever       "%%p='%p'%t"
687f5d130aSMark de Wever       "%%R='%R'%t"
697f5d130aSMark de Wever       "%%T='%T'%t"
707f5d130aSMark de Wever       "%%r='%r'%t"
717f5d130aSMark de Wever       "%%X='%X'%t"
727f5d130aSMark de Wever       "%%EX='%EX'%t"
737f5d130aSMark de Wever       "%n}");
747f5d130aSMark de Wever   constexpr std::basic_string_view<CharT> lfmt = SV(
757f5d130aSMark de Wever       "{:L"
767f5d130aSMark de Wever       "%%H='%H'%t"
777f5d130aSMark de Wever       "%%OH='%OH'%t"
787f5d130aSMark de Wever       "%%I='%I'%t"
797f5d130aSMark de Wever       "%%OI='%OI'%t"
807f5d130aSMark de Wever       "%%M='%M'%t"
817f5d130aSMark de Wever       "%%OM='%OM'%t"
827f5d130aSMark de Wever       "%%S='%S'%t"
837f5d130aSMark de Wever       "%%OS='%OS'%t"
847f5d130aSMark de Wever       "%%p='%p'%t"
857f5d130aSMark de Wever       "%%R='%R'%t"
867f5d130aSMark de Wever       "%%T='%T'%t"
877f5d130aSMark de Wever       "%%r='%r'%t"
887f5d130aSMark de Wever       "%%X='%X'%t"
897f5d130aSMark de Wever       "%%EX='%EX'%t"
907f5d130aSMark de Wever       "%n}");
917f5d130aSMark de Wever 
927f5d130aSMark de Wever   const std::locale loc(LOCALE_ja_JP_UTF_8);
937f5d130aSMark de Wever   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
947f5d130aSMark de Wever 
957f5d130aSMark de Wever   // Non localized output using C-locale
967f5d130aSMark de Wever   check(SV("%H='00'\t"
977f5d130aSMark de Wever            "%OH='00'\t"
987f5d130aSMark de Wever            "%I='12'\t"
997f5d130aSMark de Wever            "%OI='12'\t"
1007f5d130aSMark de Wever            "%M='00'\t"
1017f5d130aSMark de Wever            "%OM='00'\t"
1027f5d130aSMark de Wever            "%S='00'\t"
1037f5d130aSMark de Wever            "%OS='00'\t"
1047f5d130aSMark de Wever            "%p='AM'\t"
1057f5d130aSMark de Wever            "%R='00:00'\t"
1067f5d130aSMark de Wever            "%T='00:00:00'\t"
1077f5d130aSMark de Wever            "%r='12:00:00 AM'\t"
1087f5d130aSMark de Wever            "%X='00:00:00'\t"
1097f5d130aSMark de Wever            "%EX='00:00:00'\t"
1107f5d130aSMark de Wever            "\n"),
1117f5d130aSMark de Wever         fmt,
1127f5d130aSMark de Wever         std::chrono::hh_mm_ss(0s));
1137f5d130aSMark de Wever 
1147f5d130aSMark de Wever   check(SV("%H='23'\t"
1157f5d130aSMark de Wever            "%OH='23'\t"
1167f5d130aSMark de Wever            "%I='11'\t"
1177f5d130aSMark de Wever            "%OI='11'\t"
1187f5d130aSMark de Wever            "%M='31'\t"
1197f5d130aSMark de Wever            "%OM='31'\t"
1207f5d130aSMark de Wever            "%S='30.123'\t"
1217f5d130aSMark de Wever            "%OS='30.123'\t"
1227f5d130aSMark de Wever            "%p='PM'\t"
1237f5d130aSMark de Wever            "%R='23:31'\t"
1247f5d130aSMark de Wever            "%T='23:31:30.123'\t"
1257f5d130aSMark de Wever            "%r='11:31:30 PM'\t"
1267f5d130aSMark de Wever            "%X='23:31:30'\t"
1277f5d130aSMark de Wever            "%EX='23:31:30'\t"
1287f5d130aSMark de Wever            "\n"),
1297f5d130aSMark de Wever         fmt,
1307f5d130aSMark de Wever         std::chrono::hh_mm_ss(23h + 31min + 30s + 123ms));
1317f5d130aSMark de Wever 
1327f5d130aSMark de Wever   check(SV("-%H='03'\t"
1337f5d130aSMark de Wever            "%OH='03'\t"
1347f5d130aSMark de Wever            "%I='03'\t"
1357f5d130aSMark de Wever            "%OI='03'\t"
1367f5d130aSMark de Wever            "%M='02'\t"
1377f5d130aSMark de Wever            "%OM='02'\t"
1387f5d130aSMark de Wever            "%S='01.123456789012'\t"
1397f5d130aSMark de Wever            "%OS='01.123456789012'\t"
1407f5d130aSMark de Wever            "%p='AM'\t"
1417f5d130aSMark de Wever            "%R='03:02'\t"
1427f5d130aSMark de Wever            "%T='03:02:01.123456789012'\t"
1437f5d130aSMark de Wever            "%r='03:02:01 AM'\t"
1447f5d130aSMark de Wever            "%X='03:02:01'\t"
1457f5d130aSMark de Wever            "%EX='03:02:01'\t"
1467f5d130aSMark de Wever            "\n"),
1477f5d130aSMark de Wever         fmt,
148bd5d0feeSMark de Wever         std::chrono::hh_mm_ss(-(3h + 2min + 1s + std::chrono::duration<std::int64_t, std::pico>(123456789012))));
1497f5d130aSMark de Wever 
1507f5d130aSMark de Wever   // The number of fractional seconds is 0 according to the Standard
1517f5d130aSMark de Wever   // TODO FMT Determine what to do.
1527f5d130aSMark de Wever   check(SV("%H='01'\t"
1537f5d130aSMark de Wever            "%OH='01'\t"
1547f5d130aSMark de Wever            "%I='01'\t"
1557f5d130aSMark de Wever            "%OI='01'\t"
1567f5d130aSMark de Wever            "%M='01'\t"
1577f5d130aSMark de Wever            "%OM='01'\t"
1587f5d130aSMark de Wever            "%S='01'\t"
1597f5d130aSMark de Wever            "%OS='01'\t"
1607f5d130aSMark de Wever            "%p='AM'\t"
1617f5d130aSMark de Wever            "%R='01:01'\t"
1627f5d130aSMark de Wever            "%T='01:01:01'\t"
1637f5d130aSMark de Wever            "%r='01:01:01 AM'\t"
1647f5d130aSMark de Wever            "%X='01:01:01'\t"
1657f5d130aSMark de Wever            "%EX='01:01:01'\t"
1667f5d130aSMark de Wever            "\n"),
1677f5d130aSMark de Wever         fmt,
1687f5d130aSMark de Wever         std::chrono::hh_mm_ss(std::chrono::duration<double>(3661.123456)));
1697f5d130aSMark de Wever 
1707f5d130aSMark de Wever   // Use the global locale (fr_FR)
1717f5d130aSMark de Wever   check(SV("%H='00'\t"
1727f5d130aSMark de Wever            "%OH='00'\t"
1737f5d130aSMark de Wever            "%I='12'\t"
1747f5d130aSMark de Wever            "%OI='12'\t"
1757f5d130aSMark de Wever            "%M='00'\t"
1767f5d130aSMark de Wever            "%OM='00'\t"
1777f5d130aSMark de Wever            "%S='00'\t"
1787f5d130aSMark de Wever            "%OS='00'\t"
1797f5d130aSMark de Wever #if defined(_AIX)
1807f5d130aSMark de Wever            "%p='AM'\t"
1817f5d130aSMark de Wever #else
1827f5d130aSMark de Wever            "%p=''\t"
1837f5d130aSMark de Wever #endif
1847f5d130aSMark de Wever            "%R='00:00'\t"
1857f5d130aSMark de Wever            "%T='00:00:00'\t"
1867f5d130aSMark de Wever #ifdef _WIN32
1877f5d130aSMark de Wever            "%r='00:00:00'\t"
1887f5d130aSMark de Wever #elif defined(_AIX)
1897f5d130aSMark de Wever            "%r='12:00:00 AM'\t"
1908f01029bSMark de Wever #elif defined(__APPLE__) || defined(__FreeBSD__)
1917f5d130aSMark de Wever            "%r=''\t"
1927f5d130aSMark de Wever #else
1937f5d130aSMark de Wever            "%r='12:00:00 '\t"
1947f5d130aSMark de Wever #endif
1957f5d130aSMark de Wever            "%X='00:00:00'\t"
1967f5d130aSMark de Wever            "%EX='00:00:00'\t"
1977f5d130aSMark de Wever            "\n"),
1987f5d130aSMark de Wever         lfmt,
1997f5d130aSMark de Wever         std::chrono::hh_mm_ss(0s));
2007f5d130aSMark de Wever 
2017f5d130aSMark de Wever   check(SV("%H='23'\t"
2027f5d130aSMark de Wever            "%OH='23'\t"
2037f5d130aSMark de Wever            "%I='11'\t"
2047f5d130aSMark de Wever            "%OI='11'\t"
2057f5d130aSMark de Wever            "%M='31'\t"
2067f5d130aSMark de Wever            "%OM='31'\t"
2077f5d130aSMark de Wever            "%S='30,123'\t"
2087f5d130aSMark de Wever            "%OS='30,123'\t"
2097f5d130aSMark de Wever #if defined(_AIX)
2107f5d130aSMark de Wever            "%p='PM'\t"
2117f5d130aSMark de Wever #else
2127f5d130aSMark de Wever            "%p=''\t"
2137f5d130aSMark de Wever #endif
2147f5d130aSMark de Wever            "%R='23:31'\t"
2157f5d130aSMark de Wever            "%T='23:31:30,123'\t"
2167f5d130aSMark de Wever #ifdef _WIN32
2177f5d130aSMark de Wever            "%r='23:31:30'\t"
2187f5d130aSMark de Wever #elif defined(_AIX)
2197f5d130aSMark de Wever            "%r='11:31:30 PM'\t"
2208f01029bSMark de Wever #elif defined(__APPLE__) || defined(__FreeBSD__)
2217f5d130aSMark de Wever            "%r=''\t"
2227f5d130aSMark de Wever #else
2237f5d130aSMark de Wever            "%r='11:31:30 '\t"
2247f5d130aSMark de Wever #endif
2257f5d130aSMark de Wever            "%X='23:31:30'\t"
2267f5d130aSMark de Wever            "%EX='23:31:30'\t"
2277f5d130aSMark de Wever            "\n"),
2287f5d130aSMark de Wever         lfmt,
2297f5d130aSMark de Wever         std::chrono::hh_mm_ss(23h + 31min + 30s + 123ms));
2307f5d130aSMark de Wever 
2317f5d130aSMark de Wever   check(SV("-%H='03'\t"
2327f5d130aSMark de Wever            "%OH='03'\t"
2337f5d130aSMark de Wever            "%I='03'\t"
2347f5d130aSMark de Wever            "%OI='03'\t"
2357f5d130aSMark de Wever            "%M='02'\t"
2367f5d130aSMark de Wever            "%OM='02'\t"
2377f5d130aSMark de Wever            "%S='01,123456789012'\t"
2387f5d130aSMark de Wever            "%OS='01,123456789012'\t"
2397f5d130aSMark de Wever #if defined(_AIX)
2407f5d130aSMark de Wever            "%p='AM'\t"
2417f5d130aSMark de Wever #else
2427f5d130aSMark de Wever            "%p=''\t"
2437f5d130aSMark de Wever #endif
2447f5d130aSMark de Wever            "%R='03:02'\t"
2457f5d130aSMark de Wever            "%T='03:02:01,123456789012'\t"
2467f5d130aSMark de Wever #ifdef _WIN32
2477f5d130aSMark de Wever            "%r='03:02:01'\t"
2487f5d130aSMark de Wever #elif defined(_AIX)
2497f5d130aSMark de Wever            "%r='03:02:01 AM'\t"
2508f01029bSMark de Wever #elif defined(__APPLE__) || defined(__FreeBSD__)
2517f5d130aSMark de Wever            "%r=''\t"
2527f5d130aSMark de Wever #else
2537f5d130aSMark de Wever            "%r='03:02:01 '\t"
2547f5d130aSMark de Wever #endif
2557f5d130aSMark de Wever            "%X='03:02:01'\t"
2567f5d130aSMark de Wever            "%EX='03:02:01'\t"
2577f5d130aSMark de Wever            "\n"),
2587f5d130aSMark de Wever         lfmt,
259bd5d0feeSMark de Wever         std::chrono::hh_mm_ss(-(3h + 2min + 1s + std::chrono::duration<std::int64_t, std::pico>(123456789012))));
2607f5d130aSMark de Wever 
2617f5d130aSMark de Wever   check(SV("%H='01'\t"
2627f5d130aSMark de Wever            "%OH='01'\t"
2637f5d130aSMark de Wever            "%I='01'\t"
2647f5d130aSMark de Wever            "%OI='01'\t"
2657f5d130aSMark de Wever            "%M='01'\t"
2667f5d130aSMark de Wever            "%OM='01'\t"
2677f5d130aSMark de Wever            "%S='01'\t"
2687f5d130aSMark de Wever            "%OS='01'\t"
2697f5d130aSMark de Wever #if defined(_AIX)
2707f5d130aSMark de Wever            "%p='AM'\t"
2717f5d130aSMark de Wever #else
2727f5d130aSMark de Wever            "%p=''\t"
2737f5d130aSMark de Wever #endif
2747f5d130aSMark de Wever            "%R='01:01'\t"
2757f5d130aSMark de Wever            "%T='01:01:01'\t"
2767f5d130aSMark de Wever #ifdef _WIN32
2777f5d130aSMark de Wever            "%r='01:01:01'\t"
2787f5d130aSMark de Wever #elif defined(_AIX)
2797f5d130aSMark de Wever            "%r='01:01:01 AM'\t"
2808f01029bSMark de Wever #elif defined(__APPLE__) || defined(__FreeBSD__)
2817f5d130aSMark de Wever            "%r=''\t"
2827f5d130aSMark de Wever #else
2837f5d130aSMark de Wever            "%r='01:01:01 '\t"
2847f5d130aSMark de Wever #endif
2857f5d130aSMark de Wever            "%X='01:01:01'\t"
2867f5d130aSMark de Wever            "%EX='01:01:01'\t"
2877f5d130aSMark de Wever            "\n"),
2887f5d130aSMark de Wever         lfmt,
2897f5d130aSMark de Wever         std::chrono::hh_mm_ss(std::chrono::duration<double>(3661.123456)));
2907f5d130aSMark de Wever 
2917f5d130aSMark de Wever   // Use supplied locale (ja_JP). This locale has a different alternate.
2928f01029bSMark de Wever #if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
2937f5d130aSMark de Wever   check(loc,
2947f5d130aSMark de Wever         SV("%H='00'\t"
2957f5d130aSMark de Wever            "%OH='00'\t"
2967f5d130aSMark de Wever            "%I='12'\t"
2977f5d130aSMark de Wever            "%OI='12'\t"
2987f5d130aSMark de Wever            "%M='00'\t"
2997f5d130aSMark de Wever            "%OM='00'\t"
3007f5d130aSMark de Wever            "%S='00'\t"
3017f5d130aSMark de Wever            "%OS='00'\t"
3027f5d130aSMark de Wever #  if defined(__APPLE__)
3037f5d130aSMark de Wever            "%p='AM'\t"
3047f5d130aSMark de Wever #  else
3057f5d130aSMark de Wever            "%p='午前'\t"
3067f5d130aSMark de Wever #  endif
3077f5d130aSMark de Wever            "%R='00:00'\t"
3087f5d130aSMark de Wever            "%T='00:00:00'\t"
3098f01029bSMark de Wever #  if defined(__APPLE__) || defined(__FreeBSD__)
3107f5d130aSMark de Wever #    if defined(__APPLE__)
3117f5d130aSMark de Wever            "%r='12:00:00 AM'\t"
3128f01029bSMark de Wever #    else
3138f01029bSMark de Wever            "%r='12:00:00 午前'\t"
3148f01029bSMark de Wever #    endif
3157f5d130aSMark de Wever            "%X='00時00分00秒'\t"
3167f5d130aSMark de Wever            "%EX='00時00分00秒'\t"
3171403080aSMark de Wever #  elif defined(_WIN32)
3181403080aSMark de Wever            "%r='0:00:00'\t"
3191403080aSMark de Wever            "%X='0:00:00'\t"
3201403080aSMark de Wever            "%EX='0:00:00'\t"
3217f5d130aSMark de Wever #  else
3227f5d130aSMark de Wever            "%r='午前12:00:00'\t"
3237f5d130aSMark de Wever            "%X='00:00:00'\t"
3247f5d130aSMark de Wever            "%EX='00:00:00'\t"
3257f5d130aSMark de Wever #  endif
3267f5d130aSMark de Wever            "\n"),
3277f5d130aSMark de Wever         lfmt,
3287f5d130aSMark de Wever         std::chrono::hh_mm_ss(0s));
3297f5d130aSMark de Wever 
3307f5d130aSMark de Wever   check(loc,
3317f5d130aSMark de Wever         SV("%H='23'\t"
3327f5d130aSMark de Wever            "%OH='23'\t"
3337f5d130aSMark de Wever            "%I='11'\t"
3347f5d130aSMark de Wever            "%OI='11'\t"
3357f5d130aSMark de Wever            "%M='31'\t"
3367f5d130aSMark de Wever            "%OM='31'\t"
3377f5d130aSMark de Wever            "%S='30.123'\t"
3387f5d130aSMark de Wever            "%OS='30.123'\t"
3397f5d130aSMark de Wever #  if defined(__APPLE__)
3407f5d130aSMark de Wever            "%p='PM'\t"
3417f5d130aSMark de Wever #  else
3427f5d130aSMark de Wever            "%p='午後'\t"
3437f5d130aSMark de Wever #  endif
3447f5d130aSMark de Wever            "%R='23:31'\t"
3457f5d130aSMark de Wever            "%T='23:31:30.123'\t"
3468f01029bSMark de Wever #  if defined(__APPLE__) || defined(__FreeBSD__)
3477f5d130aSMark de Wever #    if defined(__APPLE__)
3487f5d130aSMark de Wever            "%r='11:31:30 PM'\t"
3498f01029bSMark de Wever #    else
3508f01029bSMark de Wever            "%r='11:31:30 午後'\t"
3518f01029bSMark de Wever #    endif
3527f5d130aSMark de Wever            "%X='23時31分30秒'\t"
3537f5d130aSMark de Wever            "%EX='23時31分30秒'\t"
3541403080aSMark de Wever #  elif defined(_WIN32)
3551403080aSMark de Wever            "%r='23:31:30'\t"
3561403080aSMark de Wever            "%X='23:31:30'\t"
3571403080aSMark de Wever            "%EX='23:31:30'\t"
3587f5d130aSMark de Wever #  else
3597f5d130aSMark de Wever            "%r='午後11:31:30'\t"
3607f5d130aSMark de Wever            "%X='23:31:30'\t"
3617f5d130aSMark de Wever            "%EX='23:31:30'\t"
3627f5d130aSMark de Wever #  endif
3637f5d130aSMark de Wever            "\n"),
3647f5d130aSMark de Wever         lfmt,
3657f5d130aSMark de Wever         std::chrono::hh_mm_ss(23h + 31min + 30s + 123ms));
3667f5d130aSMark de Wever 
3677f5d130aSMark de Wever   check(loc,
3687f5d130aSMark de Wever         SV("-%H='03'\t"
3697f5d130aSMark de Wever            "%OH='03'\t"
3707f5d130aSMark de Wever            "%I='03'\t"
3717f5d130aSMark de Wever            "%OI='03'\t"
3727f5d130aSMark de Wever            "%M='02'\t"
3737f5d130aSMark de Wever            "%OM='02'\t"
3747f5d130aSMark de Wever            "%S='01.123456789012'\t"
3757f5d130aSMark de Wever            "%OS='01.123456789012'\t"
3767f5d130aSMark de Wever #  if defined(__APPLE__)
3777f5d130aSMark de Wever            "%p='AM'\t"
3787f5d130aSMark de Wever #  else
3797f5d130aSMark de Wever            "%p='午前'\t"
3807f5d130aSMark de Wever #  endif
3817f5d130aSMark de Wever            "%R='03:02'\t"
3827f5d130aSMark de Wever            "%T='03:02:01.123456789012'\t"
3838f01029bSMark de Wever #  if defined(__APPLE__) || defined(__FreeBSD__)
3847f5d130aSMark de Wever #    if defined(__APPLE__)
3857f5d130aSMark de Wever            "%r='03:02:01 AM'\t"
3868f01029bSMark de Wever #    else
3878f01029bSMark de Wever            "%r='03:02:01 午前'\t"
3888f01029bSMark de Wever #    endif
3897f5d130aSMark de Wever            "%X='03時02分01秒'\t"
3907f5d130aSMark de Wever            "%EX='03時02分01秒'\t"
3911403080aSMark de Wever #  elif defined(_WIN32)
3921403080aSMark de Wever            "%r='3:02:01'\t"
3931403080aSMark de Wever            "%X='3:02:01'\t"
3941403080aSMark de Wever            "%EX='3:02:01'\t"
3957f5d130aSMark de Wever #  else
3967f5d130aSMark de Wever            "%r='午前03:02:01'\t"
3977f5d130aSMark de Wever            "%X='03:02:01'\t"
3987f5d130aSMark de Wever            "%EX='03:02:01'\t"
3997f5d130aSMark de Wever #  endif
4007f5d130aSMark de Wever            "\n"),
4017f5d130aSMark de Wever         lfmt,
402bd5d0feeSMark de Wever         std::chrono::hh_mm_ss(-(3h + 2min + 1s + std::chrono::duration<std::int64_t, std::pico>(123456789012))));
4037f5d130aSMark de Wever 
4047f5d130aSMark de Wever   check(loc,
4057f5d130aSMark de Wever         SV("%H='01'\t"
4067f5d130aSMark de Wever            "%OH='01'\t"
4077f5d130aSMark de Wever            "%I='01'\t"
4087f5d130aSMark de Wever            "%OI='01'\t"
4097f5d130aSMark de Wever            "%M='01'\t"
4107f5d130aSMark de Wever            "%OM='01'\t"
4117f5d130aSMark de Wever            "%S='01'\t"
4127f5d130aSMark de Wever            "%OS='01'\t"
4137f5d130aSMark de Wever #  if defined(__APPLE__)
4147f5d130aSMark de Wever            "%p='AM'\t"
4157f5d130aSMark de Wever #  else
4167f5d130aSMark de Wever            "%p='午前'\t"
4177f5d130aSMark de Wever #  endif
4187f5d130aSMark de Wever            "%R='01:01'\t"
4197f5d130aSMark de Wever            "%T='01:01:01'\t"
4208f01029bSMark de Wever #  if defined(__APPLE__) || defined(__FreeBSD__)
4217f5d130aSMark de Wever #    if defined(__APPLE__)
4227f5d130aSMark de Wever            "%r='01:01:01 AM'\t"
4238f01029bSMark de Wever #    else
4248f01029bSMark de Wever            "%r='01:01:01 午前'\t"
4258f01029bSMark de Wever #    endif
4267f5d130aSMark de Wever            "%X='01時01分01秒'\t"
4277f5d130aSMark de Wever            "%EX='01時01分01秒'\t"
4281403080aSMark de Wever #  elif defined(_WIN32)
4291403080aSMark de Wever            "%r='1:01:01'\t"
4301403080aSMark de Wever            "%X='1:01:01'\t"
4311403080aSMark de Wever            "%EX='1:01:01'\t"
4327f5d130aSMark de Wever #  else
4337f5d130aSMark de Wever            "%r='午前01:01:01'\t"
4347f5d130aSMark de Wever            "%X='01:01:01'\t"
4357f5d130aSMark de Wever            "%EX='01:01:01'\t"
4367f5d130aSMark de Wever #  endif
4377f5d130aSMark de Wever            "\n"),
4387f5d130aSMark de Wever         lfmt,
4397f5d130aSMark de Wever         std::chrono::hh_mm_ss(std::chrono::duration<double>(3661.123456)));
4401403080aSMark de Wever #else  // defined(__APPLE__) || defined(_AIX) || defined(_WIN32)
4417f5d130aSMark de Wever   check(loc,
4427f5d130aSMark de Wever         SV("%H='00'\t"
4437f5d130aSMark de Wever            "%OH='〇'\t"
4447f5d130aSMark de Wever            "%I='12'\t"
4457f5d130aSMark de Wever            "%OI='十二'\t"
4467f5d130aSMark de Wever            "%M='00'\t"
4477f5d130aSMark de Wever            "%OM='〇'\t"
4487f5d130aSMark de Wever            "%S='00'\t"
4497f5d130aSMark de Wever            "%OS='〇'\t"
4507f5d130aSMark de Wever            "%p='午前'\t"
4517f5d130aSMark de Wever            "%R='00:00'\t"
4527f5d130aSMark de Wever            "%T='00:00:00'\t"
4537f5d130aSMark de Wever            "%r='午前12時00分00秒'\t"
4547f5d130aSMark de Wever            "%X='00時00分00秒'\t"
4557f5d130aSMark de Wever            "%EX='00時00分00秒'\t"
4567f5d130aSMark de Wever            "\n"),
4577f5d130aSMark de Wever         lfmt,
4587f5d130aSMark de Wever         std::chrono::hh_mm_ss(0s));
4597f5d130aSMark de Wever 
4607f5d130aSMark de Wever   // TODO FMT What should fractions be in alternate display mode?
4617f5d130aSMark de Wever   check(loc,
4627f5d130aSMark de Wever         SV("%H='23'\t"
4637f5d130aSMark de Wever            "%OH='二十三'\t"
4647f5d130aSMark de Wever            "%I='11'\t"
4657f5d130aSMark de Wever            "%OI='十一'\t"
4667f5d130aSMark de Wever            "%M='31'\t"
4677f5d130aSMark de Wever            "%OM='三十一'\t"
4687f5d130aSMark de Wever            "%S='30.123'\t"
4697f5d130aSMark de Wever            "%OS='三十.123'\t"
4707f5d130aSMark de Wever            "%p='午後'\t"
4717f5d130aSMark de Wever            "%R='23:31'\t"
4727f5d130aSMark de Wever            "%T='23:31:30.123'\t"
4737f5d130aSMark de Wever            "%r='午後11時31分30秒'\t"
4747f5d130aSMark de Wever            "%X='23時31分30秒'\t"
4757f5d130aSMark de Wever            "%EX='23時31分30秒'\t"
4767f5d130aSMark de Wever            "\n"),
4777f5d130aSMark de Wever         lfmt,
4787f5d130aSMark de Wever         std::chrono::hh_mm_ss(23h + 31min + 30s + 123ms));
4797f5d130aSMark de Wever 
4807f5d130aSMark de Wever   check(loc,
4817f5d130aSMark de Wever         SV("-%H='03'\t"
4827f5d130aSMark de Wever            "%OH='三'\t"
4837f5d130aSMark de Wever            "%I='03'\t"
4847f5d130aSMark de Wever            "%OI='三'\t"
4857f5d130aSMark de Wever            "%M='02'\t"
4867f5d130aSMark de Wever            "%OM='二'\t"
4877f5d130aSMark de Wever            "%S='01.123456789012'\t"
4887f5d130aSMark de Wever            "%OS='一.123456789012'\t"
4897f5d130aSMark de Wever            "%p='午前'\t"
4907f5d130aSMark de Wever            "%R='03:02'\t"
4917f5d130aSMark de Wever            "%T='03:02:01.123456789012'\t"
4927f5d130aSMark de Wever            "%r='午前03時02分01秒'\t"
4937f5d130aSMark de Wever            "%X='03時02分01秒'\t"
4947f5d130aSMark de Wever            "%EX='03時02分01秒'\t"
4957f5d130aSMark de Wever            "\n"),
4967f5d130aSMark de Wever         lfmt,
497bd5d0feeSMark de Wever         std::chrono::hh_mm_ss(-(3h + 2min + 1s + std::chrono::duration<std::int64_t, std::pico>(123456789012))));
4987f5d130aSMark de Wever 
4997f5d130aSMark de Wever   check(loc,
5007f5d130aSMark de Wever         SV("%H='01'\t"
5017f5d130aSMark de Wever            "%OH='一'\t"
5027f5d130aSMark de Wever            "%I='01'\t"
5037f5d130aSMark de Wever            "%OI='一'\t"
5047f5d130aSMark de Wever            "%M='01'\t"
5057f5d130aSMark de Wever            "%OM='一'\t"
5067f5d130aSMark de Wever            "%S='01'\t"
5077f5d130aSMark de Wever            "%OS='一'\t"
5087f5d130aSMark de Wever            "%p='午前'\t"
5097f5d130aSMark de Wever            "%R='01:01'\t"
5107f5d130aSMark de Wever            "%T='01:01:01'\t"
5117f5d130aSMark de Wever            "%r='午前01時01分01秒'\t"
5127f5d130aSMark de Wever            "%X='01時01分01秒'\t"
5137f5d130aSMark de Wever            "%EX='01時01分01秒'\t"
5147f5d130aSMark de Wever            "\n"),
5157f5d130aSMark de Wever         lfmt,
5167f5d130aSMark de Wever         std::chrono::hh_mm_ss(std::chrono::duration<double>(3661.123456)));
5171403080aSMark de Wever #endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32)
5187f5d130aSMark de Wever 
5197f5d130aSMark de Wever   std::locale::global(std::locale::classic());
5207f5d130aSMark de Wever }
5217f5d130aSMark de Wever 
5227f5d130aSMark de Wever template <class CharT>
5237f5d130aSMark de Wever static void test_invalid_values() {
5247f5d130aSMark de Wever   using namespace std::literals::chrono_literals;
5257f5d130aSMark de Wever 
5267f5d130aSMark de Wever   // This looks odd, however the 24 hours is not valid for a 24 hour clock.
5277f5d130aSMark de Wever   // TODO FMT discuss what the "proper" behaviour is.
528402eb2efSMark de Wever   check_exception("Formatting a hour needs a valid value", SV("{:%H"), std::chrono::hh_mm_ss{24h});
529402eb2efSMark de Wever   check_exception("Formatting a hour needs a valid value", SV("{:%OH"), std::chrono::hh_mm_ss{24h});
530402eb2efSMark de Wever   check_exception("Formatting a hour needs a valid value", SV("{:%I"), std::chrono::hh_mm_ss{24h});
531402eb2efSMark de Wever   check_exception("Formatting a hour needs a valid value", SV("{:%OI"), std::chrono::hh_mm_ss{24h});
5327f5d130aSMark de Wever   check(SV("00"), SV("{:%M}"), std::chrono::hh_mm_ss{24h});
5337f5d130aSMark de Wever   check(SV("00"), SV("{:%OM}"), std::chrono::hh_mm_ss{24h});
5347f5d130aSMark de Wever   check(SV("00"), SV("{:%S}"), std::chrono::hh_mm_ss{24h});
5357f5d130aSMark de Wever   check(SV("00"), SV("{:%OS}"), std::chrono::hh_mm_ss{24h});
536402eb2efSMark de Wever   check_exception("Formatting a hour needs a valid value", SV("{:%p"), std::chrono::hh_mm_ss{24h});
537402eb2efSMark de Wever   check_exception("Formatting a hour needs a valid value", SV("{:%R"), std::chrono::hh_mm_ss{24h});
538402eb2efSMark de Wever   check_exception("Formatting a hour needs a valid value", SV("{:%T"), std::chrono::hh_mm_ss{24h});
539402eb2efSMark de Wever   check_exception("Formatting a hour needs a valid value", SV("{:%r"), std::chrono::hh_mm_ss{24h});
540402eb2efSMark de Wever   check_exception("Formatting a hour needs a valid value", SV("{:%X"), std::chrono::hh_mm_ss{24h});
541402eb2efSMark de Wever   check_exception("Formatting a hour needs a valid value", SV("{:%EX"), std::chrono::hh_mm_ss{24h});
5427f5d130aSMark de Wever }
5437f5d130aSMark de Wever 
5447f5d130aSMark de Wever template <class CharT>
5457f5d130aSMark de Wever static void test() {
5467f5d130aSMark de Wever   using namespace std::literals::chrono_literals;
5477f5d130aSMark de Wever 
5487f5d130aSMark de Wever   test_no_chrono_specs<CharT>();
5497f5d130aSMark de Wever   test_valid_values<CharT>();
5507f5d130aSMark de Wever   test_invalid_values<CharT>();
5517f5d130aSMark de Wever   check_invalid_types<CharT>(
5527f5d130aSMark de Wever       {SV("H"),
5537f5d130aSMark de Wever        SV("I"),
5547f5d130aSMark de Wever        SV("M"),
5557f5d130aSMark de Wever        SV("S"),
5567f5d130aSMark de Wever        SV("p"),
5577f5d130aSMark de Wever        SV("r"),
5587f5d130aSMark de Wever        SV("R"),
5597f5d130aSMark de Wever        SV("T"),
5607f5d130aSMark de Wever        SV("X"),
5617f5d130aSMark de Wever        SV("OH"),
5627f5d130aSMark de Wever        SV("OI"),
5637f5d130aSMark de Wever        SV("OM"),
5647f5d130aSMark de Wever        SV("OS"),
5657f5d130aSMark de Wever        SV("EX")},
5667f5d130aSMark de Wever       std::chrono::hh_mm_ss{0ms});
5677f5d130aSMark de Wever 
568402eb2efSMark de Wever   check_exception("The format specifier expects a '%' or a '}'", SV("{:A"), std::chrono::hh_mm_ss{0ms});
569402eb2efSMark de Wever   check_exception("The chrono specifiers contain a '{'", SV("{:%%{"), std::chrono::hh_mm_ss{0ms});
570402eb2efSMark de Wever   check_exception("End of input while parsing a conversion specifier", SV("{:%"), std::chrono::hh_mm_ss{0ms});
5717f5d130aSMark de Wever   check_exception("End of input while parsing the modifier E", SV("{:%E"), std::chrono::hh_mm_ss{0ms});
5727f5d130aSMark de Wever   check_exception("End of input while parsing the modifier O", SV("{:%O"), std::chrono::hh_mm_ss{0ms});
5737f5d130aSMark de Wever 
574402eb2efSMark de Wever   check_exception("The format specifier expects a '%' or a '}'", SV("{:.3}"), std::chrono::hh_mm_ss{0ms});
5757f5d130aSMark de Wever }
5767f5d130aSMark de Wever 
5777f5d130aSMark de Wever int main(int, char**) {
5787f5d130aSMark de Wever   test<char>();
5797f5d130aSMark de Wever 
5807f5d130aSMark de Wever #ifndef TEST_HAS_NO_WIDE_CHARACTERS
5817f5d130aSMark de Wever   test<wchar_t>();
5827f5d130aSMark de Wever #endif
5837f5d130aSMark de Wever 
5847f5d130aSMark de Wever   return 0;
5857f5d130aSMark de Wever }
586