1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
10 // UNSUPPORTED: no-localization
11 // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
13 // XFAIL: availability-fp_to_chars-missing
15 // REQUIRES: locale.fr_FR.UTF-8
16 // REQUIRES: locale.ja_JP.UTF-8
20 // template<class Rep, class Period, class charT>
21 // struct formatter<chrono::hh_mm_ss<duration<Rep, Period>>, charT>;
31 #include <type_traits>
33 #include "formatter_tests.h"
34 #include "make_string.h"
35 #include "platform_support.h" // locale name macros
36 #include "string_literal.h"
37 #include "test_macros.h"
39 template <class CharT
>
40 static void test_no_chrono_specs() {
41 using namespace std::literals::chrono_literals
;
43 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8
));
45 // Non localized output
46 check(SV("00:00:00.000"), SV("{}"), std::chrono::hh_mm_ss
{0ms
});
47 check(SV("*00:00:00.000*"), SV("{:*^14}"), std::chrono::hh_mm_ss
{0ms
});
48 check(SV("*00:00:00.000"), SV("{:*>13}"), std::chrono::hh_mm_ss
{0ms
});
50 std::locale::global(std::locale::classic());
53 template <class CharT
>
54 static void test_valid_values() {
55 using namespace std::literals::chrono_literals
;
57 constexpr std::basic_string_view
<CharT
> fmt
= SV(
74 constexpr std::basic_string_view
<CharT
> lfmt
= SV(
92 const std::locale
loc(LOCALE_ja_JP_UTF_8
);
93 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8
));
95 // Non localized output using C-locale
112 std::chrono::hh_mm_ss(0s
));
124 "%T='23:31:30.123'\t"
130 std::chrono::hh_mm_ss(23h
+ 31min
+ 30s
+ 123ms
));
132 check(SV("-%H='03'\t"
138 "%S='01.123456789012'\t"
139 "%OS='01.123456789012'\t"
142 "%T='03:02:01.123456789012'\t"
148 std::chrono::hh_mm_ss(-(3h
+ 2min
+ 1s
+ std::chrono::duration
<std::int64_t, std::pico
>(123456789012))));
150 // The number of fractional seconds is 0 according to the Standard
151 // TODO FMT Determine what to do.
168 std::chrono::hh_mm_ss(std::chrono::duration
<double>(3661.123456)));
170 // Use the global locale (fr_FR)
190 #elif defined(__APPLE__) || defined(__FreeBSD__)
199 std::chrono::hh_mm_ss(0s
));
215 "%T='23:31:30,123'\t"
220 #elif defined(__APPLE__) || defined(__FreeBSD__)
229 std::chrono::hh_mm_ss(23h
+ 31min
+ 30s
+ 123ms
));
231 check(SV("-%H='03'\t"
237 "%S='01,123456789012'\t"
238 "%OS='01,123456789012'\t"
245 "%T='03:02:01,123456789012'\t"
250 #elif defined(__APPLE__) || defined(__FreeBSD__)
259 std::chrono::hh_mm_ss(-(3h
+ 2min
+ 1s
+ std::chrono::duration
<std::int64_t, std::pico
>(123456789012))));
280 #elif defined(__APPLE__) || defined(__FreeBSD__)
289 std::chrono::hh_mm_ss(std::chrono::duration
<double>(3661.123456)));
291 // Use supplied locale (ja_JP). This locale has a different alternate.
292 #if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
302 # if defined(__APPLE__)
309 # if defined(__APPLE__) || defined(__FreeBSD__)
310 # if defined(__APPLE__)
317 # elif defined(_WIN32)
328 std::chrono::hh_mm_ss(0s
));
339 # if defined(__APPLE__)
345 "%T='23:31:30.123'\t"
346 # if defined(__APPLE__) || defined(__FreeBSD__)
347 # if defined(__APPLE__)
354 # elif defined(_WIN32)
365 std::chrono::hh_mm_ss(23h
+ 31min
+ 30s
+ 123ms
));
374 "%S='01.123456789012'\t"
375 "%OS='01.123456789012'\t"
376 # if defined(__APPLE__)
382 "%T='03:02:01.123456789012'\t"
383 # if defined(__APPLE__) || defined(__FreeBSD__)
384 # if defined(__APPLE__)
391 # elif defined(_WIN32)
402 std::chrono::hh_mm_ss(-(3h
+ 2min
+ 1s
+ std::chrono::duration
<std::int64_t, std::pico
>(123456789012))));
413 # if defined(__APPLE__)
420 # if defined(__APPLE__) || defined(__FreeBSD__)
421 # if defined(__APPLE__)
428 # elif defined(_WIN32)
439 std::chrono::hh_mm_ss(std::chrono::duration
<double>(3661.123456)));
440 #else // defined(__APPLE__) || defined(_AIX) || defined(_WIN32)
458 std::chrono::hh_mm_ss(0s
));
460 // TODO FMT What should fractions be in alternate display mode?
472 "%T='23:31:30.123'\t"
478 std::chrono::hh_mm_ss(23h
+ 31min
+ 30s
+ 123ms
));
487 "%S='01.123456789012'\t"
488 "%OS='一.123456789012'\t"
491 "%T='03:02:01.123456789012'\t"
497 std::chrono::hh_mm_ss(-(3h
+ 2min
+ 1s
+ std::chrono::duration
<std::int64_t, std::pico
>(123456789012))));
516 std::chrono::hh_mm_ss(std::chrono::duration
<double>(3661.123456)));
517 #endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32)
519 std::locale::global(std::locale::classic());
522 template <class CharT
>
523 static void test_invalid_values() {
524 using namespace std::literals::chrono_literals
;
526 // This looks odd, however the 24 hours is not valid for a 24 hour clock.
527 // TODO FMT discuss what the "proper" behaviour is.
528 check_exception("Formatting a hour needs a valid value", SV("{:%H"), std::chrono::hh_mm_ss
{24h
});
529 check_exception("Formatting a hour needs a valid value", SV("{:%OH"), std::chrono::hh_mm_ss
{24h
});
530 check_exception("Formatting a hour needs a valid value", SV("{:%I"), std::chrono::hh_mm_ss
{24h
});
531 check_exception("Formatting a hour needs a valid value", SV("{:%OI"), std::chrono::hh_mm_ss
{24h
});
532 check(SV("00"), SV("{:%M}"), std::chrono::hh_mm_ss
{24h
});
533 check(SV("00"), SV("{:%OM}"), std::chrono::hh_mm_ss
{24h
});
534 check(SV("00"), SV("{:%S}"), std::chrono::hh_mm_ss
{24h
});
535 check(SV("00"), SV("{:%OS}"), std::chrono::hh_mm_ss
{24h
});
536 check_exception("Formatting a hour needs a valid value", SV("{:%p"), std::chrono::hh_mm_ss
{24h
});
537 check_exception("Formatting a hour needs a valid value", SV("{:%R"), std::chrono::hh_mm_ss
{24h
});
538 check_exception("Formatting a hour needs a valid value", SV("{:%T"), std::chrono::hh_mm_ss
{24h
});
539 check_exception("Formatting a hour needs a valid value", SV("{:%r"), std::chrono::hh_mm_ss
{24h
});
540 check_exception("Formatting a hour needs a valid value", SV("{:%X"), std::chrono::hh_mm_ss
{24h
});
541 check_exception("Formatting a hour needs a valid value", SV("{:%EX"), std::chrono::hh_mm_ss
{24h
});
544 template <class CharT
>
546 using namespace std::literals::chrono_literals
;
548 test_no_chrono_specs
<CharT
>();
549 test_valid_values
<CharT
>();
550 test_invalid_values
<CharT
>();
551 check_invalid_types
<CharT
>(
566 std::chrono::hh_mm_ss
{0ms
});
568 check_exception("The format specifier expects a '%' or a '}'", SV("{:A"), std::chrono::hh_mm_ss
{0ms
});
569 check_exception("The chrono specifiers contain a '{'", SV("{:%%{"), std::chrono::hh_mm_ss
{0ms
});
570 check_exception("End of input while parsing a conversion specifier", SV("{:%"), std::chrono::hh_mm_ss
{0ms
});
571 check_exception("End of input while parsing the modifier E", SV("{:%E"), std::chrono::hh_mm_ss
{0ms
});
572 check_exception("End of input while parsing the modifier O", SV("{:%O"), std::chrono::hh_mm_ss
{0ms
});
574 check_exception("The format specifier expects a '%' or a '}'", SV("{:.3}"), std::chrono::hh_mm_ss
{0ms
});
577 int main(int, char**) {
580 #ifndef TEST_HAS_NO_WIDE_CHARACTERS