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// TODO(mordante) Investigate
10// UNSUPPORTED: apple-clang
11
12// UNSUPPORTED: c++03, c++11, c++14, c++17
13// UNSUPPORTED: no-localization
14// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
15
16// TODO FMT This test should not require std::to_chars(floating-point)
17// XFAIL: availability-fp_to_chars-missing
18
19// REQUIRES: locale.fr_FR.UTF-8
20// REQUIRES: locale.ja_JP.UTF-8
21
22// ADDITIONAL_COMPILE_FLAGS: -DFR_THOU_SEP=%{LOCALE_CONV_FR_FR_UTF_8_THOUSANDS_SEP}
23// ADDITIONAL_COMPILE_FLAGS: -DFR_DEC_POINT=%{LOCALE_CONV_FR_FR_UTF_8_DECIMAL_POINT}
24
25// <chrono>
26
27// template<class Rep, class Period = ratio<1>> class duration;
28
29// template<class charT, class traits, class Rep, class Period>
30// basic_ostream<charT, traits>&
31// operator<<(basic_ostream<charT, traits>& os,
32// const duration<Rep, Period>& d);
33
34#include <chrono>
35
36#include <cassert>
37#include <concepts>
38#include <ratio>
39#include <sstream>
40
41#include "make_string.h"
42#include "locale_helpers.h"
43#include "platform_support.h" // locale name macros
44#include "test_macros.h"
45
46#define SV(S) MAKE_STRING_VIEW(CharT, S)
47
48template <class CharT, class Rep, class Period>
49static std::basic_string<CharT> stream_c_locale(std::chrono::duration<Rep, Period> duration) {
50 std::basic_stringstream<CharT> sstr;
51 sstr.precision(4);
52 sstr << std::fixed << duration;
53 return sstr.str();
54}
55
56template <class CharT, class Rep, class Period>
57static std::basic_string<CharT> stream_fr_FR_locale(std::chrono::duration<Rep, Period> duration) {
58 std::basic_stringstream<CharT> sstr;
59 const std::locale locale(LOCALE_fr_FR_UTF_8);
60 sstr.imbue(locale);
61 sstr.precision(4);
62 sstr << std::fixed << duration;
63 return sstr.str();
64}
65
66template <class CharT, class Rep, class Period>
67static std::basic_string<CharT> stream_ja_JP_locale(std::chrono::duration<Rep, Period> duration) {
68 std::basic_stringstream<CharT> sstr;
69 const std::locale locale(LOCALE_ja_JP_UTF_8);
70 sstr.imbue(locale);
71 sstr.precision(4);
72 sstr << std::fixed << duration;
73 return sstr.str();
74}
75
76template <class CharT>
77static void test_values() {
78 using namespace std::literals::chrono_literals;
79
80 assert(stream_c_locale<CharT>(-1'000'000s) == SV("-1000000s"));
81 assert(stream_c_locale<CharT>(1'000'000s) == SV("1000000s"));
82 assert(stream_c_locale<CharT>(-1'000.123456s) == SV("-1000.1235s"));
83 assert(stream_c_locale<CharT>(1'000.123456s) == SV("1000.1235s"));
84
85 if constexpr (std::same_as<CharT, char>) {
86#if defined(__APPLE__)
87 assert(stream_fr_FR_locale<CharT>(-1'000'000s) == SV("-1000000s"));
88 assert(stream_fr_FR_locale<CharT>(1'000'000s) == SV("1000000s"));
89 assert(stream_fr_FR_locale<CharT>(-1'000.123456s) == SV("-1000,1235s"));
90 assert(stream_fr_FR_locale<CharT>(1'000.123456s) == SV("1000,1235s"));
91#else
92 assert(stream_fr_FR_locale<CharT>(-1'000'000s) == SV("-1 000 000s"));
93 assert(stream_fr_FR_locale<CharT>(1'000'000s) == SV("1 000 000s"));
94 assert(stream_fr_FR_locale<CharT>(-1'000.123456s) == SV("-1 000,1235s"));
95 assert(stream_fr_FR_locale<CharT>(1'000.123456s) == SV("1 000,1235s"));
96#endif
97 } else {
98#ifndef TEST_HAS_NO_WIDE_CHARACTERS
99 assert(stream_fr_FR_locale<CharT>(-1'000'000s) == L"-1" FR_THOU_SEP "000" FR_THOU_SEP "000s");
100 assert(stream_fr_FR_locale<CharT>(1'000'000s) == L"1" FR_THOU_SEP "000" FR_THOU_SEP "000s");
101 assert(stream_fr_FR_locale<CharT>(-1'000.123456s) == L"-1" FR_THOU_SEP "000" FR_DEC_POINT "1235s");
102 assert(stream_fr_FR_locale<CharT>(1'000.123456s) == L"1" FR_THOU_SEP "000" FR_DEC_POINT "1235s");
103#endif
104 }
105
106 assert(stream_ja_JP_locale<CharT>(-1'000'000s) == SV("-1,000,000s"));
107 assert(stream_ja_JP_locale<CharT>(1'000'000s) == SV("1,000,000s"));
108 assert(stream_ja_JP_locale<CharT>(-1'000.123456s) == SV("-1,000.1235s"));
109 assert(stream_ja_JP_locale<CharT>(1'000.123456s) == SV("1,000.1235s"));
110}
111
112template <class CharT>
113static void test_units() {
114 using namespace std::literals::chrono_literals;
115
116 // C locale
117 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::atto>(0)) == SV("0as"));
118 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::femto>(0)) == SV("0fs"));
119 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::pico>(0)) == SV("0ps"));
120 assert(stream_c_locale<CharT>(0ns) == SV("0ns"));
121#ifndef TEST_HAS_NO_UNICODE
122 assert(stream_c_locale<CharT>(0us) == SV("0\u00b5s"));
123#else
124 assert(stream_c_locale<CharT>(0us) == SV("0us"));
125#endif
126 assert(stream_c_locale<CharT>(0ms) == SV("0ms"));
127 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::centi>(0)) == SV("0cs"));
128 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::deci>(0)) == SV("0ds"));
129
130 assert(stream_c_locale<CharT>(0s) == SV("0s"));
131
132 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::deca>(0)) == SV("0das"));
133 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::hecto>(0)) == SV("0hs"));
134 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::kilo>(0)) == SV("0ks"));
135 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::mega>(0)) == SV("0Ms"));
136 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::giga>(0)) == SV("0Gs"));
137 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::tera>(0)) == SV("0Ts"));
138 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::peta>(0)) == SV("0Ps"));
139 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::exa>(0)) == SV("0Es"));
140
141 assert(stream_c_locale<CharT>(0min) == SV("0min"));
142 assert(stream_c_locale<CharT>(0h) == SV("0h"));
143 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::ratio<86400>>(0)) == SV("0d"));
144
145 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::ratio<42>>(0)) == SV("0[42]s"));
146 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::ratio<33, 3>>(0)) == SV("0[11]s"));
147 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::ratio<11, 9>>(0)) == SV("0[11/9]s"));
148
149 // fr_FR locale
150 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::atto>(0)) == SV("0as"));
151 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::femto>(0)) == SV("0fs"));
152 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::pico>(0)) == SV("0ps"));
153 assert(stream_fr_FR_locale<CharT>(0ns) == SV("0ns"));
154#ifndef TEST_HAS_NO_UNICODE
155 assert(stream_fr_FR_locale<CharT>(0us) == SV("0\u00b5s"));
156#else
157 assert(stream_fr_FR_locale<CharT>(0us) == SV("0us"));
158#endif
159 assert(stream_fr_FR_locale<CharT>(0ms) == SV("0ms"));
160 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::centi>(0)) == SV("0cs"));
161 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::deci>(0)) == SV("0ds"));
162
163 assert(stream_fr_FR_locale<CharT>(0s) == SV("0s"));
164
165 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::deca>(0)) == SV("0das"));
166 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::hecto>(0)) == SV("0hs"));
167 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::kilo>(0)) == SV("0ks"));
168 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::mega>(0)) == SV("0Ms"));
169 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::giga>(0)) == SV("0Gs"));
170 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::tera>(0)) == SV("0Ts"));
171 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::peta>(0)) == SV("0Ps"));
172 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::exa>(0)) == SV("0Es"));
173
174 assert(stream_fr_FR_locale<CharT>(0min) == SV("0min"));
175 assert(stream_fr_FR_locale<CharT>(0h) == SV("0h"));
176 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::ratio<86400>>(0)) == SV("0d"));
177
178 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::ratio<42>>(0)) == SV("0[42]s"));
179 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::ratio<33, 3>>(0)) == SV("0[11]s"));
180 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::ratio<11, 9>>(0)) == SV("0[11/9]s"));
181
182 // ja_JP locale
183 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::atto>(0)) == SV("0as"));
184 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::femto>(0)) == SV("0fs"));
185 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::pico>(0)) == SV("0ps"));
186 assert(stream_ja_JP_locale<CharT>(0ns) == SV("0ns"));
187#ifndef TEST_HAS_NO_UNICODE
188 assert(stream_ja_JP_locale<CharT>(0us) == SV("0\u00b5s"));
189#else
190 assert(stream_ja_JP_locale<CharT>(0us) == SV("0us"));
191#endif
192 assert(stream_ja_JP_locale<CharT>(0ms) == SV("0ms"));
193 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::centi>(0)) == SV("0cs"));
194 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::deci>(0)) == SV("0ds"));
195
196 assert(stream_ja_JP_locale<CharT>(0s) == SV("0s"));
197
198 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::deca>(0)) == SV("0das"));
199 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::hecto>(0)) == SV("0hs"));
200 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::kilo>(0)) == SV("0ks"));
201 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::mega>(0)) == SV("0Ms"));
202 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::giga>(0)) == SV("0Gs"));
203 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::tera>(0)) == SV("0Ts"));
204 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::peta>(0)) == SV("0Ps"));
205 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::exa>(0)) == SV("0Es"));
206
207 assert(stream_ja_JP_locale<CharT>(0min) == SV("0min"));
208 assert(stream_ja_JP_locale<CharT>(0h) == SV("0h"));
209 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::ratio<86400>>(0)) == SV("0d"));
210
211 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::ratio<42>>(0)) == SV("0[42]s"));
212 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::ratio<33, 3>>(0)) == SV("0[11]s"));
213 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::ratio<11, 9>>(0)) == SV("0[11/9]s"));
214}
215
216template <class CharT>
217static void test_unsigned_types() {
218 // Reported in https://github.com/llvm/llvm-project/issues/96820
219 using namespace std::literals::chrono_literals;
220
221 // C locale
222 assert(stream_c_locale<CharT>(std::chrono::duration<unsigned short, std::atto>(0)) == SV("0as"));
223 assert(stream_c_locale<CharT>(std::chrono::duration<unsigned, std::femto>(0)) == SV("0fs"));
224 assert(stream_c_locale<CharT>(std::chrono::duration<unsigned long, std::pico>(0)) == SV("0ps"));
225 assert(stream_c_locale<CharT>(std::chrono::duration<unsigned long long, std::nano>(0)) == SV("0ns"));
226
227 // fr_FR locale
228 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<unsigned short, std::atto>(0)) == SV("0as"));
229 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<unsigned, std::femto>(0)) == SV("0fs"));
230 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<unsigned long, std::pico>(0)) == SV("0ps"));
231 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<unsigned long long, std::nano>(0)) == SV("0ns"));
232
233 // ja_JP locale
234 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<unsigned short, std::atto>(0)) == SV("0as"));
235 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<unsigned, std::femto>(0)) == SV("0fs"));
236 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<unsigned long, std::pico>(0)) == SV("0ps"));
237 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<unsigned long long, std::nano>(0)) == SV("0ns"));
238}
239
240template <class CharT>
241static void test() {
242 test_values<CharT>();
243 test_units<CharT>();
244 test_unsigned_types<CharT>();
245}
246
247int main(int, char**) {
248 test<char>();
249
250#ifndef TEST_HAS_NO_WIDE_CHARACTERS
251 test<wchar_t>();
252#endif
253
254 return 0;
255}
256

source code of libcxx/test/std/time/time.duration/time.duration.nonmember/ostream.pass.cpp