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 // XFAIL: libcpp-has-no-experimental-tzdb
13 // XFAIL: availability-tzdb-missing
14
15 // <chrono>
16
17 // class nonexistent_local_time
18 //
19 // template<class Duration>
20 // nonexistent_local_time(const local_time<Duration>& tp, const local_info& i);
21
22 #include <chrono>
23 #include <string_view>
24
25 #include "assert_macros.h"
26 #include "concat_macros.h"
27
28 template <class Duration>
29 static void
test(const std::chrono::local_time<Duration> & tp,const std::chrono::local_info & i,std::string_view expected)30 test(const std::chrono::local_time<Duration>& tp, const std::chrono::local_info& i, std::string_view expected) {
31 std::chrono::nonexistent_local_time exception{tp, i};
32 std::string_view result = exception.what();
33 TEST_REQUIRE(result == expected,
34 TEST_WRITE_CONCATENATED("Expected output\n", expected, "\n\nActual output\n", result, '\n'));
35 }
36
37 // The constructor constructs the runtime_error base class with a specific
38 // message. This implicitly tests what() too, since that is inherited from
39 // runtime_error there is no separate test for what().
main(int,char **)40 int main(int, char**) {
41 using namespace std::literals::chrono_literals;
42
43 // There is no requirement on the ordering of PREV and NEXT so an "invalid"
44 // gap is allowed. All tests with negative dates use the same order as
45 // positive tests.
46
47 test(std::chrono::local_time<std::chrono::nanoseconds>{-1ns},
48 std::chrono::local_info{
49 std::chrono::local_info::nonexistent,
50 std::chrono::sys_info{
51 std::chrono::sys_days{std::chrono::September / 1 / 1969},
52 std::chrono::sys_days{std::chrono::December / 31 / 1969} + 23h,
53 0s,
54 0min,
55 "PREV"},
56 std::chrono::sys_info{
57 std::chrono::sys_days{std::chrono::January / 1 / 1970},
58 std::chrono::sys_days{std::chrono::March / 1 / 1970},
59 1h,
60 60min,
61 "NEXT"}},
62 R"(1969-12-31 23:59:59.999999999 is in a gap between
63 1969-12-31 23:00:00 PREV and
64 1970-01-01 01:00:00 NEXT which are both equivalent to
65 1969-12-31 23:00:00 UTC)");
66
67 test(std::chrono::local_time<std::chrono::microseconds>{0us},
68 std::chrono::local_info{
69 std::chrono::local_info::nonexistent,
70 std::chrono::sys_info{
71 std::chrono::sys_days{std::chrono::September / 1 / 1969},
72 std::chrono::sys_days{std::chrono::December / 31 / 1969} + 23h,
73 0s,
74 0min,
75 "PREV"},
76 std::chrono::sys_info{
77 std::chrono::sys_days{std::chrono::January / 1 / 1970},
78 std::chrono::sys_days{std::chrono::March / 1 / 1970},
79 1h,
80 60min,
81 "NEXT"}},
82 R"(1970-01-01 00:00:00.000000 is in a gap between
83 1969-12-31 23:00:00 PREV and
84 1970-01-01 01:00:00 NEXT which are both equivalent to
85 1969-12-31 23:00:00 UTC)");
86
87 test(std::chrono::local_time<std::chrono::milliseconds>{1ms},
88 std::chrono::local_info{
89 std::chrono::local_info::nonexistent,
90 std::chrono::sys_info{
91 std::chrono::sys_days{std::chrono::September / 1 / 1969},
92 std::chrono::sys_days{std::chrono::December / 31 / 1969} + 23h,
93 0s,
94 0min,
95 "PREV"},
96 std::chrono::sys_info{
97 std::chrono::sys_days{std::chrono::January / 1 / 1970},
98 std::chrono::sys_days{std::chrono::March / 1 / 1970},
99 1h,
100 60min,
101 "NEXT"}},
102 R"(1970-01-01 00:00:00.001 is in a gap between
103 1969-12-31 23:00:00 PREV and
104 1970-01-01 01:00:00 NEXT which are both equivalent to
105 1969-12-31 23:00:00 UTC)");
106
107 test(std::chrono::local_seconds{(std::chrono::sys_days{std::chrono::January / 1 / -21970}).time_since_epoch()},
108 std::chrono::local_info{
109 std::chrono::local_info::nonexistent,
110 std::chrono::sys_info{
111 std::chrono::sys_days{std::chrono::September / 1 / -21969},
112 std::chrono::sys_days{std::chrono::December / 31 / -21969} + 23h,
113 0s,
114 0min,
115 "PREV"},
116 std::chrono::sys_info{
117 std::chrono::sys_days{std::chrono::January / 1 / -21970},
118 std::chrono::sys_days{std::chrono::March / 1 / -21970},
119 1h,
120 60min,
121 "NEXT"}},
122 R"(-21970-01-01 00:00:00 is in a gap between
123 -21969-12-31 23:00:00 PREV and
124 -21970-01-01 01:00:00 NEXT which are both equivalent to
125 -21969-12-31 23:00:00 UTC)");
126
127 test(
128 std::chrono::local_time<std::chrono::days>{
129 (std::chrono::sys_days{std::chrono::January / 1 / 21970}).time_since_epoch()},
130 std::chrono::local_info{
131 std::chrono::local_info::nonexistent,
132 std::chrono::sys_info{
133 std::chrono::sys_days{std::chrono::September / 1 / 21969},
134 std::chrono::sys_days{std::chrono::December / 31 / 21969} + 23h,
135 0s,
136 0min,
137 "PREV"},
138 std::chrono::sys_info{
139 std::chrono::sys_days{std::chrono::January / 1 / 21970},
140 std::chrono::sys_days{std::chrono::March / 1 / 21970},
141 1h,
142 60min,
143 "NEXT"}},
144 R"(21970-01-01 is in a gap between
145 21969-12-31 23:00:00 PREV and
146 21970-01-01 01:00:00 NEXT which are both equivalent to
147 21969-12-31 23:00:00 UTC)");
148
149 test(std::chrono::local_time<std::chrono::weeks>{},
150 std::chrono::local_info{
151 std::chrono::local_info::nonexistent,
152 std::chrono::sys_info{
153 std::chrono::sys_days{std::chrono::September / 1 / 1969},
154 std::chrono::sys_days{std::chrono::December / 31 / 1969} + 23h,
155 0s,
156 0min,
157 "PREV"},
158 std::chrono::sys_info{
159 std::chrono::sys_days{std::chrono::January / 1 / 1970},
160 std::chrono::sys_days{std::chrono::March / 1 / 1970},
161 1h,
162 60min,
163 "NEXT"}},
164 R"(1970-01-01 is in a gap between
165 1969-12-31 23:00:00 PREV and
166 1970-01-01 01:00:00 NEXT which are both equivalent to
167 1969-12-31 23:00:00 UTC)");
168
169 // Note months and years can not be streamed.
170
171 return 0;
172 }
173