Skip to content

Commit 2d25530

Browse files
committed
[libc++][TZDB] Adds zoned_time deduction guides.
Completes - LWG3232 Inconsistency in zoned_time deduction guides - LWG3294 zoned_time deduction guides misinterprets stringchar* Implements parts of: - P0355 Extending to chrono Calendars and Time Zones
1 parent ad83e31 commit 2d25530

File tree

3 files changed

+315
-2
lines changed

3 files changed

+315
-2
lines changed

libcxx/docs/Status/Cxx20Issues.csv

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@
167167
"`3218 <https://wg21.link/LWG3218>`__","Modifier for ``%d``\ parse flag does not match POSIX and ``format``\ specification","Belfast","","","|chrono| |format|"
168168
"`3224 <https://wg21.link/LWG3224>`__","``zoned_time``\ constructor from ``TimeZonePtr``\ does not specify initialization of ``tp_``\ ","Belfast","|Complete|","19.0","|chrono|"
169169
"`3230 <https://wg21.link/LWG3230>`__","Format specifier ``%y/%Y``\ is missing locale alternative versions","Belfast","|Complete|","16.0","|chrono| |format|"
170-
"`3232 <https://wg21.link/LWG3232>`__","Inconsistency in ``zoned_time``\ deduction guides","Belfast","","","|chrono|"
170+
"`3232 <https://wg21.link/LWG3232>`__","Inconsistency in ``zoned_time``\ deduction guides","Belfast","|Complete|","19.0","|chrono|"
171171
"`3222 <https://wg21.link/LWG3222>`__","P0574R1 introduced preconditions on non-existent parameters","Belfast","",""
172172
"`3221 <https://wg21.link/LWG3221>`__","Result of ``year_month``\ arithmetic with ``months``\ is ambiguous","Belfast","|Complete|","8.0"
173173
"`3235 <https://wg21.link/LWG3235>`__","``parse``\ manipulator without abbreviation is not callable","Belfast","",""
@@ -225,7 +225,7 @@
225225
"`3286 <https://wg21.link/LWG3286>`__","``ranges::size``\ is not required to be valid after a call to ``ranges::begin``\ on an input range","Prague","|Complete|","15.0","|ranges|"
226226
"`3291 <https://wg21.link/LWG3291>`__","``iota_view::iterator``\ has the wrong ``iterator_category``\ ","Prague","|Complete|","15.0","|ranges|"
227227
"`3292 <https://wg21.link/LWG3292>`__","``iota_view``\ is under-constrained","Prague","|Complete|","15.0","|ranges|"
228-
"`3294 <https://wg21.link/LWG3294>`__","``zoned_time``\ deduction guides misinterprets ``string``\ /``char*``\ ","Prague","","","|chrono|"
228+
"`3294 <https://wg21.link/LWG3294>`__","``zoned_time``\ deduction guides misinterprets ``string``\ /``char*``\ ","Prague","|Complete|","19.0","|chrono|"
229229
"`3296 <https://wg21.link/LWG3296>`__","Inconsistent default argument for ``basic_regex<>::assign``\ ","Prague","|Complete|",""
230230
"`3299 <https://wg21.link/LWG3299>`__","Pointers don't need customized iterator behavior","Prague","|Complete|","15.0","|ranges|"
231231
"`3300 <https://wg21.link/LWG3300>`__","Non-array ``ssize``\ overload is underconstrained","Prague","|Nothing To Do|",""

libcxx/include/__chrono/zoned_time.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
# include <__config>
2626
# include <__fwd/string_view.h>
2727
# include <__type_traits/common_type.h>
28+
# include <__type_traits/conditional.h>
29+
# include <__type_traits/remove_cvref.h>
2830
# include <__utility/move.h>
2931

3032
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -176,6 +178,32 @@ class zoned_time {
176178
sys_time<duration> __tp_;
177179
};
178180

