brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.2 KiB · e32b6d5 Raw
238 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// XFAIL: libcpp-has-no-experimental-tzdb13// XFAIL: availability-tzdb-missing14 15// <chrono>16 17// class time_zone;18 19// template <class _Duration>20// sys_time<common_type_t<Duration, seconds>>21//   to_sys(const local_time<Duration>& tp) const;22 23#include <chrono>24#include <format>25#include <cassert>26#include <string_view>27 28#include "test_macros.h"29#include "assert_macros.h"30#include "concat_macros.h"31 32// Tests unique conversions. To make sure the test is does not depend on changes33// in the database it uses a time zone with a fixed offset.34static void test_unique() {35  using namespace std::literals::chrono_literals;36 37  const std::chrono::time_zone* tz = std::chrono::locate_zone("Etc/GMT+1");38 39  assert(tz->to_sys(std::chrono::local_time<std::chrono::nanoseconds>{-1ns}) ==40         std::chrono::sys_time<std::chrono::nanoseconds>{-1ns + 1h});41 42  assert(tz->to_sys(std::chrono::local_time<std::chrono::microseconds>{0us}) ==43         std::chrono::sys_time<std::chrono::microseconds>{1h});44 45  assert(tz->to_sys(std::chrono::local_time<std::chrono::seconds>{46             (std::chrono::sys_days{std::chrono::January / 1 / -21970}).time_since_epoch()}) ==47         std::chrono::sys_time<std::chrono::seconds>{48             (std::chrono::sys_days{std::chrono::January / 1 / -21970}).time_since_epoch() + 1h});49 50  // sys_time<common_type_t<Duration, seconds>> is seconds for the larger types51  assert(tz->to_sys(std::chrono::local_time<std::chrono::days>{52             (std::chrono::sys_days{std::chrono::January / 1 / 21970}).time_since_epoch()}) ==53         std::chrono::sys_time<std::chrono::seconds>{54             (std::chrono::sys_days{std::chrono::January / 1 / 21970}).time_since_epoch() + 1h});55 56  assert(tz->to_sys(std::chrono::local_time<std::chrono::weeks>{}) ==57         std::chrono::sys_time<std::chrono::seconds>{58             (std::chrono::sys_days{std::chrono::January / 1 / 1970}).time_since_epoch() + 1h});59 60  // Note months and years can not be streamed; thus the function cannot be61  // instantiated for these types. (Even when there is no exception thrown.)62}63 64// Tests non-existant conversions.65static void test_nonexistent() {66#ifndef TEST_HAS_NO_EXCEPTIONS67  using namespace std::literals::chrono_literals;68 69  const std::chrono::time_zone* tz = std::chrono::locate_zone("Europe/Berlin");70 71  // Z Europe/Berlin 0:53:28 - LMT 1893 Ap72  // ...73  // 1 DE CE%sT 198074  // 1 E CE%sT75  //76  // ...77  // R E 1981 ma - Mar lastSu 1u 1 S78  // R E 1996 ma - O lastSu 1u 0 -79 80  // Pick an historic date where it's well known what the time zone rules were.81  // This makes it unlikely updates to the database change these rules.82  std::chrono::local_time<std::chrono::seconds> time{83      (std::chrono::sys_days{std::chrono::March / 30 / 1986} + 2h + 30min).time_since_epoch()};84 85  // Validates whether the database did not change.86  std::chrono::local_info info = tz->get_info(time);87  assert(info.result == std::chrono::local_info::nonexistent);88 89  TEST_VALIDATE_EXCEPTION(90      std::chrono::nonexistent_local_time,91      [&]([[maybe_unused]] const std::chrono::nonexistent_local_time& e) {92        [[maybe_unused]] std::string_view what =93            R"(1986-03-30 02:30:00.000000000 is in a gap between941986-03-30 02:00:00 CET and951986-03-30 03:00:00 CEST which are both equivalent to961986-03-30 01:00:00 UTC)";97        TEST_LIBCPP_REQUIRE(98            e.what() == what,99            TEST_WRITE_CONCATENATED("Expected exception\n", what, "\n\nActual exception\n", e.what(), '\n'));100      },101      tz->to_sys(time + 0ns));102 103  TEST_VALIDATE_EXCEPTION(104      std::chrono::nonexistent_local_time,105      [&]([[maybe_unused]] const std::chrono::nonexistent_local_time& e) {106        [[maybe_unused]] std::string_view what =107            R"(1986-03-30 02:30:00.000000 is in a gap between1081986-03-30 02:00:00 CET and1091986-03-30 03:00:00 CEST which are both equivalent to1101986-03-30 01:00:00 UTC)";111        TEST_LIBCPP_REQUIRE(112            e.what() == what,113            TEST_WRITE_CONCATENATED("Expected exception\n", what, "\n\nActual exception\n", e.what(), '\n'));114      },115      tz->to_sys(time + 0us));116 117  TEST_VALIDATE_EXCEPTION(118      std::chrono::nonexistent_local_time,119      [&]([[maybe_unused]] const std::chrono::nonexistent_local_time& e) {120        [[maybe_unused]] std::string_view what =121            R"(1986-03-30 02:30:00.000 is in a gap between1221986-03-30 02:00:00 CET and1231986-03-30 03:00:00 CEST which are both equivalent to1241986-03-30 01:00:00 UTC)";125        TEST_LIBCPP_REQUIRE(126            e.what() == what,127            TEST_WRITE_CONCATENATED("Expected exception\n", what, "\n\nActual exception\n", e.what(), '\n'));128      },129      tz->to_sys(time + 0ms));130 131  TEST_VALIDATE_EXCEPTION(132      std::chrono::nonexistent_local_time,133      [&]([[maybe_unused]] const std::chrono::nonexistent_local_time& e) {134        [[maybe_unused]] std::string_view what =135            R"(1986-03-30 02:30:00 is in a gap between1361986-03-30 02:00:00 CET and1371986-03-30 03:00:00 CEST which are both equivalent to1381986-03-30 01:00:00 UTC)";139        TEST_LIBCPP_REQUIRE(140            e.what() == what,141            TEST_WRITE_CONCATENATED("Expected exception\n", what, "\n\nActual exception\n", e.what(), '\n'));142      },143      tz->to_sys(time + 0s));144 145#endif // TEST_HAS_NO_EXCEPTIONS146}147 148// Tests ambiguous conversions.149static void test_ambiguous() {150#ifndef TEST_HAS_NO_EXCEPTIONS151  using namespace std::literals::chrono_literals;152 153  const std::chrono::time_zone* tz = std::chrono::locate_zone("Europe/Berlin");154 155  // Z Europe/Berlin 0:53:28 - LMT 1893 Ap156  // ...157  // 1 DE CE%sT 1980158  // 1 E CE%sT159  //160  // ...161  // R E 1981 ma - Mar lastSu 1u 1 S162  // R E 1996 ma - O lastSu 1u 0 -163 164  // Pick an historic date where it's well known what the time zone rules were.165  // This makes it unlikely updates to the database change these rules.166  std::chrono::local_time<std::chrono::seconds> time{167      (std::chrono::sys_days{std::chrono::September / 28 / 1986} + 2h + 30min).time_since_epoch()};168 169  // Validates whether the database did not change.170  std::chrono::local_info info = tz->get_info(time);171  assert(info.result == std::chrono::local_info::ambiguous);172 173  TEST_VALIDATE_EXCEPTION(174      std::chrono::ambiguous_local_time,175      [&]([[maybe_unused]] const std::chrono::ambiguous_local_time& e) {176        [[maybe_unused]] std::string_view what =177            R"(1986-09-28 02:30:00.000000000 is ambiguous.  It could be1781986-09-28 02:30:00.000000000 CEST == 1986-09-28 00:30:00.000000000 UTC or1791986-09-28 02:30:00.000000000 CET == 1986-09-28 01:30:00.000000000 UTC)";180        TEST_LIBCPP_REQUIRE(181            e.what() == what,182            TEST_WRITE_CONCATENATED("Expected exception\n", what, "\n\nActual exception\n", e.what(), '\n'));183      },184      tz->to_sys(time + 0ns));185 186  TEST_VALIDATE_EXCEPTION(187      std::chrono::ambiguous_local_time,188      [&]([[maybe_unused]] const std::chrono::ambiguous_local_time& e) {189        [[maybe_unused]] std::string_view what =190            R"(1986-09-28 02:30:00.000000 is ambiguous.  It could be1911986-09-28 02:30:00.000000 CEST == 1986-09-28 00:30:00.000000 UTC or1921986-09-28 02:30:00.000000 CET == 1986-09-28 01:30:00.000000 UTC)";193        TEST_LIBCPP_REQUIRE(194            e.what() == what,195            TEST_WRITE_CONCATENATED("Expected exception\n", what, "\n\nActual exception\n", e.what(), '\n'));196      },197      tz->to_sys(time + 0us));198 199  TEST_VALIDATE_EXCEPTION(200      std::chrono::ambiguous_local_time,201      [&]([[maybe_unused]] const std::chrono::ambiguous_local_time& e) {202        [[maybe_unused]] std::string_view what =203            R"(1986-09-28 02:30:00.000 is ambiguous.  It could be2041986-09-28 02:30:00.000 CEST == 1986-09-28 00:30:00.000 UTC or2051986-09-28 02:30:00.000 CET == 1986-09-28 01:30:00.000 UTC)";206        TEST_LIBCPP_REQUIRE(207            e.what() == what,208            TEST_WRITE_CONCATENATED("Expected exception\n", what, "\n\nActual exception\n", e.what(), '\n'));209      },210      tz->to_sys(time + 0ms));211 212  TEST_VALIDATE_EXCEPTION(213      std::chrono::ambiguous_local_time,214      [&]([[maybe_unused]] const std::chrono::ambiguous_local_time& e) {215        [[maybe_unused]] std::string_view what =216            R"(1986-09-28 02:30:00 is ambiguous.  It could be2171986-09-28 02:30:00 CEST == 1986-09-28 00:30:00 UTC or2181986-09-28 02:30:00 CET == 1986-09-28 01:30:00 UTC)";219        TEST_LIBCPP_REQUIRE(220            e.what() == what,221            TEST_WRITE_CONCATENATED("Expected exception\n", what, "\n\nActual exception\n", e.what(), '\n'));222      },223      tz->to_sys(time + 0s));224 225#endif // TEST_HAS_NO_EXCEPTIONS226}227 228// This test does the basic validations of this function. The library function229// uses `local_info get_info(const local_time<Duration>& tp)` as implementation230// detail. The get_info function does extensive testing of the data.231int main(int, char**) {232  test_unique();233  test_nonexistent();234  test_ambiguous();235 236  return 0;237}238