352 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710// UNSUPPORTED: no-filesystem, no-localization, no-tzdb11 12// TODO FMT This test should not require std::to_chars(floating-point)13// XFAIL: availability-fp_to_chars-missing14 15// XFAIL: libcpp-has-no-experimental-tzdb16 17// REQUIRES: locale.fr_FR.UTF-818// REQUIRES: locale.ja_JP.UTF-819 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 macros35#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 durations75 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 switches101 // 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 Ap105 // ...106 // 1 DE CE%sT 1980107 // 1 E CE%sT108 //109 // ...110 // R E 1979 1995 - S lastSu 1u 0 -111 // R E 1981 ma - Mar lastSu 1u 1 S112 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 time117 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 time126 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 pointer144 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 durations163 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 switches190 // 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 Ap194 // ...195 // 1 DE CE%sT 1980196 // 1 E CE%sT197 //198 // ...199 // R E 1979 1995 - S lastSu 1u 0 -200 // R E 1981 ma - Mar lastSu 1u 1 S201 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 time206 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 time215 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 pointer233 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 durations252 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 switches279 // 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 Ap283 // ...284 // 1 DE CE%sT 1980285 // 1 E CE%sT286 //287 // ...288 // R E 1979 1995 - S lastSu 1u 0 -289 // R E 1981 ma - Mar lastSu 1u 1 S290 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 time295 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 time304 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 pointer322 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_CHARACTERS347 test<wchar_t>();348#endif349 350 return 0;351}352