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-filesystem, no-localization, no-tzdb
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, class traits, class Duration, class TimeZonePtr>
23// basic_ostream<charT, traits>&
24// operator<<(basic_ostream<charT, traits>& os,
25// const zoned_time<Duration, TimeZonePtr>& t);
26
27#include <chrono>
28#include <cassert>
29#include <sstream>
30
31#include "assert_macros.h"
32#include "concat_macros.h"
33#include "make_string.h"
34#include "platform_support.h" // locale name macros
35#include "test_macros.h"
36#include "../test_offset_time_zone.h"
37
38#define SV(S) MAKE_STRING_VIEW(CharT, S)
39
40#define TEST_EQUAL(OUT, EXPECTED) \
41 TEST_REQUIRE(OUT == EXPECTED, \
42 TEST_WRITE_CONCATENATED( \
43 "\nExpression ", #OUT, "\nExpected output ", EXPECTED, "\nActual output ", OUT, '\n'));
44
45template <class CharT, class Duration, class TimeZonePtr>
46static std::basic_string<CharT> stream_c_locale(std::chrono::zoned_time<Duration, TimeZonePtr> time_point) {
47 std::basic_stringstream<CharT> sstr;
48 sstr << time_point;
49 return sstr.str();
50}
51
52template <class CharT, class Duration, class TimeZonePtr>
53static std::basic_string<CharT> stream_fr_FR_locale(std::chrono::zoned_time<Duration, TimeZonePtr> time_point) {
54 std::basic_stringstream<CharT> sstr;
55 const std::locale locale(LOCALE_fr_FR_UTF_8);
56 sstr.imbue(locale);
57 sstr << time_point;
58 return sstr.str();
59}
60
61template <class CharT, class Duration, class TimeZonePtr>
62static std::basic_string<CharT> stream_ja_JP_locale(std::chrono::zoned_time<Duration, TimeZonePtr> time_point) {
63 std::basic_stringstream<CharT> sstr;
64 const std::locale locale(LOCALE_ja_JP_UTF_8);
65 sstr.imbue(locale);
66 sstr << time_point;
67 return sstr.str();
68}
69
70template <class CharT>
71static void test_c() {
72 using namespace std::literals::chrono_literals;
73
74 { // Different durations
75 TEST_EQUAL(stream_c_locale<CharT>(
76 std::chrono::zoned_time("Etc/GMT-1", std::chrono::sys_time<std::chrono::nanoseconds>{42ns})),
77 SV("1970-01-01 01:00:00.000000042 +01"));
78
79 TEST_EQUAL(stream_c_locale<CharT>(
80 std::chrono::zoned_time("Etc/GMT-1", std::chrono::sys_time<std::chrono::microseconds>{42us})),
81 SV("1970-01-01 01:00:00.000042 +01"));
82
83 TEST_EQUAL(stream_c_locale<CharT>(
84 std::chrono::zoned_time("Etc/GMT-1", std::chrono::sys_time<std::chrono::milliseconds>{42ms})),
85 SV("1970-01-01 01:00:00.042 +01"));
86
87 TEST_EQUAL(
88 stream_c_locale<CharT>(std::chrono::zoned_time("Etc/GMT-1", std::chrono::sys_time<std::chrono::seconds>{42s})),
89 SV("1970-01-01 01:00:42 +01"));
90
91 TEST_EQUAL(stream_c_locale<CharT>(std::chrono::zoned_time(
92 "Etc/GMT-1", std::chrono::sys_time<std::chrono::days>{std::chrono::days{42}})),
93 SV("1970-02-12 01:00:00 +01"));
94
95 TEST_EQUAL(stream_c_locale<CharT>(std::chrono::zoned_time(
96 "Etc/GMT-1", std::chrono::sys_time<std::chrono::weeks>{std::chrono::weeks{42}})),
97 SV("1970-10-22 01:00:00 +01"));
98 }
99
100 { // Daylight saving time switches
101 // Pick an historic date where it's well known what the time zone rules were.
102 // This makes it unlikely updates to the database change these rules.
103
104 // Z Europe/Berlin 0:53:28 - LMT 1893 Ap
105 // ...
106 // 1 DE CE%sT 1980
107 // 1 E CE%sT
108 //
109 // ...
110 // R E 1979 1995 - S lastSu 1u 0 -
111 // R E 1981 ma - Mar lastSu 1u 1 S
112
113 // Pick an historic date where it's well known what the time zone rules were.
114 // This makes it unlikely updates to the database change these rules.
115
116 // Start of daylight saving time
117 TEST_EQUAL(stream_c_locale<CharT>(std::chrono::zoned_time(
118 "Europe/Berlin", std::chrono::sys_days{std::chrono::March / 30 / 1986} + 0h + 59min + 59s)),
119 SV("1986-03-30 01:59:59 CET"));
120
121 TEST_EQUAL(stream_c_locale<CharT>(std::chrono::zoned_time(
122 "Europe/Berlin", std::chrono::sys_days{std::chrono::March / 30 / 1986} + 1h)),
123 SV("1986-03-30 03:00:00 CEST"));
124
125 // End of daylight saving time
126 TEST_EQUAL(stream_c_locale<CharT>(std::chrono::zoned_time(
127 "Europe/Berlin", std::chrono::sys_days{std::chrono::September / 28 / 1986} + 0h + 59min + 59s)),
128 SV("1986-09-28 02:59:59 CEST"));
129
130 TEST_EQUAL(stream_c_locale<CharT>(std::chrono::zoned_time(
131 "Europe/Berlin", std::chrono::sys_days{std::chrono::September / 28 / 1986} + 1h)),
132 SV("1986-09-28 02:00:00 CET"));
133
134 TEST_EQUAL(stream_c_locale<CharT>(std::chrono::zoned_time(
135 "Europe/Berlin", std::chrono::sys_days{std::chrono::September / 28 / 1986} + 1h + 59min + 59s)),
136 SV("1986-09-28 02:59:59 CET"));
137
138 TEST_EQUAL(stream_c_locale<CharT>(std::chrono::zoned_time(
139 "Europe/Berlin", std::chrono::sys_days{std::chrono::September / 28 / 1986} + 2h)),
140 SV("1986-09-28 03:00:00 CET"));
141 }
142
143 { // offset pointer
144 TEST_EQUAL(stream_c_locale<CharT>(std::chrono::zoned_time(
145 offset_time_zone<offset_time_zone_flags::none>{}, std::chrono::sys_seconds{})),
146 SV("1970-01-01 00:00:00 +00s"));
147
148 TEST_EQUAL(stream_c_locale<CharT>(std::chrono::zoned_time(
149 offset_time_zone<offset_time_zone_flags::none>{"42"}, std::chrono::sys_seconds{})),
150 SV("1969-12-31 23:59:18 +42s"));
151
152 TEST_EQUAL(stream_c_locale<CharT>(std::chrono::zoned_time(
153 offset_time_zone<offset_time_zone_flags::none>{"-42"}, std::chrono::sys_seconds{})),
154 SV("1970-01-01 00:00:42 -42s"));
155 }
156}
157
158template <class CharT>
159static void test_fr_FR() {
160 using namespace std::literals::chrono_literals;
161
162 { // Different durations
163
164 TEST_EQUAL(stream_fr_FR_locale<CharT>(
165 std::chrono::zoned_time("Etc/GMT-1", std::chrono::sys_time<std::chrono::nanoseconds>{42ns})),
166 SV("1970-01-01 01:00:00,000000042 +01"));
167
168 TEST_EQUAL(stream_fr_FR_locale<CharT>(
169 std::chrono::zoned_time("Etc/GMT-1", std::chrono::sys_time<std::chrono::microseconds>{42us})),
170 SV("1970-01-01 01:00:00,000042 +01"));
171
172 TEST_EQUAL(stream_fr_FR_locale<CharT>(
173 std::chrono::zoned_time("Etc/GMT-1", std::chrono::sys_time<std::chrono::milliseconds>{42ms})),
174 SV("1970-01-01 01:00:00,042 +01"));
175
176 TEST_EQUAL(stream_fr_FR_locale<CharT>(
177 std::chrono::zoned_time("Etc/GMT-1", std::chrono::sys_time<std::chrono::seconds>{42s})),
178 SV("1970-01-01 01:00:42 +01"));
179
180 TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::zoned_time(
181 "Etc/GMT-1", std::chrono::sys_time<std::chrono::days>{std::chrono::days{42}})),
182 SV("1970-02-12 01:00:00 +01"));
183
184 TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::zoned_time(
185 "Etc/GMT-1", std::chrono::sys_time<std::chrono::weeks>{std::chrono::weeks{42}})),
186 SV("1970-10-22 01:00:00 +01"));
187 }
188
189 { // Daylight saving time switches
190 // Pick an historic date where it's well known what the time zone rules were.
191 // This makes it unlikely updates to the database change these rules.
192
193 // Z Europe/Berlin 0:53:28 - LMT 1893 Ap
194 // ...
195 // 1 DE CE%sT 1980
196 // 1 E CE%sT
197 //
198 // ...
199 // R E 1979 1995 - S lastSu 1u 0 -
200 // R E 1981 ma - Mar lastSu 1u 1 S
201
202 // Pick an historic date where it's well known what the time zone rules were.
203 // This makes it unlikely updates to the database change these rules.
204
205 // Start of daylight saving time
206 TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::zoned_time(
207 "Europe/Berlin", std::chrono::sys_days{std::chrono::March / 30 / 1986} + 0h + 59min + 59s)),
208 SV("1986-03-30 01:59:59 CET"));
209
210 TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::zoned_time(
211 "Europe/Berlin", std::chrono::sys_days{std::chrono::March / 30 / 1986} + 1h)),
212 SV("1986-03-30 03:00:00 CEST"));
213
214 // End of daylight saving time
215 TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::zoned_time(
216 "Europe/Berlin", std::chrono::sys_days{std::chrono::September / 28 / 1986} + 0h + 59min + 59s)),
217 SV("1986-09-28 02:59:59 CEST"));
218
219 TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::zoned_time(
220 "Europe/Berlin", std::chrono::sys_days{std::chrono::September / 28 / 1986} + 1h)),
221 SV("1986-09-28 02:00:00 CET"));
222
223 TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::zoned_time(
224 "Europe/Berlin", std::chrono::sys_days{std::chrono::September / 28 / 1986} + 1h + 59min + 59s)),
225 SV("1986-09-28 02:59:59 CET"));
226
227 TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::zoned_time(
228 "Europe/Berlin", std::chrono::sys_days{std::chrono::September / 28 / 1986} + 2h)),
229 SV("1986-09-28 03:00:00 CET"));
230 }
231
232 { // offset pointer
233 TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::zoned_time(
234 offset_time_zone<offset_time_zone_flags::none>{}, std::chrono::sys_seconds{})),
235 SV("1970-01-01 00:00:00 +00s"));
236
237 TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::zoned_time(
238 offset_time_zone<offset_time_zone_flags::none>{"42"}, std::chrono::sys_seconds{})),
239 SV("1969-12-31 23:59:18 +42s"));
240
241 TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::zoned_time(
242 offset_time_zone<offset_time_zone_flags::none>{"-42"}, std::chrono::sys_seconds{})),
243 SV("1970-01-01 00:00:42 -42s"));
244 }
245}
246
247template <class CharT>
248static void test_ja_JP() {
249 using namespace std::literals::chrono_literals;
250
251 { // Different durations
252
253 TEST_EQUAL(stream_ja_JP_locale<CharT>(
254 std::chrono::zoned_time("Etc/GMT-1", std::chrono::sys_time<std::chrono::nanoseconds>{42ns})),
255 SV("1970-01-01 01:00:00.000000042 +01"));
256
257 TEST_EQUAL(stream_ja_JP_locale<CharT>(
258 std::chrono::zoned_time("Etc/GMT-1", std::chrono::sys_time<std::chrono::microseconds>{42us})),
259 SV("1970-01-01 01:00:00.000042 +01"));
260
261 TEST_EQUAL(stream_ja_JP_locale<CharT>(
262 std::chrono::zoned_time("Etc/GMT-1", std::chrono::sys_time<std::chrono::milliseconds>{42ms})),
263 SV("1970-01-01 01:00:00.042 +01"));
264
265 TEST_EQUAL(stream_ja_JP_locale<CharT>(
266 std::chrono::zoned_time("Etc/GMT-1", std::chrono::sys_time<std::chrono::seconds>{42s})),
267 SV("1970-01-01 01:00:42 +01"));
268
269 TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::zoned_time(
270 "Etc/GMT-1", std::chrono::sys_time<std::chrono::days>{std::chrono::days{42}})),
271 SV("1970-02-12 01:00:00 +01"));
272
273 TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::zoned_time(
274 "Etc/GMT-1", std::chrono::sys_time<std::chrono::weeks>{std::chrono::weeks{42}})),
275 SV("1970-10-22 01:00:00 +01"));
276 }
277
278 { // Daylight saving time switches
279 // Pick an historic date where it's well known what the time zone rules were.
280 // This makes it unlikely updates to the database change these rules.
281
282 // Z Europe/Berlin 0:53:28 - LMT 1893 Ap
283 // ...
284 // 1 DE CE%sT 1980
285 // 1 E CE%sT
286 //
287 // ...
288 // R E 1979 1995 - S lastSu 1u 0 -
289 // R E 1981 ma - Mar lastSu 1u 1 S
290
291 // Pick an historic date where it's well known what the time zone rules were.
292 // This makes it unlikely updates to the database change these rules.
293
294 // Start of daylight saving time
295 TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::zoned_time(
296 "Europe/Berlin", std::chrono::sys_days{std::chrono::March / 30 / 1986} + 0h + 59min + 59s)),
297 SV("1986-03-30 01:59:59 CET"));
298
299 TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::zoned_time(
300 "Europe/Berlin", std::chrono::sys_days{std::chrono::March / 30 / 1986} + 1h)),
301 SV("1986-03-30 03:00:00 CEST"));
302
303 // End of daylight saving time
304 TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::zoned_time(
305 "Europe/Berlin", std::chrono::sys_days{std::chrono::September / 28 / 1986} + 0h + 59min + 59s)),
306 SV("1986-09-28 02:59:59 CEST"));
307
308 TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::zoned_time(
309 "Europe/Berlin", std::chrono::sys_days{std::chrono::September / 28 / 1986} + 1h)),
310 SV("1986-09-28 02:00:00 CET"));
311
312 TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::zoned_time(
313 "Europe/Berlin", std::chrono::sys_days{std::chrono::September / 28 / 1986} + 1h + 59min + 59s)),
314 SV("1986-09-28 02:59:59 CET"));
315
316 TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::zoned_time(
317 "Europe/Berlin", std::chrono::sys_days{std::chrono::September / 28 / 1986} + 2h)),
318 SV("1986-09-28 03:00:00 CET"));
319 }
320
321 { // offset pointer
322 TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::zoned_time(
323 offset_time_zone<offset_time_zone_flags::none>{}, std::chrono::sys_seconds{})),
324 SV("1970-01-01 00:00:00 +00s"));
325
326 TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::zoned_time(
327 offset_time_zone<offset_time_zone_flags::none>{"42"}, std::chrono::sys_seconds{})),
328 SV("1969-12-31 23:59:18 +42s"));
329
330 TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::zoned_time(
331 offset_time_zone<offset_time_zone_flags::none>{"-42"}, std::chrono::sys_seconds{})),
332 SV("1970-01-01 00:00:42 -42s"));
333 }
334}
335
336template <class CharT>
337static void test() {
338 test_c<CharT>();
339 test_fr_FR<CharT>();
340 test_ja_JP<CharT>();
341}
342
343int main(int, char**) {
344 test<char>();
345
346#ifndef TEST_HAS_NO_WIDE_CHARACTERS
347 test<wchar_t>();
348#endif
349
350 return 0;
351}
352

source code of libcxx/test/std/time/time.zone/time.zone.zonedtime/time.zone.zonedtime.nonmembers/ostream.pass.cpp