| 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 | |
| 12 | // TODO FMT This test should not require std::to_chars(floating-point) |
| 13 | // XFAIL: availability-fp_to_chars-missing |
| 14 | |
| 15 | // XFAIL: libcpp-has-no-experimental-tzdb |
| 16 | |
| 17 | // REQUIRES: locale.fr_FR.UTF-8 |
| 18 | // REQUIRES: locale.ja_JP.UTF-8 |
| 19 | |
| 20 | // <chrono> |
| 21 | // |
| 22 | // template<class charT> struct formatter<chrono::sys_info, charT>; |
| 23 | |
| 24 | #include <chrono> |
| 25 | #include <format> |
| 26 | |
| 27 | #include <cassert> |
| 28 | #include <concepts> |
| 29 | #include <locale> |
| 30 | #include <iostream> |
| 31 | #include <type_traits> |
| 32 | |
| 33 | #include "formatter_tests.h" |
| 34 | #include "make_string.h" |
| 35 | #include "platform_support.h" // locale name macros |
| 36 | #include "test_macros.h" |
| 37 | |
| 38 | template <class CharT> |
| 39 | static void test_no_chrono_specs() { |
| 40 | // This test libc++ specific due to |
| 41 | // [time.zone.info.sys]/7 |
| 42 | // Effects: Streams out the sys_info object r in an unspecified format. |
| 43 | #ifdef _LIBCPP_VERSION |
| 44 | using namespace std::literals::chrono_literals; |
| 45 | namespace tz = std::chrono; |
| 46 | |
| 47 | std::locale::global(std::locale(LOCALE_fr_FR_UTF_8)); |
| 48 | |
| 49 | // Non localized output |
| 50 | |
| 51 | check(SV("[-10484-10-16 15:30:08, 14423-03-17 15:30:07) 00:00:00 0min \"TZ\"" ), |
| 52 | SV("{}" ), |
| 53 | tz::sys_info{tz::sys_seconds::min(), tz::sys_seconds::max(), 0s, 0min, "TZ" }); |
| 54 | |
| 55 | check(SV("[1970-01-01 00:00:00, 2038-12-31 00:00:00) 12:23:45 -67min \"DMY\"" ), |
| 56 | SV("{}" ), |
| 57 | tz::sys_info{static_cast<tz::sys_days>(tz::year_month_day{1970y, tz::January, 1d}), |
| 58 | static_cast<tz::sys_days>(tz::year_month_day{2038y, tz::December, 31d}), |
| 59 | 12h + 23min + 45s, |
| 60 | -67min, |
| 61 | "DMY" }); |
| 62 | |
| 63 | std::locale::global(std::locale::classic()); |
| 64 | #endif // _LIBCPP_VERSION |
| 65 | } |
| 66 | |
| 67 | template <class CharT> |
| 68 | static void test_valid_values() { |
| 69 | using namespace std::literals::chrono_literals; |
| 70 | |
| 71 | constexpr std::basic_string_view<CharT> fmt = SV("{:%%z='%z'%t%%Ez='%Ez'%t%%Oz='%Oz'%t%%Z='%Z'%n}" ); |
| 72 | constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%z='%z'%t%%Ez='%Ez'%t%%Oz='%Oz'%t%%Z='%Z'%n}" ); |
| 73 | |
| 74 | const std::locale loc(LOCALE_ja_JP_UTF_8); |
| 75 | std::locale::global(std::locale(LOCALE_fr_FR_UTF_8)); |
| 76 | |
| 77 | // Non localized output using C-locale |
| 78 | check(SV("%z='-0200'\t%Ez='-02:00'\t%Oz='-02:00'\t%Z='NEG'\n" ), |
| 79 | fmt, |
| 80 | std::chrono::sys_info{std::chrono::sys_seconds{0s}, std::chrono::sys_seconds{0s}, -2h, 0min, "NEG" }); |
| 81 | |
| 82 | check(SV("%z='+0000'\t%Ez='+00:00'\t%Oz='+00:00'\t%Z='ZERO'\n" ), |
| 83 | fmt, |
| 84 | std::chrono::sys_info{std::chrono::sys_seconds{0s}, std::chrono::sys_seconds{0s}, 0s, 0min, "ZERO" }); |
| 85 | |
| 86 | check(SV("%z='+1115'\t%Ez='+11:15'\t%Oz='+11:15'\t%Z='POS'\n" ), |
| 87 | fmt, |
| 88 | std::chrono::sys_info{std::chrono::sys_seconds{0s}, std::chrono::sys_seconds{0s}, 11h + 15min, 0min, "POS" }); |
| 89 | |
| 90 | // Use the global locale (fr_FR) |
| 91 | check(SV("%z='-0200'\t%Ez='-02:00'\t%Oz='-02:00'\t%Z='NEG'\n" ), |
| 92 | lfmt, |
| 93 | std::chrono::sys_info{std::chrono::sys_seconds{0s}, std::chrono::sys_seconds{0s}, -2h, 0min, "NEG" }); |
| 94 | |
| 95 | check(SV("%z='+0000'\t%Ez='+00:00'\t%Oz='+00:00'\t%Z='ZERO'\n" ), |
| 96 | lfmt, |
| 97 | std::chrono::sys_info{std::chrono::sys_seconds{0s}, std::chrono::sys_seconds{0s}, 0s, 0min, "ZERO" }); |
| 98 | |
| 99 | check(SV("%z='+1115'\t%Ez='+11:15'\t%Oz='+11:15'\t%Z='POS'\n" ), |
| 100 | lfmt, |
| 101 | std::chrono::sys_info{std::chrono::sys_seconds{0s}, std::chrono::sys_seconds{0s}, 11h + 15min, 0min, "POS" }); |
| 102 | |
| 103 | // Use supplied locale (ja_JP). |
| 104 | check(loc, |
| 105 | SV("%z='-0200'\t%Ez='-02:00'\t%Oz='-02:00'\t%Z='NEG'\n" ), |
| 106 | lfmt, |
| 107 | std::chrono::sys_info{std::chrono::sys_seconds{0s}, std::chrono::sys_seconds{0s}, -2h, 0min, "NEG" }); |
| 108 | |
| 109 | check(loc, |
| 110 | SV("%z='+0000'\t%Ez='+00:00'\t%Oz='+00:00'\t%Z='ZERO'\n" ), |
| 111 | lfmt, |
| 112 | std::chrono::sys_info{std::chrono::sys_seconds{0s}, std::chrono::sys_seconds{0s}, 0s, 0min, "ZERO" }); |
| 113 | |
| 114 | check(loc, |
| 115 | SV("%z='+1115'\t%Ez='+11:15'\t%Oz='+11:15'\t%Z='POS'\n" ), |
| 116 | lfmt, |
| 117 | std::chrono::sys_info{std::chrono::sys_seconds{0s}, std::chrono::sys_seconds{0s}, 11h + 15min, 0min, "POS" }); |
| 118 | |
| 119 | std::locale::global(loc: std::locale::classic()); |
| 120 | } |
| 121 | |
| 122 | template <class CharT> |
| 123 | static void test() { |
| 124 | test_no_chrono_specs<CharT>(); |
| 125 | test_valid_values<CharT>(); |
| 126 | |
| 127 | check_invalid_types<CharT>({SV("z" ), SV("Z" ), SV("Ez" ), SV("Oz" )}, std::chrono::sys_info{}); |
| 128 | } |
| 129 | |
| 130 | int main(int, char**) { |
| 131 | test<char>(); |
| 132 | |
| 133 | #ifndef TEST_HAS_NO_WIDE_CHARACTERS |
| 134 | test<wchar_t>(); |
| 135 | #endif |
| 136 | |
| 137 | return 0; |
| 138 | } |
| 139 | |