xref: /llvm-project/libcxx/include/__chrono/parser_std_format_spec.h (revision f69585235ec85d54e0f3fc41b2d5700430907f99)
1e5d2d3eaSMark de Wever // -*- C++ -*-
2e5d2d3eaSMark de Wever //===----------------------------------------------------------------------===//
3e5d2d3eaSMark de Wever //
4e5d2d3eaSMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5e5d2d3eaSMark de Wever // See https://llvm.org/LICENSE.txt for license information.
6e5d2d3eaSMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7e5d2d3eaSMark de Wever //
8e5d2d3eaSMark de Wever //===----------------------------------------------------------------------===//
9e5d2d3eaSMark de Wever 
10e5d2d3eaSMark de Wever #ifndef _LIBCPP___CHRONO_PARSER_STD_FORMAT_SPEC_H
11e5d2d3eaSMark de Wever #define _LIBCPP___CHRONO_PARSER_STD_FORMAT_SPEC_H
12e5d2d3eaSMark de Wever 
13e5d2d3eaSMark de Wever #include <__config>
1487d56c59SLouis Dionne 
15c6f3b7bcSNikolas Klauser #if _LIBCPP_HAS_LOCALIZATION
1687d56c59SLouis Dionne 
17e5d2d3eaSMark de Wever #  include <__format/concepts.h>
18e5d2d3eaSMark de Wever #  include <__format/format_error.h>
19e5d2d3eaSMark de Wever #  include <__format/format_parse_context.h>
20e5d2d3eaSMark de Wever #  include <__format/formatter_string.h>
21e5d2d3eaSMark de Wever #  include <__format/parser_std_format_spec.h>
22e5d2d3eaSMark de Wever #  include <string_view>
23e5d2d3eaSMark de Wever 
24e5d2d3eaSMark de Wever #  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
25e5d2d3eaSMark de Wever #    pragma GCC system_header
26e5d2d3eaSMark de Wever #  endif
27e5d2d3eaSMark de Wever 
28e5d2d3eaSMark de Wever _LIBCPP_BEGIN_NAMESPACE_STD
29e5d2d3eaSMark de Wever 
30dff62f52SMark de Wever #  if _LIBCPP_STD_VER >= 20
31e5d2d3eaSMark de Wever 
32e5d2d3eaSMark de Wever namespace __format_spec {
33e5d2d3eaSMark de Wever 
34e5d2d3eaSMark de Wever // By not placing this constant in the formatter class it's not duplicated for char and wchar_t
35719c3dc6SMark de Wever inline constexpr __fields __fields_chrono_fractional{
36719c3dc6SMark de Wever     .__precision_ = true, .__locale_specific_form_ = true, .__type_ = false};
37e5d2d3eaSMark de Wever inline constexpr __fields __fields_chrono{.__locale_specific_form_ = true, .__type_ = false};
38e5d2d3eaSMark de Wever 
39e5d2d3eaSMark de Wever /// Flags available or required in a chrono type.
40e5d2d3eaSMark de Wever ///
41e5d2d3eaSMark de Wever /// The caller of the chrono formatter lists the types it has available and the
42e5d2d3eaSMark de Wever /// validation tests whether the requested type spec (e.g. %M) is available in
43e5d2d3eaSMark de Wever /// the formatter.
44e5d2d3eaSMark de Wever /// When the type in the chrono-format-spec isn't present in the data a
45e5d2d3eaSMark de Wever /// \ref format_error is thrown.
46e5d2d3eaSMark de Wever enum class __flags {
47e5d2d3eaSMark de Wever   __second = 0x1,
48e5d2d3eaSMark de Wever   __minute = 0x2,
49e5d2d3eaSMark de Wever   __hour   = 0x4,
50e5d2d3eaSMark de Wever   __time   = __hour | __minute | __second,
51e5d2d3eaSMark de Wever 
52e5d2d3eaSMark de Wever   __day   = 0x8,
53e5d2d3eaSMark de Wever   __month = 0x10,
54e5d2d3eaSMark de Wever   __year  = 0x20,
55e5d2d3eaSMark de Wever 
56e5d2d3eaSMark de Wever   __weekday = 0x40,
57e5d2d3eaSMark de Wever 
58e5d2d3eaSMark de Wever   __month_day     = __day | __month,
59e5d2d3eaSMark de Wever   __month_weekday = __weekday | __month,
60e5d2d3eaSMark de Wever   __year_month    = __month | __year,
61e5d2d3eaSMark de Wever   __date          = __day | __month | __year | __weekday,
62e5d2d3eaSMark de Wever 
63e5d2d3eaSMark de Wever   __date_time = __date | __time,
64e5d2d3eaSMark de Wever 
65e5d2d3eaSMark de Wever   __duration = 0x80 | __time,
66e5d2d3eaSMark de Wever 
67e5d2d3eaSMark de Wever   __time_zone = 0x100,
68e5d2d3eaSMark de Wever 
69e5d2d3eaSMark de Wever   __clock = __date_time | __time_zone
70e5d2d3eaSMark de Wever };
71e5d2d3eaSMark de Wever 
72e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr __flags operator&(__flags __lhs, __flags __rhs) {
73e5d2d3eaSMark de Wever   return static_cast<__flags>(static_cast<unsigned>(__lhs) & static_cast<unsigned>(__rhs));
74e5d2d3eaSMark de Wever }
75e5d2d3eaSMark de Wever 
76e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_second(__flags __flags) {
77e5d2d3eaSMark de Wever   if ((__flags & __flags::__second) != __flags::__second)
78e5d2d3eaSMark de Wever     std::__throw_format_error("The supplied date time doesn't contain a second");
79e5d2d3eaSMark de Wever }
80e5d2d3eaSMark de Wever 
81e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_minute(__flags __flags) {
82e5d2d3eaSMark de Wever   if ((__flags & __flags::__minute) != __flags::__minute)
83e5d2d3eaSMark de Wever     std::__throw_format_error("The supplied date time doesn't contain a minute");
84e5d2d3eaSMark de Wever }
85e5d2d3eaSMark de Wever 
86e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_hour(__flags __flags) {
87e5d2d3eaSMark de Wever   if ((__flags & __flags::__hour) != __flags::__hour)
88e5d2d3eaSMark de Wever     std::__throw_format_error("The supplied date time doesn't contain an hour");
89e5d2d3eaSMark de Wever }
90e5d2d3eaSMark de Wever 
91e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_time(__flags __flags) {
92e5d2d3eaSMark de Wever   if ((__flags & __flags::__time) != __flags::__time)
93e5d2d3eaSMark de Wever     std::__throw_format_error("The supplied date time doesn't contain a time");
94e5d2d3eaSMark de Wever }
95e5d2d3eaSMark de Wever 
96e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_day(__flags __flags) {
97e5d2d3eaSMark de Wever   if ((__flags & __flags::__day) != __flags::__day)
98e5d2d3eaSMark de Wever     std::__throw_format_error("The supplied date time doesn't contain a day");
99e5d2d3eaSMark de Wever }
100e5d2d3eaSMark de Wever 
101e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_month(__flags __flags) {
102e5d2d3eaSMark de Wever   if ((__flags & __flags::__month) != __flags::__month)
103e5d2d3eaSMark de Wever     std::__throw_format_error("The supplied date time doesn't contain a month");
104e5d2d3eaSMark de Wever }
105e5d2d3eaSMark de Wever 
106e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_year(__flags __flags) {
107e5d2d3eaSMark de Wever   if ((__flags & __flags::__year) != __flags::__year)
108e5d2d3eaSMark de Wever     std::__throw_format_error("The supplied date time doesn't contain a year");
109e5d2d3eaSMark de Wever }
110e5d2d3eaSMark de Wever 
111e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_date(__flags __flags) {
112e5d2d3eaSMark de Wever   if ((__flags & __flags::__date) != __flags::__date)
113e5d2d3eaSMark de Wever     std::__throw_format_error("The supplied date time doesn't contain a date");
114e5d2d3eaSMark de Wever }
115e5d2d3eaSMark de Wever 
116e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_date_or_duration(__flags __flags) {
117e5d2d3eaSMark de Wever   if (((__flags & __flags::__date) != __flags::__date) && ((__flags & __flags::__duration) != __flags::__duration))
118e5d2d3eaSMark de Wever     std::__throw_format_error("The supplied date time doesn't contain a date or duration");
119e5d2d3eaSMark de Wever }
120e5d2d3eaSMark de Wever 
121e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_date_time(__flags __flags) {
122e5d2d3eaSMark de Wever   if ((__flags & __flags::__date_time) != __flags::__date_time)
123e5d2d3eaSMark de Wever     std::__throw_format_error("The supplied date time doesn't contain a date and time");
124e5d2d3eaSMark de Wever }
125e5d2d3eaSMark de Wever 
126e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_weekday(__flags __flags) {
127e5d2d3eaSMark de Wever   if ((__flags & __flags::__weekday) != __flags::__weekday)
128e5d2d3eaSMark de Wever     std::__throw_format_error("The supplied date time doesn't contain a weekday");
129e5d2d3eaSMark de Wever }
130e5d2d3eaSMark de Wever 
131e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_duration(__flags __flags) {
132e5d2d3eaSMark de Wever   if ((__flags & __flags::__duration) != __flags::__duration)
133e5d2d3eaSMark de Wever     std::__throw_format_error("The supplied date time doesn't contain a duration");
134e5d2d3eaSMark de Wever }
135e5d2d3eaSMark de Wever 
136e5d2d3eaSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __validate_time_zone(__flags __flags) {
137e5d2d3eaSMark de Wever   if ((__flags & __flags::__time_zone) != __flags::__time_zone)
138e5d2d3eaSMark de Wever     std::__throw_format_error("The supplied date time doesn't contain a time zone");
139e5d2d3eaSMark de Wever }
140e5d2d3eaSMark de Wever 
141e5d2d3eaSMark de Wever template <class _CharT>
142e5d2d3eaSMark de Wever class _LIBCPP_TEMPLATE_VIS __parser_chrono {
143*f6958523SNikolas Klauser   using _ConstIterator _LIBCPP_NODEBUG = typename basic_format_parse_context<_CharT>::const_iterator;
144a845b5b4SLouis Dionne 
145e5d2d3eaSMark de Wever public:
146b51e8acdSMark de Wever   template <class _ParseContext>
147b51e8acdSMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator
148b51e8acdSMark de Wever   __parse(_ParseContext& __ctx, __fields __fields, __flags __flags) {
149b51e8acdSMark de Wever     _ConstIterator __begin = __parser_.__parse(__ctx, __fields);
150b51e8acdSMark de Wever     _ConstIterator __end   = __ctx.end();
151e5d2d3eaSMark de Wever     if (__begin == __end)
152e5d2d3eaSMark de Wever       return __begin;
153e5d2d3eaSMark de Wever 
154a845b5b4SLouis Dionne     _ConstIterator __last = __parse_chrono_specs(__begin, __end, __flags);
155e5d2d3eaSMark de Wever     __chrono_specs_       = basic_string_view<_CharT>{__begin, __last};
156e5d2d3eaSMark de Wever 
157e5d2d3eaSMark de Wever     return __last;
158e5d2d3eaSMark de Wever   }
159e5d2d3eaSMark de Wever 
160e5d2d3eaSMark de Wever   __parser<_CharT> __parser_;
161e5d2d3eaSMark de Wever   basic_string_view<_CharT> __chrono_specs_;
162e5d2d3eaSMark de Wever 
163e5d2d3eaSMark de Wever private:
164a845b5b4SLouis Dionne   _LIBCPP_HIDE_FROM_ABI constexpr _ConstIterator
165a845b5b4SLouis Dionne   __parse_chrono_specs(_ConstIterator __begin, _ConstIterator __end, __flags __flags) {
1664f215fddSKonstantin Varlamov     _LIBCPP_ASSERT_INTERNAL(__begin != __end,
167e5d2d3eaSMark de Wever                             "When called with an empty input the function will cause "
168e5d2d3eaSMark de Wever                             "undefined behavior by evaluating data not in the input");
169e5d2d3eaSMark de Wever 
170e5d2d3eaSMark de Wever     if (*__begin != _CharT('%') && *__begin != _CharT('}'))
171402eb2efSMark de Wever       std::__throw_format_error("The format specifier expects a '%' or a '}'");
172e5d2d3eaSMark de Wever 
173e5d2d3eaSMark de Wever     do {
174e5d2d3eaSMark de Wever       switch (*__begin) {
175e5d2d3eaSMark de Wever       case _CharT('{'):
176402eb2efSMark de Wever         std::__throw_format_error("The chrono specifiers contain a '{'");
177e5d2d3eaSMark de Wever 
178e5d2d3eaSMark de Wever       case _CharT('}'):
179e5d2d3eaSMark de Wever         return __begin;
180e5d2d3eaSMark de Wever 
181e5d2d3eaSMark de Wever       case _CharT('%'):
182e5d2d3eaSMark de Wever         __parse_conversion_spec(__begin, __end, __flags);
183e5d2d3eaSMark de Wever         [[fallthrough]];
184e5d2d3eaSMark de Wever 
185e5d2d3eaSMark de Wever       default:
186e5d2d3eaSMark de Wever         // All other literals
187e5d2d3eaSMark de Wever         ++__begin;
188e5d2d3eaSMark de Wever       }
189e5d2d3eaSMark de Wever 
190e5d2d3eaSMark de Wever     } while (__begin != __end && *__begin != _CharT('}'));
191e5d2d3eaSMark de Wever 
192e5d2d3eaSMark de Wever     return __begin;
193e5d2d3eaSMark de Wever   }
194e5d2d3eaSMark de Wever 
195e5d2d3eaSMark de Wever   /// \pre *__begin == '%'
196e5d2d3eaSMark de Wever   /// \post __begin points at the end parsed conversion-spec
197e5d2d3eaSMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr void
198a845b5b4SLouis Dionne   __parse_conversion_spec(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) {
199e5d2d3eaSMark de Wever     ++__begin;
200e5d2d3eaSMark de Wever     if (__begin == __end)
201402eb2efSMark de Wever       std::__throw_format_error("End of input while parsing a conversion specifier");
202e5d2d3eaSMark de Wever 
203e5d2d3eaSMark de Wever     switch (*__begin) {
204e5d2d3eaSMark de Wever     case _CharT('n'):
205e5d2d3eaSMark de Wever     case _CharT('t'):
206e5d2d3eaSMark de Wever     case _CharT('%'):
207e5d2d3eaSMark de Wever       break;
208e5d2d3eaSMark de Wever 
209e5d2d3eaSMark de Wever     case _CharT('S'):
210e5d2d3eaSMark de Wever       __format_spec::__validate_second(__flags);
211e5d2d3eaSMark de Wever       break;
212e5d2d3eaSMark de Wever 
213e5d2d3eaSMark de Wever     case _CharT('M'):
214e5d2d3eaSMark de Wever       __format_spec::__validate_minute(__flags);
215e5d2d3eaSMark de Wever       break;
216e5d2d3eaSMark de Wever 
217e5d2d3eaSMark de Wever     case _CharT('p'): // TODO FMT does the formater require an hour or a time?
218e5d2d3eaSMark de Wever     case _CharT('H'):
219e5d2d3eaSMark de Wever     case _CharT('I'):
2207f5d130aSMark de Wever       __parser_.__hour_ = true;
221e5d2d3eaSMark de Wever       __validate_hour(__flags);
222e5d2d3eaSMark de Wever       break;
223e5d2d3eaSMark de Wever 
224e5d2d3eaSMark de Wever     case _CharT('r'):
225e5d2d3eaSMark de Wever     case _CharT('R'):
226e5d2d3eaSMark de Wever     case _CharT('T'):
227e5d2d3eaSMark de Wever     case _CharT('X'):
2287f5d130aSMark de Wever       __parser_.__hour_ = true;
229e5d2d3eaSMark de Wever       __format_spec::__validate_time(__flags);
230e5d2d3eaSMark de Wever       break;
231e5d2d3eaSMark de Wever 
232e5d2d3eaSMark de Wever     case _CharT('d'):
233e5d2d3eaSMark de Wever     case _CharT('e'):
234e5d2d3eaSMark de Wever       __format_spec::__validate_day(__flags);
235e5d2d3eaSMark de Wever       break;
236e5d2d3eaSMark de Wever 
237e5d2d3eaSMark de Wever     case _CharT('b'):
238e5d2d3eaSMark de Wever     case _CharT('h'):
239e5d2d3eaSMark de Wever     case _CharT('B'):
240e5d2d3eaSMark de Wever       __parser_.__month_name_ = true;
241e5d2d3eaSMark de Wever       [[fallthrough]];
242e5d2d3eaSMark de Wever     case _CharT('m'):
243e5d2d3eaSMark de Wever       __format_spec::__validate_month(__flags);
244e5d2d3eaSMark de Wever       break;
245e5d2d3eaSMark de Wever 
246e5d2d3eaSMark de Wever     case _CharT('y'):
247e5d2d3eaSMark de Wever     case _CharT('C'):
248e5d2d3eaSMark de Wever     case _CharT('Y'):
249e5d2d3eaSMark de Wever       __format_spec::__validate_year(__flags);
250e5d2d3eaSMark de Wever       break;
251e5d2d3eaSMark de Wever 
252e5d2d3eaSMark de Wever     case _CharT('j'):
253105fef5dSMark de Wever       __parser_.__day_of_year_ = true;
254e5d2d3eaSMark de Wever       __format_spec::__validate_date_or_duration(__flags);
255e5d2d3eaSMark de Wever       break;
256e5d2d3eaSMark de Wever 
257e5d2d3eaSMark de Wever     case _CharT('g'):
258e5d2d3eaSMark de Wever     case _CharT('G'):
259e5d2d3eaSMark de Wever     case _CharT('U'):
260e5d2d3eaSMark de Wever     case _CharT('V'):
261e5d2d3eaSMark de Wever     case _CharT('W'):
262105fef5dSMark de Wever       __parser_.__week_of_year_ = true;
263105fef5dSMark de Wever       [[fallthrough]];
264105fef5dSMark de Wever     case _CharT('x'):
265105fef5dSMark de Wever     case _CharT('D'):
266105fef5dSMark de Wever     case _CharT('F'):
267e5d2d3eaSMark de Wever       __format_spec::__validate_date(__flags);
268e5d2d3eaSMark de Wever       break;
269e5d2d3eaSMark de Wever 
270e5d2d3eaSMark de Wever     case _CharT('c'):
271e5d2d3eaSMark de Wever       __format_spec::__validate_date_time(__flags);
272e5d2d3eaSMark de Wever       break;
273e5d2d3eaSMark de Wever 
274e5d2d3eaSMark de Wever     case _CharT('a'):
275e5d2d3eaSMark de Wever     case _CharT('A'):
276e5d2d3eaSMark de Wever       __parser_.__weekday_name_ = true;
277e5d2d3eaSMark de Wever       [[fallthrough]];
278e5d2d3eaSMark de Wever     case _CharT('u'):
279e5d2d3eaSMark de Wever     case _CharT('w'):
280105fef5dSMark de Wever       __parser_.__weekday_ = true;
281105fef5dSMark de Wever       __validate_weekday(__flags);
282e5d2d3eaSMark de Wever       __format_spec::__validate_weekday(__flags);
283e5d2d3eaSMark de Wever       break;
284e5d2d3eaSMark de Wever 
285e5d2d3eaSMark de Wever     case _CharT('q'):
286e5d2d3eaSMark de Wever     case _CharT('Q'):
287e5d2d3eaSMark de Wever       __format_spec::__validate_duration(__flags);
288e5d2d3eaSMark de Wever       break;
289e5d2d3eaSMark de Wever 
290e5d2d3eaSMark de Wever     case _CharT('E'):
291e5d2d3eaSMark de Wever       __parse_modifier_E(__begin, __end, __flags);
292e5d2d3eaSMark de Wever       break;
293e5d2d3eaSMark de Wever 
294e5d2d3eaSMark de Wever     case _CharT('O'):
295e5d2d3eaSMark de Wever       __parse_modifier_O(__begin, __end, __flags);
296e5d2d3eaSMark de Wever       break;
297e5d2d3eaSMark de Wever 
298e5d2d3eaSMark de Wever     case _CharT('z'):
299e5d2d3eaSMark de Wever     case _CharT('Z'):
300e5d2d3eaSMark de Wever       // Currently there's no time zone information. However some clocks have a
301e5d2d3eaSMark de Wever       // hard-coded "time zone", for these clocks the information can be used.
302e5d2d3eaSMark de Wever       // TODO FMT implement time zones.
303e5d2d3eaSMark de Wever       __format_spec::__validate_time_zone(__flags);
304e5d2d3eaSMark de Wever       break;
305e5d2d3eaSMark de Wever 
306e5d2d3eaSMark de Wever     default: // unknown type;
307e5d2d3eaSMark de Wever       std::__throw_format_error("The date time type specifier is invalid");
308e5d2d3eaSMark de Wever     }
309e5d2d3eaSMark de Wever   }
310e5d2d3eaSMark de Wever 
311e5d2d3eaSMark de Wever   /// \pre *__begin == 'E'
312e5d2d3eaSMark de Wever   /// \post __begin is incremented by one.
313e5d2d3eaSMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr void
314a845b5b4SLouis Dionne   __parse_modifier_E(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) {
315e5d2d3eaSMark de Wever     ++__begin;
316e5d2d3eaSMark de Wever     if (__begin == __end)
317e5d2d3eaSMark de Wever       std::__throw_format_error("End of input while parsing the modifier E");
318e5d2d3eaSMark de Wever 
319e5d2d3eaSMark de Wever     switch (*__begin) {
320e5d2d3eaSMark de Wever     case _CharT('X'):
3217f5d130aSMark de Wever       __parser_.__hour_ = true;
322e5d2d3eaSMark de Wever       __format_spec::__validate_time(__flags);
323e5d2d3eaSMark de Wever       break;
324e5d2d3eaSMark de Wever 
325e5d2d3eaSMark de Wever     case _CharT('y'):
326e5d2d3eaSMark de Wever     case _CharT('C'):
327e5d2d3eaSMark de Wever     case _CharT('Y'):
328e5d2d3eaSMark de Wever       __format_spec::__validate_year(__flags);
329e5d2d3eaSMark de Wever       break;
330e5d2d3eaSMark de Wever 
331e5d2d3eaSMark de Wever     case _CharT('x'):
332e5d2d3eaSMark de Wever       __format_spec::__validate_date(__flags);
333e5d2d3eaSMark de Wever       break;
334e5d2d3eaSMark de Wever 
335e5d2d3eaSMark de Wever     case _CharT('c'):
336e5d2d3eaSMark de Wever       __format_spec::__validate_date_time(__flags);
337e5d2d3eaSMark de Wever       break;
338e5d2d3eaSMark de Wever 
339e5d2d3eaSMark de Wever     case _CharT('z'):
340e5d2d3eaSMark de Wever       // Currently there's no time zone information. However some clocks have a
341e5d2d3eaSMark de Wever       // hard-coded "time zone", for these clocks the information can be used.
342e5d2d3eaSMark de Wever       // TODO FMT implement time zones.
343e5d2d3eaSMark de Wever       __format_spec::__validate_time_zone(__flags);
344e5d2d3eaSMark de Wever       break;
345e5d2d3eaSMark de Wever 
346e5d2d3eaSMark de Wever     default:
347e5d2d3eaSMark de Wever       std::__throw_format_error("The date time type specifier for modifier E is invalid");
348e5d2d3eaSMark de Wever     }
349e5d2d3eaSMark de Wever   }
350e5d2d3eaSMark de Wever 
351e5d2d3eaSMark de Wever   /// \pre *__begin == 'O'
352e5d2d3eaSMark de Wever   /// \post __begin is incremented by one.
353e5d2d3eaSMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr void
354a845b5b4SLouis Dionne   __parse_modifier_O(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) {
355e5d2d3eaSMark de Wever     ++__begin;
356e5d2d3eaSMark de Wever     if (__begin == __end)
357e5d2d3eaSMark de Wever       std::__throw_format_error("End of input while parsing the modifier O");
358e5d2d3eaSMark de Wever 
359e5d2d3eaSMark de Wever     switch (*__begin) {
360e5d2d3eaSMark de Wever     case _CharT('S'):
361e5d2d3eaSMark de Wever       __format_spec::__validate_second(__flags);
362e5d2d3eaSMark de Wever       break;
363e5d2d3eaSMark de Wever 
364e5d2d3eaSMark de Wever     case _CharT('M'):
365e5d2d3eaSMark de Wever       __format_spec::__validate_minute(__flags);
366e5d2d3eaSMark de Wever       break;
367e5d2d3eaSMark de Wever 
368e5d2d3eaSMark de Wever     case _CharT('I'):
369e5d2d3eaSMark de Wever     case _CharT('H'):
3707f5d130aSMark de Wever       __parser_.__hour_ = true;
371e5d2d3eaSMark de Wever       __format_spec::__validate_hour(__flags);
372e5d2d3eaSMark de Wever       break;
373e5d2d3eaSMark de Wever 
374e5d2d3eaSMark de Wever     case _CharT('d'):
375e5d2d3eaSMark de Wever     case _CharT('e'):
376e5d2d3eaSMark de Wever       __format_spec::__validate_day(__flags);
377e5d2d3eaSMark de Wever       break;
378e5d2d3eaSMark de Wever 
379e5d2d3eaSMark de Wever     case _CharT('m'):
380e5d2d3eaSMark de Wever       __format_spec::__validate_month(__flags);
381e5d2d3eaSMark de Wever       break;
382e5d2d3eaSMark de Wever 
383e5d2d3eaSMark de Wever     case _CharT('y'):
384e5d2d3eaSMark de Wever       __format_spec::__validate_year(__flags);
385e5d2d3eaSMark de Wever       break;
386e5d2d3eaSMark de Wever 
387e5d2d3eaSMark de Wever     case _CharT('U'):
388e5d2d3eaSMark de Wever     case _CharT('V'):
389e5d2d3eaSMark de Wever     case _CharT('W'):
390105fef5dSMark de Wever       __parser_.__week_of_year_ = true;
391e5d2d3eaSMark de Wever       __format_spec::__validate_date(__flags);
392e5d2d3eaSMark de Wever       break;
393e5d2d3eaSMark de Wever 
394e5d2d3eaSMark de Wever     case _CharT('u'):
395e5d2d3eaSMark de Wever     case _CharT('w'):
396105fef5dSMark de Wever       __parser_.__weekday_ = true;
397e5d2d3eaSMark de Wever       __format_spec::__validate_weekday(__flags);
398e5d2d3eaSMark de Wever       break;
399e5d2d3eaSMark de Wever 
400e5d2d3eaSMark de Wever     case _CharT('z'):
401e5d2d3eaSMark de Wever       // Currently there's no time zone information. However some clocks have a
402e5d2d3eaSMark de Wever       // hard-coded "time zone", for these clocks the information can be used.
403e5d2d3eaSMark de Wever       // TODO FMT implement time zones.
404e5d2d3eaSMark de Wever       __format_spec::__validate_time_zone(__flags);
405e5d2d3eaSMark de Wever       break;
406e5d2d3eaSMark de Wever 
407e5d2d3eaSMark de Wever     default:
408e5d2d3eaSMark de Wever       std::__throw_format_error("The date time type specifier for modifier O is invalid");
409e5d2d3eaSMark de Wever     }
410e5d2d3eaSMark de Wever   }
411e5d2d3eaSMark de Wever };
412e5d2d3eaSMark de Wever 
413e5d2d3eaSMark de Wever } // namespace __format_spec
414e5d2d3eaSMark de Wever 
415dff62f52SMark de Wever #  endif // _LIBCPP_STD_VER >= 20
416e5d2d3eaSMark de Wever 
417e5d2d3eaSMark de Wever _LIBCPP_END_NAMESPACE_STD
418e5d2d3eaSMark de Wever 
419c6f3b7bcSNikolas Klauser #endif // _LIBCPP_HAS_LOCALIZATION
42087d56c59SLouis Dionne 
421e5d2d3eaSMark de Wever #endif // _LIBCPP___CHRONO_PARSER_STD_FORMAT_SPEC_H
422