summaryrefslogtreecommitdiffstats
path: root/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/to_sys_choose.pass.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/to_sys_choose.pass.cpp')
-rw-r--r--libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/to_sys_choose.pass.cpp147
1 files changed, 147 insertions, 0 deletions
diff --git a/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/to_sys_choose.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/to_sys_choose.pass.cpp
new file mode 100644
index 000000000000..bad4ef352e9b
--- /dev/null
+++ b/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/to_sys_choose.pass.cpp
@@ -0,0 +1,147 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
+
+// XFAIL: libcpp-has-no-experimental-tzdb
+// XFAIL: availability-tzdb-missing
+
+// <chrono>
+
+// class time_zone;
+
+// template <class _Duration>
+// sys_time<common_type_t<Duration, seconds>>
+// to_sys(const local_time<Duration>& tp, choose z) const;
+
+#include <chrono>
+#include <format>
+#include <cassert>
+#include <string_view>
+
+#include "test_macros.h"
+
+// Tests unique conversions. To make sure the test is does not depend on changes
+// in the database it uses a time zone with a fixed offset.
+static void test_unique() {
+ using namespace std::literals::chrono_literals;
+
+ const std::chrono::time_zone* tz = std::chrono::locate_zone("Etc/GMT+1");
+
+ assert(tz->to_sys(std::chrono::local_time<std::chrono::nanoseconds>{-1ns}, std::chrono::choose::earliest) ==
+ std::chrono::sys_time<std::chrono::nanoseconds>{-1ns + 1h});
+
+ assert(tz->to_sys(std::chrono::local_time<std::chrono::microseconds>{0us}, std::chrono::choose::latest) ==
+ std::chrono::sys_time<std::chrono::microseconds>{1h});
+
+ assert(tz->to_sys(
+ std::chrono::local_time<std::chrono::seconds>{
+ (std::chrono::sys_days{std::chrono::January / 1 / -21970}).time_since_epoch()},
+ std::chrono::choose::earliest) ==
+ std::chrono::sys_time<std::chrono::seconds>{
+ (std::chrono::sys_days{std::chrono::January / 1 / -21970}).time_since_epoch() + 1h});
+
+ // sys_time<common_type_t<Duration, seconds>> is seconds for the larger types
+ assert(tz->to_sys(
+ std::chrono::local_time<std::chrono::days>{
+ (std::chrono::sys_days{std::chrono::January / 1 / 21970}).time_since_epoch()},
+ std::chrono::choose::latest) ==
+ std::chrono::sys_time<std::chrono::seconds>{
+ (std::chrono::sys_days{std::chrono::January / 1 / 21970}).time_since_epoch() + 1h});
+
+ assert(tz->to_sys(std::chrono::local_time<std::chrono::weeks>{}, std::chrono::choose::earliest) ==
+ std::chrono::sys_time<std::chrono::seconds>{
+ (std::chrono::sys_days{std::chrono::January / 1 / 1970}).time_since_epoch() + 1h});
+
+ // Note months and years cannot be streamed; however these functions don't
+ // throw an exception and thus can be used.
+ assert(tz->to_sys(std::chrono::local_time<std::chrono::months>{}, std::chrono::choose::latest) ==
+ std::chrono::sys_time<std::chrono::seconds>{
+ (std::chrono::sys_days{std::chrono::January / 1 / 1970}).time_since_epoch() + 1h});
+
+ assert(tz->to_sys(std::chrono::local_time<std::chrono::years>{}, std::chrono::choose::earliest) ==
+ std::chrono::sys_time<std::chrono::seconds>{
+ (std::chrono::sys_days{std::chrono::January / 1 / 1970}).time_since_epoch() + 1h});
+}
+
+// Tests non-existant conversions.
+static void test_nonexistent() {
+ using namespace std::literals::chrono_literals;
+
+ const std::chrono::time_zone* tz = std::chrono::locate_zone("Europe/Berlin");
+
+ // Z Europe/Berlin 0:53:28 - LMT 1893 Ap
+ // ...
+ // 1 DE CE%sT 1980
+ // 1 E CE%sT
+ //
+ // ...
+ // R E 1981 ma - Mar lastSu 1u 1 S
+ // R E 1996 ma - O lastSu 1u 0 -
+
+ // Pick an historic date where it's well known what the time zone rules were.
+ // This makes it unlikely updates to the database change these rules.
+ std::chrono::local_time<std::chrono::seconds> time{
+ (std::chrono::sys_days{std::chrono::March / 30 / 1986} + 2h + 30min).time_since_epoch()};
+
+ std::chrono::sys_seconds expected{time.time_since_epoch() - 1h};
+
+ // Validates whether the database did not change.
+ std::chrono::local_info info = tz->get_info(time);
+ assert(info.result == std::chrono::local_info::nonexistent);
+
+ assert(tz->to_sys(time + 0ns, std::chrono::choose::earliest) == expected);
+ assert(tz->to_sys(time + 0us, std::chrono::choose::latest) == expected);
+ assert(tz->to_sys(time + 0ms, std::chrono::choose::earliest) == expected);
+ assert(tz->to_sys(time + 0s, std::chrono::choose::latest) == expected);
+}
+
+// Tests ambiguous conversions.
+static void test_ambiguous() {
+ using namespace std::literals::chrono_literals;
+
+ const std::chrono::time_zone* tz = std::chrono::locate_zone("Europe/Berlin");
+
+ // Z Europe/Berlin 0:53:28 - LMT 1893 Ap
+ // ...
+ // 1 DE CE%sT 1980
+ // 1 E CE%sT
+ //
+ // ...
+ // R E 1981 ma - Mar lastSu 1u 1 S
+ // R E 1996 ma - O lastSu 1u 0 -
+
+ // Pick an historic date where it's well known what the time zone rules were.
+ // This makes it unlikely updates to the database change these rules.
+ std::chrono::local_time<std::chrono::seconds> time{
+ (std::chrono::sys_days{std::chrono::September / 28 / 1986} + 2h + 30min).time_since_epoch()};
+
+ std::chrono::sys_seconds earlier{time.time_since_epoch() - 2h};
+ std::chrono::sys_seconds later{time.time_since_epoch() - 1h};
+
+ // Validates whether the database did not change.
+ std::chrono::local_info info = tz->get_info(time);
+ assert(info.result == std::chrono::local_info::ambiguous);
+
+ assert(tz->to_sys(time + 0ns, std::chrono::choose::earliest) == earlier);
+ assert(tz->to_sys(time + 0us, std::chrono::choose::latest) == later);
+ assert(tz->to_sys(time + 0ms, std::chrono::choose::earliest) == earlier);
+ assert(tz->to_sys(time + 0s, std::chrono::choose::latest) == later);
+}
+
+// This test does the basic validations of this function. The library function
+// uses `local_info get_info(const local_time<Duration>& tp)` as implementation
+// detail. The get_info function does extensive testing of the data.
+int main(int, char**) {
+ test_unique();
+ test_nonexistent();
+ test_ambiguous();
+
+ return 0;
+}