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