181+
zoned_time() -> zoned_time<seconds>;
182+
183+
template <class _Duration>
184+
zoned_time(sys_time<_Duration>) -> zoned_time<common_type_t<_Duration, seconds>>;
185+
186+
template <class _TimeZonePtrOrName>
187+
using __time_zone_representation =
188+
conditional_t<is_convertible_v<_TimeZonePtrOrName, string_view>,
189+
const time_zone*,
190+
remove_cvref_t<_TimeZonePtrOrName>>;
191+
192+
template <class _TimeZonePtrOrName>
193+
zoned_time(_TimeZonePtrOrName&&) -> zoned_time<seconds, __time_zone_representation<_TimeZonePtrOrName>>;
194+
195+
template <class _TimeZonePtrOrName, class _Duration>
196+
zoned_time(_TimeZonePtrOrName&&, sys_time<_Duration>)
197+
-> zoned_time<common_type_t<_Duration, seconds>, __time_zone_representation<_TimeZonePtrOrName>>;
198+
199+
template <class _TimeZonePtrOrName, class _Duration>
200+
zoned_time(_TimeZonePtrOrName&&, local_time<_Duration>, choose = choose::earliest)
201+
-> zoned_time<common_type_t<_Duration, seconds>, __time_zone_representation<_TimeZonePtrOrName>>;
202+
203+
template <class _Duration, class _TimeZonePtrOrName, class TimeZonePtr2>
204+
zoned_time(_TimeZonePtrOrName&&, zoned_time<_Duration, TimeZonePtr2>, choose = choose::earliest)
205+
-> zoned_time<common_type_t<_Duration, seconds>, __time_zone_representation<_TimeZonePtrOrName>>;
206+
179207
} // namespace chrono
180208

