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 ambiguous_local_time
18 //
19 //  template<class Duration>
20 //    ambiguous_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::ambiguous_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   // overlap 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::ambiguous,
50            std::chrono::sys_info{
51                std::chrono::sys_days{std::chrono::January / 1 / 1970},
52                std::chrono::sys_days{std::chrono::March / 1 / 1970},
53                1h,
54                60min,
55                "PREV"},
56 
57            std::chrono::sys_info{
58                std::chrono::sys_days{std::chrono::September / 1 / 1969},
59                std::chrono::sys_days{std::chrono::December / 31 / 1969} + 23h,
60                0s,
61                0min,
62                "NEXT"}
63 
64        },
65        R"(1969-12-31 23:59:59.999999999 is ambiguous.  It could be
66 1969-12-31 23:59:59.999999999 PREV == 1969-12-31 22:59:59.999999999 UTC or
67 1969-12-31 23:59:59.999999999 NEXT == 1969-12-31 23:59:59.999999999 UTC)");
68 
69   test(std::chrono::local_time<std::chrono::microseconds>{0us},
70        std::chrono::local_info{
71            std::chrono::local_info::ambiguous,
72            std::chrono::sys_info{
73                std::chrono::sys_days{std::chrono::January / 1 / 1970},
74                std::chrono::sys_days{std::chrono::March / 1 / 1970},
75                1h,
76                60min,
77                "PREV"},
78 
79            std::chrono::sys_info{
80                std::chrono::sys_days{std::chrono::September / 1 / 1969},
81                std::chrono::sys_days{std::chrono::December / 31 / 1969} + 23h,
82                0s,
83                0min,
84                "NEXT"}},
85        R"(1970-01-01 00:00:00.000000 is ambiguous.  It could be
86 1970-01-01 00:00:00.000000 PREV == 1969-12-31 23:00:00.000000 UTC or
87 1970-01-01 00:00:00.000000 NEXT == 1970-01-01 00:00:00.000000 UTC)");
88 
89   test(std::chrono::local_time<std::chrono::milliseconds>{1ms},
90        std::chrono::local_info{
91            std::chrono::local_info::ambiguous,
92            std::chrono::sys_info{
93                std::chrono::sys_days{std::chrono::January / 1 / 1970},
94                std::chrono::sys_days{std::chrono::March / 1 / 1970},
95                1h,
96                60min,
97                "PREV"},
98 
99            std::chrono::sys_info{
100                std::chrono::sys_days{std::chrono::September / 1 / 1969},
101                std::chrono::sys_days{std::chrono::December / 31 / 1969} + 23h,
102                0s,
103                0min,
104                "NEXT"}},
105        R"(1970-01-01 00:00:00.001 is ambiguous.  It could be
106 1970-01-01 00:00:00.001 PREV == 1969-12-31 23:00:00.001 UTC or
107 1970-01-01 00:00:00.001 NEXT == 1970-01-01 00:00:00.001 UTC)");
108 
109   test(std::chrono::local_seconds{(std::chrono::sys_days{std::chrono::January / 1 / -21970}).time_since_epoch()},
110        std::chrono::local_info{
111            std::chrono::local_info::ambiguous,
112            std::chrono::sys_info{
113                std::chrono::sys_days{std::chrono::September / 1 / -21969},
114                std::chrono::sys_days{std::chrono::December / 31 / -21969},
115                0s,
116                0min,
117                "PREV"},
118            std::chrono::sys_info{
119                std::chrono::sys_days{std::chrono::January / 1 / -21970},
120                std::chrono::sys_days{std::chrono::March / 1 / -21970} + 23h,
121                1h,
122                60min,
123                "NEXT"}},
124        R"(-21970-01-01 00:00:00 is ambiguous.  It could be
125 -21970-01-01 00:00:00 PREV == -21970-01-01 00:00:00 UTC or
126 -21970-01-01 00:00:00 NEXT == -21971-12-31 23:00:00 UTC)");
127 
128   test(
129       std::chrono::local_time<std::chrono::days>{
130           (std::chrono::sys_days{std::chrono::January / 1 / 21970}).time_since_epoch()},
131       std::chrono::local_info{
132           std::chrono::local_info::ambiguous,
133           std::chrono::sys_info{
134               std::chrono::sys_days{std::chrono::September / 1 / 21969},
135               std::chrono::sys_days{std::chrono::December / 31 / 21969},
136               0s,
137               0min,
138               "PREV"},
139           std::chrono::sys_info{
140               std::chrono::sys_days{std::chrono::January / 1 / 21970},
141               std::chrono::sys_days{std::chrono::March / 1 / 21970} + 23h,
142               1h,
143               60min,
144               "NEXT"}},
145       R"(21970-01-01 is ambiguous.  It could be
146 21970-01-01 PREV == 21970-01-01 00:00:00 UTC or
147 21970-01-01 NEXT == 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::ambiguous,
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},
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} + 23h,
161                1h,
162                60min,
163                "NEXT"}},
164        R"(1970-01-01 is ambiguous.  It could be
165 1970-01-01 PREV == 1970-01-01 00:00:00 UTC or
166 1970-01-01 NEXT == 1969-12-31 23:00:00 UTC)");
167 
168   // Note months and years can not be streamed.
169 
170   return 0;
171 }
172