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