181209
# endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_TIME_ZONE_DATABASE) && !defined(_LIBCPP_HAS_NO_FILESYSTEM)
Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
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+
// zoned_time() -> zoned_time<seconds>;
18+
//
19+
// template<class Duration>
20+
// zoned_time(sys_time<Duration>)
21+
// -> zoned_time<common_type_t<Duration, seconds>>;
22+
//
23+
// template<class TimeZonePtrOrName>
24+
// using time-zone-representation = // exposition only
25+
// conditional_t<is_convertible_v<TimeZonePtrOrName, string_view>,
26+
// const time_zone*,
27+
// remove_cvref_t<TimeZonePtrOrName>>;
28+
//
29+
// template<class TimeZonePtrOrName>
30+
// zoned_time(TimeZonePtrOrName&&)
31+
// -> zoned_time<seconds, time-zone-representation<TimeZonePtrOrName>>;
32+
//
33+
// template<class TimeZonePtrOrName, class Duration>
34+
// zoned_time(TimeZonePtrOrName&&, sys_time<Duration>)
35+
// -> zoned_time<common_type_t<Duration, seconds>,
36+
// time-zone-representation<TimeZonePtrOrName>>;
37+
//
38+
// template<class TimeZonePtrOrName, class Duration>
39+
// zoned_time(TimeZonePtrOrName&&, local_time<Duration>,
40+
// choose = choose::earliest)
41+
// -> zoned_time<common_type_t<Duration, seconds>,
42+
// time-zone-representation<TimeZonePtrOrName>>;
43+
//
44+
// template<class Duration, class TimeZonePtrOrName, class TimeZonePtr2>
45+
// zoned_time(TimeZonePtrOrName&&, zoned_time<Duration, TimeZonePtr2>,
46+
// choose = choose::earliest)
47+
// -> zoned_time<common_type_t<Duration, seconds>,
48+
// time-zone-representation<TimeZonePtrOrName>>;
49+
50+
#include <chrono>
51+
#include <concepts>
52+
#include <string>
53+
54+
#include "test_offset_time_zone.h"
55+
56+
// Verify the results of the constructed object.
57+
int main(int, char**) {
58+
{
59+
// zoned_time() -> zoned_time<seconds>;
60+
std::chrono::zoned_time zt;
61+
static_assert(
62+
std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>);
63+
}
64+
65+
{
66+
// template<class Duration>
67+
// zoned_time(sys_time<Duration>)
68+
// -> zoned_time<common_type_t<Duration, seconds>>;
69+
{
70+
std::chrono::zoned_time zt{std::chrono::sys_time<std::chrono::nanoseconds>{std::chrono::nanoseconds{0}}};
71+
static_assert(
72+
std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::nanoseconds, const std::chrono::time_zone*>>);
73+
}
74+
{
75+
std::chrono::zoned_time zt{std::chrono::sys_time<std::chrono::seconds>{std::chrono::seconds{0}}};
76+
static_assert(
77+
std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>);
78+
}
79+
{
80+
std::chrono::zoned_time zt{std::chrono::sys_time<std::chrono::days>{std::chrono::days{0}}};
81+
static_assert(
82+
std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>);
83+
}
84+
}
85+
86+
{
87+
// template<class TimeZonePtrOrName>
88+
// zoned_time(TimeZonePtrOrName&&)
89+
// -> zoned_time<seconds, time-zone-representation<TimeZonePtrOrName>>;
90+
{ // Name
91+
{
92+
std::chrono::zoned_time zt{"UTC"};
93+
static_assert(
94+
std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>);
95+
}
96+
{
97+
std::chrono::zoned_time zt{std::string{"UTC"}};
98+
static_assert(
99+
std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>);
100+
}
101+
{
102+
std::chrono::zoned_time zt{std::string_view{"UTC"}};
103+
static_assert(
104+
std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>);
105+
}
106+
}
107+
{ // TimeZonePtr
108+
{
109+
std::chrono::zoned_time zt{static_cast<const std::chrono::time_zone*>(nullptr)};
110+
static_assert(
111+
std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>);
112+
}
113+
{
114+
std::chrono::zoned_time zt{offset_time_zone<offset_time_zone_flags::none>{}};
115+
static_assert(std::same_as<
116+
decltype(zt),
117+
std::chrono::zoned_time<std::chrono::seconds, offset_time_zone<offset_time_zone_flags::none>>>);
118+
}
119+
{
120+
std::chrono::zoned_time zt{offset_time_zone<offset_time_zone_flags::has_default_zone>{}};
121+
static_assert(
122+
std::same_as<decltype(zt),
123+
std::chrono::zoned_time<std::chrono::seconds,
124+
offset_time_zone<offset_time_zone_flags::has_default_zone>>>);
125+
}
126+
{
127+
std::chrono::zoned_time zt{offset_time_zone<offset_time_zone_flags::has_locate_zone>{}};
128+
static_assert(std::same_as<decltype(zt),
129+
std::chrono::zoned_time<std::chrono::seconds,
130+
offset_time_zone<offset_time_zone_flags::has_locate_zone>>>);
131+
}
132+
{
133+
std::chrono::zoned_time zt{offset_time_zone<offset_time_zone_flags::both>{}};
134+
static_assert(std::same_as<
135+
decltype(zt),
136+
std::chrono::zoned_time<std::chrono::seconds, offset_time_zone<offset_time_zone_flags::both>>>);
137+
}
138+
139+
// There are no requirements on the TimeZonePtr type.
140+
{
141+
std::chrono::zoned_time zt{0};
142+
static_assert(std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, int>>);
143+
}
144+
{
145+
std::chrono::zoned_time zt{0.0};
146+
static_assert(std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, double>>);
147+
}
148+
{
149+
std::chrono::zoned_time zt{std::chrono::seconds{}};
150+
static_assert(std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, std::chrono::seconds>>);
151+
}
152+
}
153+
}
154+
155+
{
156+
// template<class TimeZonePtrOrName, class Duration>
157+
// zoned_time(TimeZonePtrOrName&&, sys_time<Duration>)
158+
// -> zoned_time<common_type_t<Duration, seconds>,
159+
// time-zone-representation<TimeZonePtrOrName>>;
160+
{ // Name
161+
{
162+
std::chrono::zoned_time zt{"UTC", std::chrono::sys_time<std::chrono::nanoseconds>{}};
163+
static_assert(std::same_as<decltype(zt),
164+
std::chrono::zoned_time<std::chrono::nanoseconds, const std::chrono::time_zone*>>);
165+
}
166+
{
167+
std::chrono::zoned_time zt{"UTC", std::chrono::sys_time<std::chrono::days>{}};
168+
static_assert(
169+
std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>);
170+
}
171+
}
172+
173+
{ // TimeZonePtr
174+
{
175+
std::chrono::zoned_time zt{
176+
static_cast<const std::chrono::time_zone*>(nullptr), std::chrono::sys_time<std::chrono::nanoseconds>{}};
177+
static_assert(std::same_as<decltype(zt),
178+
std::chrono::zoned_time<std::chrono::nanoseconds, const std::chrono::time_zone*>>);
179+
}
180+
{
181+
std::chrono::zoned_time zt{
182+
static_cast<const std::chrono::time_zone*>(nullptr), std::chrono::sys_time<std::chrono::days>{}};
183+
static_assert(
184+
std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>);
185+
}
186+
{
187+
std::chrono::zoned_time zt{
188+
offset_time_zone<offset_time_zone_flags::none>{}, std::chrono::sys_time<std::chrono::nanoseconds>{}};
189+
static_assert(
190+
std::same_as<
191+
decltype(zt),
192+
std::chrono::zoned_time<std::chrono::nanoseconds, offset_time_zone<offset_time_zone_flags::none>>>);
193+
}
194+
{
195+
std::chrono::zoned_time zt{
196+
offset_time_zone<offset_time_zone_flags::none>{}, std::chrono::sys_time<std::chrono::days>{}};
197+
static_assert(std::same_as<
198+
decltype(zt),
199+
std::chrono::zoned_time<std::chrono::seconds, offset_time_zone<offset_time_zone_flags::none>>>);
200+
}
201+
}
202+
}
203+
204+
{
205+
// template<class TimeZonePtrOrName, class Duration>
206+
// zoned_time(TimeZonePtrOrName&&, local_time<Duration>,
207+
// choose = choose::earliest)
208+
// -> zoned_time<common_type_t<Duration, seconds>,
209+
// time-zone-representation<TimeZonePtrOrName>>;
210+
{ // Name
211+
{
212+
std::chrono::zoned_time zt{"UTC", std::chrono::local_time<std::chrono::nanoseconds>{}};
213+
static_assert(std::same_as<decltype(zt),
214+
std::chrono::zoned_time<std::chrono::nanoseconds, const std::chrono::time_zone*>>);
215+
}
216+
{
217+
std::chrono::zoned_time zt{"UTC", std::chrono::local_time<std::chrono::days>{}, std::chrono::choose::earliest};
218+
static_assert(
219+
std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>);
220+
}
221+
}
222+
{ // TimeZonePtr
223+
{
224+
std::chrono::zoned_time zt{
225+
std::chrono::locate_zone("UTC"), std::chrono::local_time<std::chrono::nanoseconds>{}};
226+
static_assert(std::same_as<decltype(zt),
227+
std::chrono::zoned_time<std::chrono::nanoseconds, const std::chrono::time_zone*>>);
228+
}
229+
{
230+
std::chrono::zoned_time zt{
231+
std::chrono::locate_zone("UTC"),
232+
std::chrono::local_time<std::chrono::days>{},
233+
std::chrono::choose::earliest};
234+
static_assert(
235+
std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>);
236+
}
237+
}
238+
}
239+
240+
{
241+
// template<class Duration, class TimeZonePtrOrName, class TimeZonePtr2>
242+
// zoned_time(TimeZonePtrOrName&&, zoned_time<Duration, TimeZonePtr2>,
243+
// choose = choose::earliest)
244+
// -> zoned_time<common_type_t<Duration, seconds>,
245+
// time-zone-representation<TimeZonePtrOrName>>;
246+
{ // Name
247+
{
248+
std::chrono::zoned_time zt{
249+
"UTC",
250+
std::chrono::zoned_time<std::chrono::nanoseconds,
251+
offset_time_zone<offset_time_zone_flags::has_default_zone>>{}};
252+
static_assert(std::same_as<decltype(zt),
253+
std::chrono::zoned_time<std::chrono::nanoseconds, const std::chrono::time_zone*>>);
254+
}
255+
{
256+
std::chrono::zoned_time zt{
257+
"UTC",
258+
std::chrono::zoned_time<std::chrono::days, offset_time_zone<offset_time_zone_flags::has_default_zone>>{},
259+
std::chrono::choose::earliest};
260+
static_assert(
261+
std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>);
262+
}
263+
}
264+
{ // TimeZonePtr
265+
{
266+
std::chrono::zoned_time zt{
267+
std::chrono::locate_zone("UTC"),
268+
std::chrono::zoned_time<std::chrono::nanoseconds,
269+
offset_time_zone<offset_time_zone_flags::has_default_zone>>{}};
270+
static_assert(std::same_as<decltype(zt),
271+
std::chrono::zoned_time<std::chrono::nanoseconds, const std::chrono::time_zone*>>);
272+
}
273+
{
274+
std::chrono::zoned_time zt{
275+
std::chrono::locate_zone("UTC"),
276+
std::chrono::zoned_time<std::chrono::days, offset_time_zone<offset_time_zone_flags::has_default_zone>>{},
277+
std::chrono::choose::earliest};
278+
static_assert(
279+
std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>);
280+
}
281+
}
282+
}
283+
284+
return 0;
285+
}

0 commit comments

Comments
 (0)