Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qttemporalpattern.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4#include "private/qttemporalpattern_p.h"
5
6#include "private/qlocale_p.h"
7#include "private/qtparseqttemporalformat_p.h"
8#if QT_CONFIG(datetimeparser)
9# include "private/qtparsetemporal_p.h"
10#endif
11
12#include <bitset>
13
14QT_BEGIN_NAMESPACE
15
17/*!
18 \internal
19 \since 6.12
20 \namespace QtTemporalPattern
21 \brief Supporting types and functions for temporal patterns.
22
23 Temporal patterns describe how a date, time or datetime may be serialized as
24 text or parsed from text. This namespace provides the common tools used by
25 the classes describing such patterns: \l QDateTimePattern, \l QTimePattern
26 and \l QDatePattern.
27*/
28
29/* Note (QTBUG-70516): For now (Qt 6.12) it suffices to cover everything that
30 the existing Qt datetime format strings are capable of. However, the intent
31 is to eventually expand this to fully support CLDR's datetime formats so that
32 we can switch from converting those to Qt formats when we scan CLDR to
33 actually storing the CLDR format in the qlocale_data_p.h tables and
34 constructing our Q(Date|Time)+Pattern objects from those formats. See comment
35 in header for a link to the relevant parts of LDML.
36*/
37
38/*!
39 \enum QtTemporalPattern::TemporalFieldCategory
40
41 This enumeration characterizes the information supplied by a field.
42
43 For the details of how that information is conveyed, see \l
44 {QtTemporalPattern::}{TemporalFieldFlag}. For the classification of fields
45 by whether they specify date, time or zone, see \l
46 {QtTemporalPattern::}{DateTimePart}.
47
48 \value Literal Describes a text fragment that frames the data, such as
49 separators and delimiters.
50 \value TimeZone Identifies the timezone or offset from UTC of a datetime.
51 \value SecondFraction The fraction of a second (an optional time field).
52 \value Second The second within the minute (an optional time field).
53 \value Minute The minute within the hour (a time field).
54 \value PeriodInDay A subdivision of the day, such as before noon vs after
55 noon (a time field). May serve to disambiguate the hour
56 when specified only modulo 12. (Currently only the am/pm
57 distinction is supported.)
58 \value HourMod12 The hour in the range 1 through 12 (a time field). May be
59 ambiguous on its own.
60 \value Hour The hour in the range from 0 through 23 (a time field).
61
62 \value DayOfWeek The day within the week (a date field). Usually specified
63 by name. Some locales may use numbers for their Narrow
64 Verbal and/or Standalone forms. No form is supported for
65 Numeric | DayOfWeek.
66 \value DayOfMonth The day number within the month (a date field). Runs from
67 1 for the first day of the month up to the length of the
68 month. Always numeric, regardless of field flags.
69
70 \value Month The month within the year (a date field). When specified
71 numerically, the first month of the year is numbered 1; there
72 is no month 0. Some locales may use numbers for their Narrow
73 Verbal form.
74
75 \value YearWithinCentury The two-digit year number (a date field). Widely
76 used in date formats, despite its potential for
77 ambiguity. May be disambiguated by other fields or
78 by specifying base year for the hundred years
79 presumed when only two digits are given and other
80 fields don't disambiguate.
81 \value Year The full year number (a date field).
82
83 Fields identified as numbers, along with hour, minute, second and fraction
84 of second, are always given in numeric form (regardless of Numeric, Verbal
85 or Standalone flags). Where a field is given in numeric form, its field
86 width is the smallest number of digits that can match it. Further digits are
87 accepted, up to the greatest number of significant digits that can appear in
88 a valid value for it. (If the field width exceeds this, fields of this width
89 are accepted, provided the numeric value is valid. This may require
90 zero-padding.)
91
92 The SecondFraction field describes the digits immediately following the
93 fractional-part separator in a decimal representation of the seconds with
94 fractional part. It is up to the format to position it suitably in relation
95 to a Second field and a Literal field for the separator. Leading zeros are
96 significant and not considered to be padding: trailing zeros are understood
97 as padding.
98
99 As QTime and QDateTime only handle times to millisecond precision, normally
100 their allowed range of values runs from 0 to 999 and no more than three
101 digits are accepted, or the field width if greater. If the \l
102 {QtTemporalPattern::TemporalFieldFlag} {RoundFraction} flag is passed,
103 digits beyond this are accepted and will affect the result only via
104 appropriate rounding. (If fewer than three digits are parsed, the value is
105 implicitly extended on the right with zeros to obtain milliseconds
106 precision. Whether such a field is accepted will depend on the setting of
107 the \c width of the field and the absence of \l
108 {QtTemporalPattern::TemporalFieldFlag} {ZeroPad} from its \l
109 {QtTemporalPattern::TemporalField} {\c options}, in the usual ways.)
110
111 Where a SecondFraction field accepts more than three digits (either because
112 its field width exceeds three or because the RoundFraction flag is
113 specified), the resulting fractional part is rounded to three significant
114 digits. If rounding would require increasing the Second field, however, the
115 Second field is retained unchanged and the fractional part is rounded to 999
116 milliseconds. For example, 29.9997 seconds is rounded to 29.999 seconds, to
117 preserve the fact that the time is strictly before the 30 second mark.
118
119 \note For negative years, the YearWithinCentury will be understood as the
120 number of completed years since the start of the most recent year that is a
121 multiple of 100. Thus year -1 (which Qt understands, when using the
122 Gregorian calendar, to mean 1 BCE) has a YearWithinCentury value of 99,
123 since the last year that's a multiple of 100 is -100 (for Gregorian, 100
124 BCE).
125
126 \omitvalue EndCategories
127
128 \sa {QtTemporalPattern::}{TemporalFieldFlag}, {QtTemporalPattern::}{DateTimePart}
129*/
130
131/* For numbers as narrow days of the week, at least three different numberings
132 are used, all of which are used in locales whose "first day of the week" is
133 Monday. (Furthermore, some locales with digits as narrow names only do that
134 for some days, with letters for others.) So there is no way to determine how
135 days of the week are numbered from one locale to the next, except in so far
136 as their narrow Verbal or Standalone forms use digits. A Numeric version of
137 the day of the week field would thus either not know what to do for most
138 locales, be inconsistent between locales or be inconsistent, for some
139 locales, between Narrow Verbal / Standalone formats and Numeric format.
140 Hence the lack of a meaning of Numeric for DayOfWeek.
141
142 Some locales use month numbers for the narrow format of months; but none are
143 known to do so inconsistently with the usual month numbering (although Pashto
144 does this only partially, using non-numeric narrow standalone forms for the
145 first two months). This does still conflict with the numeric form of months,
146 at least in some cases, that use ASCII digits for narrow forms of month
147 numbers but locale-appropriate digits for their numeric forms. However, the
148 conflict is only in how the numbers are represented, not in the numeric
149 values used for months.
150*/
151
152/*!
153 \internal
154 \namespace QtTemporalPattern::FieldGroup
155 \brief Masks identifying mutually-exclusive families of options.
156
157 Each constant in this namespace is of type \l {QtTemporalPattern::}
158 {TemporalFieldFlags} and combines a mutually-exclusive family of \l
159 {QtTemporalPattern::} {TemporalFieldFlag} values into a mask by which to
160 identify that family. Within each such family, if none of the flags is
161 specified, any of them may be applied but if any of them are specified then
162 only one of those specified may be applied.
163
164 \value FormMask The three general forms of a field: numeric, verbal and
165 standalone.
166 \value WidthMask The four field widths: wide, short, abbreviated, and
167 narrow.
168 \value UtcPrefixMask The two options for prefixes on offset forms of
169 timezones, with and without a UTC prefix.
170 \value PaddingMask The two padding options for when fields don't fill the
171 width allotted to them: spaces and zeros.
172 \value SeasonMask The three perspectives from which to describe a timezone:
173 the generic, regardless of the time of year, the standard,
174 and how it's described when exercising daylight-saving
175 time (if it does at all).
176*/
177/* Namespace QtParseCommon has helper functions, defined in qtparsetimezone_p.h,
178 to apply the above rule related to these masks.
179*/
180
181/*!
182 \enum QtTemporalPattern::TemporalFieldFlag
183
184 This enumeration describes how datetime fields are expressed in text.
185
186 A combination of these flags is used to qualify a \l {QtTemporalPattern::}
187 {TemporalFieldCategory}, indicating whether it is conveyed by words or
188 numbers, how tersely or in which terms, depending on the field
189 category. Interpretation of a flag in this enumeration varies with the field
190 category it is qualifying and with other flags combined with it.
191
192 Some flags, such as the four width options, are mutually exclusive. For each
193 group of mutually-exclusive flags, a mask constant is defined in namespace
194 QtTemporalPattern::FieldGroup, of type \l {QtTemporalPattern::}
195 {TemporalFieldFlags}, that combines the members of that group. If no member
196 of such a group is set in a flags variable, it is treated as if all members
197 of that group were set. When serializing, the behavior when two or more
198 conflicting flags, in a group relevant to the field, are combined is
199 unspecified. It may depend on other fields or variables passed to the
200 serialization function. When parsing, such conflicting flags allow the
201 parser to match any of the conflicting options specified. If this leads to
202 ambiguity, parsing prefers the option that consumes more of the text to
203 parse.
204
205 Unless otherwise indicated, fields are localized. For example, ZeroPad pads
206 with, and Numeric uses, locale-appropriate digits when localized, and the
207 names of months, days of the week and timezones are translated into the
208 appropriate language (if possible).
209
210 The primary distinction in how fields are expressed is the form of the
211 field. These first three options are mutually incompatible and are grouped
212 together as the \l {QtTemporalPattern::FieldGroup::} {FormMask} constant:
213
214 \value Numeric Express the field numerically as a series of digits.
215 \value Verbal Name the field value in its usual in-format grammatical form.
216 \value Standalone Name the field value in its stand-alone grammatical form.
217
218 Next comes the width of the field. The meanings of these fields depends on
219 other flags and the field category, where relevant. Some field categories
220 may ignore these entirely, others may draw fewer distinctions and use the
221 same meaning for some widths. These four options are mutually exclusive and
222 grouped together as the \l {QtTemporalPattern::FieldGroup::} {WidthMask}
223 constant:
224
225 \value Narrow Use a the narrowest supported form for the field. In some
226 locales, the Narrow Verbal forms of some fields may use
227 numbers, potentially conflicting with one of its Numeric
228 forms.
229 \value Abbreviated Use an abbreviated form of the field.
230 \value Short Use a short form of the field.
231 \value Wide Use a wide form of the field.
232
233 \section2 Padding
234
235 Where a \c width is specified for a field but the field's value is naturally
236 shorter, it is necessary to indicate how to pad it to the desired width.
237 These two options are mutually exclusive and grouped together as the \l
238 {QtTemporalPattern::FieldGroup::} {PaddingMask} constant:
239
240 \value ZeroPad Only for numeric fields: pad to \c width with zeros. When
241 parsing, accept zeros that don't affect value, reject fields
242 that are narrower than their specified \c width.
243 \value SpacePad For a field with a positive \c width, pad to that \c width
244 with spaces. When parsing, allow leading and trailing
245 spacing characters.
246
247 If neither form of padding is indicated, the natural representation of a
248 value is used even if it fails to reach the \c width specified and parsing
249 will accept a narrower field (although it will prefer a match with full
250 width). In a \l {QtTemporalPattern::TemporalFieldCategory} {TimeZone} field
251 (see below) using an offset form, SpacePad is ignored and ZeroPad or its
252 absence only has its usual meaning for hour fields, while controlling the
253 presence of zero minute and second offsets following the hour field.
254
255 \section2 Space
256
257 Where a text to be matched (for example, a literal or the name of a month or
258 day of the week) contains spaces, by default plain space (ASCII SPACE,
259 U+0020) and the various Unicode spacing characters outside the ASCII range
260 (of various widths, some of them non-breaking) are all accepted as matches
261 for one another, while the number and placement of such short horizontal
262 spaces must match. Other spacing characters (newline, tab, etc.) must match
263 exactly. Since users commonly do not distinguish the short horizontal
264 spaces, this default usually suffices. In some cases, there may be reason to
265 insist on exact matching of spaces, without treating short horizontal spaces
266 as equivalent. Where the text to be parsed is taken from a larger text,
267 however, it's also possible that this larger text has been flowed, as a
268 paragraph, which may have turned some spaces into line breaks, possibly with
269 added indentation, or the text may be split across a page boundary. Coping
270 with such cases is supported by the options
271
272 \value FlexSpace Where a field to be matched contains spacing characters, or
273 a run of them, any spacing character or run of them will be
274 accepted as matching. A character is deemed to be a spacing
275 character if \l QChar::isSpace() is true for it.
276 \value StrictSpace Spacing characters must be matched exactly.
277 Ignored if FlexSpace is also set.
278
279 \section2 Letter case
280
281 The following options are only relevant to Verbal and Standalone
282 fields. They are not treated as a group or descrbed by a mask, as the locale
283 provides relevant fields with the appropriate (possibly mixed) case for the
284 lcoale. By default, the locale's form is used when serializing and matched
285 (case-sensitively) when parsing. The first two of these are mutually
286 exclusive. They change that default, forcing the case when serializing and
287 requiring the specified case (or one of the specified cases) when
288 parsing. The third has no effect when serializing and overrides the other
289 two, if either is present, when parsing.
290
291 \value LowerCase When serializing, force lower-case.
292 \value UpperCase When serializing, force upper-case.
293 \value IgnoreCase When parsing, match the field case-insensitively.
294
295 \section2 Extended fields
296
297 The following options modify the handling of specific fields where there is
298 no intrinsic limit to the number of significant digits in a valid value.
299 They are described in more detail below.
300
301 \value RoundFraction Allows excess precision in a fractional part.
302 \value YearSignIso8601 Requires a sign if there are extra digits in a year.
303
304 By default a \l {QtTemporalPattern::TemporalFieldCategory} {SecondFraction}
305 field only accepts up to three digits or as many digits as its field width
306 specifies. The RoundFraction modifies the field to allow more digits than
307 this, using the excess precision only to resolve rounding to the appropriate
308 precision, as described above for the SecondFraction field.
309
310 Modern revisions of ISO 8601 permit years outside the range from 0 through
311 9999 but require that they have a sign. By default a + sign on a positive
312 year is allowed and silently ignored (without counting towards its \c
313 width), but the YearSignIso8601 applies a modified version of the ISO rule:
314 the year field will only match a text with more digits than its specified \c
315 width if that text starts with a sign. When the field's \c width is 4, this
316 implements the ISO rule, but it can be applied to other widths, if needed.
317
318 In contrast to ISO's use of year 0000 to indicate 1 BCE, with negative year
319 values representing successively earlier years, where the calendar in use
320 has no year zero, Qt describes the year before year 1 as year -1, skipping
321 over 0 and treating 0 as an invalid value for the year. In particular, this
322 applies to the Gregorian calendar, which is used by default: 1 CE is
323 represented as year 1, with 1 BC as year -1. If the calendar in use reports
324 \c true from \l {QCalendar::} {hasYearZero()}, Qt duly accepts a year 0
325 between years -1 and +1. ISO also specifies that years before 1583 (the
326 first full year after the Gregorian calendar came into play) or after 9999
327 should not be used except by prior agreement between the producer and
328 consumer of the serialized date or datetime. Qt leaves such agreement as a
329 matter between the user and those they communicate with, simply accepting
330 any year number within the range of QDate or QDateTime, as appropriate.
331
332 \section2 Timezone representation
333
334 The following options are only relevant to timezones. If used with other
335 categories of field, they are ignored. By default, when the other fields of
336 a timestamp determine a datetime, the zone's localized name in effect at
337 that datetime is used when serializing and matched when parsing.
338
339 There are both localized and international standard formats available. The
340 following pair of options select which of those to use. They are grouped
341 together as the \l {QtTemporalPattern::FieldGroup::} {LocalizationMask}
342 constant:
343
344 \value LocalizedZone For a TimeZone, use localized forms.
345 \value Iso8601 For a TimeZone, use an ISO 8601 offset format.
346
347 When both are specified, or neither is, localized forms are preferred. See
348 \l {Locale-independent offset forms}, below, for details of the ISO
349 8601-based formats. See \c{Standalone | Short} below for the IANA DB and
350 \l{Local time} for a system-dependent form, both of which ignore the choice
351 between LocalizedZone and Iso8601.
352
353 The following three options, selecting seasonal variations, are mutually
354 exclusive and only relevant to Verbal or Standalone forms. They are
355 independent of the choice between LocalizedZone and Iso8601. They are
356 grouped together as the \l {QtTemporalPattern::FieldGroup::} {SeasonMask}
357 constant:
358
359 \value GenericTime For a non-Numeric TimeZone, use its generic name.
360 \value StandardTime For a non-Numeric TimeZone, use its standard-time name.
361 \value DaylightSavingTime For a non-Numeric TimeZone, use its
362 daylight-saving name.
363
364 For localized timezones, Numeric selects a basic offset format or an offset
365 format with a base prefix (typically a localized form of UTC or GMT), Verbal
366 selects a form of the zone's name, and Standalone selects the IANA ID or a
367 localized name based on a city that serves as exemplar for the zone (for the
368 given locale). The effects of the width options above then depend on which
369 of these is used. When LocalizedZone is set, the following forms are
370 available:
371
372 \list
373 \li For Numeric, the timezone offset is used:
374 \list
375 \li Wide uses the hour, minute and second, as for Short, but when
376 parsing it will accept a fractional part of the seconds (following
377 the locale-appropriate separator, after the whole number part of
378 the seconds), if present. As Qt only supports whole numbers of
379 seconds as offsets, this fractional part's only effect is to round
380 up the second part if it is at least a half second. (See note on
381 rounding in the next section.)
382 \li Short uses the hour, minute and second, rounding to the nearest
383 second if the offset is not a whole number of seconds.
384 \li Abbreviated uses the hour and minute, rounding to the nearest
385 minute if the offset is not a whole number of minutes.
386 \li Narrow uses the hour, rounding to nearest if the actual offset is
387 not a whole number of hours.
388 \endlist
389 \li For Verbal, the zone name is used:
390 \list
391 \li Wide uses the full name of the zone, e.g. "Pacific Time", "Pacific
392 Standard Time" or "Pacific Daylight Time", depending on season.
393 \li Short is treated as Wide.
394 \li Abbreviated uses the zone abbreviation, e.g. "PT", "PST" or "PDT".
395 Note that these cannot be reliably parsed.
396 \li Narrow is treated as Abbreviated.
397 \endlist
398 \li For Standalone, the city name:
399 \list
400 \li Wide uses the locale's generic location format, such as "Los
401 Angeles Time".
402 \li Short uses the full IANA ID, such as America/Los_Angeles.
403 This is not localized (the LocalizedZone flag is ignored).
404 \li Abbreviated just gives the localized exemplar city, e.g. "Los
405 Angeles".
406 \li Narrow is treated as Abbreviated.
407 \endlist
408 \endlist
409
410 Where a timezone is specified simply in terms of an offset from UTC, it does
411 not necessarily have an associated city or a name other than its offset
412 representations. For such zones, when serializing, Verbal and Standalone are
413 treated as Numeric, with the exception of \c{Staldalone | Short}, as the
414 IANA ID is not localized and this form, like an IANA ID, is accepted by the
415 QTimeZone(QByteArray) constructor. (Note that these do not include ZeroPad:
416 see the next section for its effect on offset forms.) When parsing,
417 therefore, these offset formats are accepted for the Verbal and Standalone
418 forms that would map to them for offset zones. This applies to \l
419 {QTimeZone::fromDurationAheadOfUtc()} lightweight time representations (for
420 which \l {QTimeZone::}{isUtcOrFixedOffset()} is true) as well as to those,
421 with a UTC-offset backend, constructed by QTimeZone(int) or, with an ID of
422 form \c{"UTC"} or \c{"UTC±HH:mm"}, by QTimeZone(QByteArray),
423
424 \section3 Offset modifiers
425
426 In the various timezone offset formats (both above and below), there are
427 potentially hour, minute and second parts of the offset, depending on the
428 width option selected. The minute and second parts, when present, always use
429 two digits, rendering the usual meaning of ZeroPad redundant. Instead, for
430 these parts, ZeroPad controls whether trailing zero parts are included.
431 When ZeroPad is set they are included when serializing and required to be
432 present when parsing. When ZeroPad is not set, they are omitted when
433 serializing and, if trailng parts are missing when parsing, they are taken
434 to have value zero. Zero parts are always accepted when parsing, even when
435 ZeroPad is not set.
436
437 The hour part of an offset is never omitted when serializing and is always
438 required when parsing. When ZeroPad is not set, when parsing offset formats
439 with separators between parts, a single-digit hour is accepted. (For the
440 localized offset formats above, whether there are separators between parts
441 depends on the locale.) When ZeroPad is not set, serialization only produces
442 a single-digit hour if there are no later parts (typically because they were
443 all zero, hence omitted). Otherwise, the hour part is always serialized with
444 two digits and parsing requires it to have two digits.
445
446 As ever, if more than one width is specified, any given is allowed. On
447 serializing, narrower formats are preferred unless they lose precision in
448 the offset that an allowed longer format would include. Thus \c{Narrow |
449 Short} would include only the hours for a whole-hour offset, but would
450 include hours, minutes and seconds for an hour-and-a-half offset (albeit
451 omitting the zero seconds unless ZeroPad is set). Where the width thus
452 selected requires rounding due to omitting a part of the offset that isn't
453 zero, exact halves round away from zero. On parsing, the longest allowed
454 form for which a match is found will be used.
455
456 Offset formats may also include a prefix (localized in the forms above) that
457 identifies the offset as being relative to UTC or GMT. The following pair of
458 mutually exclusive options control whether that is omitted or included.
459 They are grouped together as the \l {QtTemporalPattern::FieldGroup::}
460 {UtcPrefixMask} constant:
461
462 \value AcceptUtcPrefix Include a UTC prefix on offsets when serializing and
463 require it when parsing.
464 \value NeedNoUtcPrefix Leave off the UTC prefix when serializing and reject
465 it when parsing.
466
467 If neither or both of these are specified, serializing omits the prefix and
468 parsing permits it but does not require it.
469
470 \section3 Locale-independent offset forms
471
472 In addition to these localized forms, a timestamp may also represent its
473 zone in a locale-independent offset form. In effect, this use the C locale,
474 with ASCII digits 0 through 9, the ASCII + and - as signs, and the ASCII
475 colon as separator (where relevant). These are selected by the \c Iso8601
476 flag.
477
478 \value AllowZSuffix Modifies Iso8601 to allow use of a \c{Z} suffix to
479 denote a zero UTC offset. See RFC 9557 note below.
480
481 If AllowZSuffix is set and ZeroPad is not, serialization will use \c{Z} to
482 represent a zero offset. When ZeroPad is set, serialization ignores
483 AllowZSuffix. If AllowZSufix is set, regardless of ZeroPad, parsing will
484 accept a \c{Z} suffix as meaning zero offset.
485
486 The Iso8601 format is modified by other flags as follows (when not using
487 \c{Z} to represent a zero offset):
488 \list
489 \li With Numeric it uses a basic format (with no separators), with Verbal
490 or Standalone it uses separators between hours, minutes and seconds,
491 in so far as these appear.
492 \li The width options Wide, Short, Abbreviated and Narrow have the same
493 meanings as for Numeric localized offset formats, modified by the
494 ZeroPad option, as described above.
495 \endlist
496
497 \note In some contexts, notably where \l
498 {https://www.rfc-editor.org/rfc/rfc9557.html} {RFC 9557} is used, a zone
499 indicator on a timestamp may be understood as giving context to the
500 information in which it appears, as opposed to only indicating the zone with
501 respect to which the timestamp itself is expressed. In such contexts, a
502 \c{Z} suffix, applied by \c AllowZSuffix, only indicates that the timestamp
503 itself is given with respect to UTC and does not give any context to the
504 information in which it appears. For contrast, in such contexts, a +00:00
505 suffix does indicate not only that the timestamp is given in UTC but also
506 that UTC is the relevant zone for the context of the information. Prior to
507 RFC 9557, some RFCs (incompatibly with ISO 8601) proposed using -00:00 to
508 indicate what RFC 9557 has specified as the meaning for a \c{Z}
509 suffix. Nothing in Qt attends to this distinction.
510
511 \section3 Local time
512
513 Where Qt can determine how the local system describes its local time, Qt has
514 no control over the form in which the system supplies it, nor does Qt know
515 whether, or how, it is localized, with the result that this representation
516 is system-dependent. As another system may be using a different local time,
517 or representing it differently, there is no guarantee that what one system
518 supplies for local time can be successfully understood on another system. To
519 opt in to using this system-dependent representation of local time, supply
520 the following option. Even then, when serializing, if the options given
521 permit any other available representation of the timezone, that is preferred
522 over this.
523
524 \value LocalTimeName Allow the system-supplied local time name to describe
525 the system's local time.
526
527 The system local time may come in separate forms for standard time and
528 daylight-saving time. When it does, the options above for selecting between
529 these affect LocalTimeName as usual, with GenericTime ignored.
530
531 \sa {QtTemporalPattern::}{TemporalFieldCategory}, {QtTemporalPattern::}{TemporalFieldFlags}
532*/
533// RFC 9557: see QTBUG-114172
534
535// TemporalFieldFlags and DateTimeParts: docs taken care of automagically by
536// QDoc, recognizing QFLAG() usage.
537
538/*!
539 \fn constexpr bool QtTemporalPattern::matchesFlagWithin(QtTemporalPattern::TemporalFieldFlags flags, QtTemporalPattern::TemporalFieldFlag sought, QtTemporalPattern::TemporalFieldFlags group)
540
541 Tests \a flags for a \a sought flag within a \a group.
542
543 Implements the per-flag check for a single TemporalFieldFlag with respect to
544 its FieldGroup entry. If no flag in a group is given in \a flags, then all
545 flags in the group are allowed; otherwise, only the given flags in the group
546 match.
547*/
548
549/*!
550 \fn constexpr bool QtTemporalPattern::matchesFlagsWithin(QtTemporalPattern::TemporalFieldFlags flags, QtTemporalPattern::TemporalFieldFlags sought, QtTemporalPattern::TemporalFieldFlags group)
551
552 Similar to \l matchesFlagWithin(), but if any of those \a sought is found in
553 \a flags, or if none of group are, it's counted as a match.
554
555 In some contexts, some flags are treated as equivalent, so to check for what
556 they represent pass the equivalent flags |-joined as \a sought.
557*/
558
559
560/*!
561 \enum QtTemporalPattern::DateTimePart
562 \brief This enumeraction classifies the various field categories.
563
564 The classification addresses which parts of a datetime a field contributes
565 data to.
566
567 \value None A literal field contributes no data.
568 \value Date Various fields contribute to the date.
569 \value Time Various fields contribute to the time.
570 \value Zone Only the \l {QtTemporalPattern::TemporalFieldFlag::}{TimeZone}
571 field contributes information about the timezone.
572
573 These may be combined in a \l {QtTemporalPattern::}{DateTimeParts} to
574 express a set of parts that a set of fields might suffice to describe,
575 whether fully or only in part.
576
577 \sa {QtTemporalPattern::}{TemporalFieldCategory}, {QtTemporalPattern::}{supports()}
578*/
579
580/*!
581 \fn QtTemporalPattern::classify(QtTemporalPattern::TemporalFieldCategory category) noexcept
582 \brief Classify a field category according to the part of a datetime it contributes to.
583
584 This maps a \l {QtTemporalPattern::}{TemporalFieldCategory} to the \l
585 {QtTemporalPattern::}{DateTimePart} for which it supplies data.
586*/
587
588/*!
589 \class QtTemporalPattern::TemporalField
590 \brief Describes one field in a temporal pattern.
591
592 A single field is characterized by its \l
593 {QtTemporalPattern::TemporalFieldCategory}{category}, some \l
594 {QtTemporalPattern::TemporalFieldFlags}{options} identifying how the field
595 is to be expressed and, where relevant, a datum. For a Literal field, the
596 datum is the string to be matched.
597
598 For numeric fields, a width may optionally be specified, indicating
599 the expected number of digits in the field. If options specifies
600 zero-padding, this is a minimum number of digits; otherwise, shorter fields
601 are accepted. In any case, longer values are accepted, where the resulting
602 numeric value is valid for the field. A zero width does not mean an empty
603 field will be accepted: it is effectively equivalent to a width of 1.
604
605 \note in some locales, the digits may require surrogate pairs to encode, so
606 the UTF-16 length of the field may exceed the number of digits. In a year
607 field with a sign, the sign does not count towards the width of the
608 field. The width only counts digits. The width is, in any case, a lower
609 bound: more digits may be read, if present and not consumed by some later
610 field. The \c endIndex of any parse result is the only reliable source of
611 truth on the UTF-16 end of the text parsed.
612*/
613// TODO: should we support digit grouping in year numbers, at least with > 4 digits ?
614
615/*!
616 \fn QtTemporalPattern::hasFieldsFor(QSpan<const QtTemporalPattern::TemporalField> range)
617 \brief Identify the parts to which the given fields contribute data.
618
619 Takes a \a range of TemporalField instances and returns a \l
620 {QtTemporalPattern::}{DateTimeParts} indicating which parts \l classify()
621 says any of the fields contribute to. Note that this only tessts for
622 contribution to a part, not for full coverage of the part. See \l supports()
623 for that.
624
625 \sa classify(), supports()
626*/
627
628/*!
629 \enum QtTemporalPattern::SupportType
630 \brief This enumeration identifies how well some fields describe requested datetime parts.
631
632 The fields of a pattern may contain partial or complete data on each of the
633 \l {QtTemporalPattern::TemporalFieldPart}{parts of} a datetime. When parsing
634 or serializing only a date or only a time, fields for the other or for
635 timezone are extraneous, making the pattern unable to serialize just the
636 intended type, as it lacks the data for those fields. It would also, when
637 parsing, be obliged discard some of the data it parses, as the type it
638 returns cannot express it.
639
640 When serializing a datetime, if the fields present do not suffice to fully
641 encode the date or time, it will not be possible for a reader of the
642 resulting text to unambiguously determine the datetime. If timezone is not
643 specified, it is possible to convert the datetime to some specific choice of
644 zone: provided both ends of the communication use the same zone, it is then
645 possible to recover the exact point in time, albeit without knowing the
646 timezone originally used to encode it.
647
648 Where data is partially supplied, it is possible that the partial data
649 suffices to meet the readers needs, although this typically involves the
650 reader in making some default assumptions about the missing fields. For
651 example, a two-digit year may need some assumptions about the century
652 (possibly aided by information about the date and day of the week) to
653 determine what year to presume the sender intended.
654
655 \value None No fields were found.
656 \value HasStrays Some field not relevant to the requested parts was present.
657 \value Partial Either some requested part is present and some other is
658 missing or some fields for a requested part are present but
659 not enough to fully describe that part.
660 \value Clear Enough fields of the requested parts were found to fully
661 determine them and no fields of unwanted parts were present.
662
663 Where partial fields for the requested parts were found along with fields
664 for unwanted parts, HasStrays is used in preference to Partial, as it is
665 considered a more significant defect.
666
667 \sa {QtTemporalPattern::}{TemporalFieldPart}, {QtTemporalPattern::}{supports()}
668*/
669
670/*!
671 \fn QtTemporalPattern::supports(QtTemporalPattern::DateTimeParts wanted, QSpan<QtTemporalPattern::TemporalField> range, bool hasBaseYear) noexcept
672 \brief Assess how well the given fields support the \a wanted parts.
673
674 If any field in \a range belongs to a part not included in \a wanted,
675 returns \l {SupportType::}{HasStrays}. Otherwise,
676
677 \list
678 \li If no fields are present, aside from \l
679 {TemporalFieldCategory::}{Literal} ones, returns \l
680 {SupportType::}{None}.
681 \li If the fields present completely specify all parts in \a wanted,
682 returns \l {SupportType::}{Clear}.
683 \li If some fields are specified but some \a wanted part is inadequately
684 specified, or entirely unspecified, returns \l
685 {SupportType::}{Partial}.
686 \endlist
687
688 For these purposes,
689
690 \list
691 \li The \l {DateTimePart::}{Zone} part is specified by the \l
692 {TemporalFieldCategory::}{TimeZone}.
693 \li The \l {DateTimePart::}{Time} part is specified by any combination of
694 fields that identify the hour and minute. If the \l
695 {TemporalFieldCategory::}{SecondFractions} field is present, the part is
696 considered incompletely specified unless the \l
697 {TemporalFieldCategory::}{Seconds} field is also present.
698 \li The \l {DateTimePart::}{Date} part is specified by any combination of
699 fields that identify a date. This usually means \l
700 {TemporalFieldCategory::}{Year}, \l {TemporalFieldCategory::}{Month}
701 and \l {TemporalFieldCategory::}{DayOfMonth} although Year may be
702 indirectly specified by \l
703 {TemporalFieldCategory::}{YearWithinCentury} if the presence of \l
704 {TemporalFieldCategory::}{DayOfWeek} enables disambiguation among
705 centuries close to the present, given the other date fields.
706 \endlist
707*/
708
709template <typename Enum, size_t Size>
711{
712 std::bitset<Size> bits;
713 static size_t map(Enum cat) { return qToUnderlying(cat); }
714public:
715 void set(Enum cat) { bits[map(cat)] = true; }
716 bool test(Enum cat) const { return bits[map(cat)]; }
717};
718
719SupportType supports(DateTimeParts wanted, QSpan<const TemporalField> range,
720 bool hasBaseYear) noexcept
721{
722 // TODO: may need to take into account calendar (and perhaps locale).
723 SupportType support = SupportType::HasStrays;
724 SupportType zone = SupportType::None;
725 EnumIndexedBitSet<TemporalFieldCategory, EndTemporalFieldCategories> categories;
726 for (const TemporalField &field : range) {
727 const DateTimePart part = field.part();
728 switch (part) {
729 case DateTimePart::None: // Literal contributes no data.
730 continue;
731 case DateTimePart::Date:
732 case DateTimePart::Time:
733 categories.set(field.category);
734 break;
735 case DateTimePart::Zone:
736 if (field.options.testAnyFlags(TemporalFieldFlag::Wide | TemporalFieldFlag::Short)
737 || field.options.testAnyFlags(TemporalFieldFlag::Numeric
738 | TemporalFieldFlag::Standalone
739 | TemporalFieldFlag::Iso8601)) {
740 zone = SupportType::Clear;
741 } else if (zone == SupportType::None) {
742 // Zone name abbreviation: does not uniquely identify zone.
743 zone = SupportType::Partial;
744 }
745 break;
746 }
747 if (!wanted.testFlag(part))
748 return support;
749 }
750
751 bool partsSeen = wanted.testFlag(DateTimePart::Zone);
752 support = partsSeen ? zone : SupportType::None;
753
754 constexpr auto join = [](SupportType lhs, SupportType rhs) -> SupportType {
755 Q_PRE(lhs != SupportType::HasStrays);
756 Q_PRE(rhs != SupportType::HasStrays);
757 // For combining SupportTypes from different Parts to determine support
758 // for their composite. Simplest case is when they're the same:
759 if (lhs == rhs)
760 return lhs;
761 // Every combination of distinct values among the other three is partial:
762 return SupportType::Partial;
763 };
764
765#define CHECK(field) (categories.test(TemporalFieldCategory::field))
766
767 if (wanted.testFlag(DateTimePart::Date)) {
768 const SupportType hasDate = [&] {
769 // if (CHECK(JulianDay)) return SupportType::Clear;
770 int fields = 0;
771 bool partial = false;
772 if (CHECK(Year)) {
773 ++fields;
774 } else if (CHECK(YearWithinCentury)) {
775 if (hasBaseYear) {
776 ++fields;
777 // } else if (CHECK(Century)) { ++fields;
778 } else if (CHECK(DayOfWeek) && CHECK(DayOfMonth) && CHECK(Month)) {
779 // We can infer century from those three by assuming it's
780 // close to the present.
781 ++fields;
782 } else {
783 partial = true;
784 }
785 // } else if (CHECK(Century)) { partial = true;
786 }
787 if (CHECK(Month))
788 ++fields;
789 if (CHECK(DayOfMonth))
790 ++fields;
791 else if (CHECK(DayOfWeek))
792 partial = true;
793 if (fields == 3 && !partial)
794 return SupportType::Clear;
795 if (fields || partial)
796 return SupportType::Partial;
797 return SupportType::None;
798 }();
799 support = partsSeen ? join(support, hasDate) : hasDate;
800 partsSeen = true;
801 }
802
803 if (wanted.testFlag(DateTimePart::Time)) {
804 const SupportType hasTime = [&] {
805 // if (CHECK(MillisecondInDay)) return SupportType::Clear;
806 int fields = 0;
807 bool partial = false;
808 if (CHECK(Hour)) {
809 ++fields;
810 } else if (CHECK(HourMod12)) {
811 if (CHECK(PeriodInDay))
812 ++fields;
813 else
814 partial = true;
815 } else if (CHECK(PeriodInDay)) {
816 partial = true;
817 }
818 if (CHECK(Minute))
819 ++fields;
820 // Hour and minute are required, but seconds and later are optional;
821 // however, having a finer field without an coarser one leaves a gap => Partial.
822 if (CHECK(Second))
823 partial = fields < 2;
824 else if (CHECK(SecondFraction))
825 partial = true;
826 if (fields == 2 && !partial)
827 return SupportType::Clear;
828 if (fields || partial)
829 return SupportType::Partial;
830 return SupportType::None;
831 }();
832 support = partsSeen ? join(support, hasTime) : hasTime;
833 partsSeen = true;
834 }
835
836#undef CHECK
837
838 // Shall still be None if we've seen no fields:
839 Q_ASSERT(partsSeen || support == SupportType::None);
840 return support;
841}
842
843} // namespace QtTemporalPattern
844
845/*!
846 \internal
847 \since 6.12
848 \class QDateTimePattern
849 \brief A description of a serialization format for a datetime
850*/
851
852/*!
853 \fn QDateTimePattern::forLocale(const QLocale &locale, QLocale::FormatType format)
854 Construct a QDateTimePattern appropriate to the given \a locale.
855
856 The \a format can be used to select how compact or expansive the pattern is.
857
858 \sa fromQtFormat()
859*/
860
861/*!
862 \fn QDateTimePattern::isNull() const noexcept
863
864 Returns \c true if this pattern has no fields, otherwise \a false.
865
866 \sa fromQtFormat()
867*/
868
869/*
870//! [is-valid]
871 Returns \c true if this pattern can be used to reliably transmit {\1}s.
872
873 Returns \c false if there is unresolved ambiguity in the texts it will
874 produce when serializing or the texts that will match it when parsing.
875 Some apparent ambiguities may be resolved by interactions between other
876 fields or the \c{defaults} parameter to \l{parse()}.
877//! [is-valid]
878*/
879
880// TODO: currently (see supports(), above) doesn't take locale or calendar into account.
881/*!
882 \fn QDateTimePattern::isValid() const noexcept
883
884 \include qttemporalpattern.cpp {is-valid} {datetime}
885 \include qttemporalpattern.cpp base-year-disambiguates
886
887 Timezone abbreviations are ambiguous.
888
889 \sa isNull()
890*/
891
892/*!
893 \fn QDateTimePattern::setLocale(const QLocale &loc) noexcept
894
895//! [set-locale]
896 Sets the locale, for use for fields whose representation depends on locale,
897 to \a loc. By default the application's current default locale is used.
898
899 \sa QLocale::setDefault()
900//! [set-locale]
901*/
902
903/*!
904 \fn QDateTimePattern::locale() const noexcep
905
906 Returns the current locale in use by this pattern.
907
908 \sa setLocale()
909*/
910
911/*!
912 \fn QDateTimePattern::setCalendar(QCalendar calendar) noexcept
913
914 \include qttemporalpattern.cpp set-calendar
915*/
916
917/*!
918 \fn QDateTimePattern::calendar(QCalendar calendar) const noexcept
919
920 Returns the current calendar in use by this pattern.
921
922 \sa setCalendar()
923*/
924
925/*!
926 \fn QDateTimePattern::setBaseYear(int centuryStart) noexcept
927
928 \include qttemporalpattern.cpp set-base-year
929*/
930
931/*!
932 \fn QDateTimePattern::clearBaseYear() noexcept
933
934 \include qttemporalpattern.cpp clear-base-year
935*/
936
937/*!
938 \fn QDateTimePattern::baseYear() const noexcept
939
940 \include qttemporalpattern.cpp get-base-year
941*/
942
943/*!
944 Parse and return the datetime represented by \a text.
945
946//! [parser-defaults]
947 If \a defaults is provided and valid, any fields the format described by
948 this pattern does not provide will be copied from \a defaults to construct
949 the returned value.
950//! [parser-defaults]
951*/
952
953QtTemporalPattern::ParseResult<QDateTime>
954QDateTimePattern::parse(QStringView text, const QDateTime &defaults) const
955{
956#if QT_CONFIG(datetimeparser)
957 const auto seen = QtParseTemporal::prefix(text, m_fields, m_locale, m_calendar, m_baseYear);
958 if (!m_fields.isEmpty() && !seen) // Failed to parse.
959 return {};
960
961 const QDate date = seen.date(m_calendar, defaults.date());
962 const QTime time = seen.time(defaults.time());
963
964 if (QDateTime result(date, time, seen.zone, seen.resolveType()); result.isValid())
965 return {std::move(result), seen.size()};
966 // Fall back to default transition resolution:
967 return {QDateTime(date, time, seen.zone), seen.size()};
968#else
969 Q_UNUSED(text);
970 Q_UNUSED(defaults);
971 return {};
972#endif // datetimeparser
973}
974
975/*!
976 Serialize the given \a datetime to a string representation.
977*/
978
979QString QDateTimePattern::serialize(const QDateTime &datetime) const
980{
981 Q_UNUSED(datetime);
982 return {};
983}
984
985/*!
986 Construct a QDateTimePattern described by the given \a format string.
987
988 If the format is empty or malformed, the returned pattern's \c isNull() shall
989 be \c true. Otherwise, \c isNull() shall be \c false.
990
991 \sa forLocale(), isNull()
992*/
993
994QDateTimePattern QDateTimePattern::fromQtFormat(QStringView format)
995{
996 using namespace QtTemporalPattern;
997 constexpr DateTimeParts form = DateTimePart::Date | DateTimePart::Time | DateTimePart::Zone;
998 const auto qt = QtParseQtTemporalFormat::prefix(format, form);
999 if (qt.size() == format.size())
1000 return QDateTimePattern(qt.fields);
1001 return QDateTimePattern({});
1002}
1003
1004/*!
1005 \internal
1006 \since 6.12
1007 \class QTimePattern
1008 \brief A description of a serialization format for a time
1009*/
1010
1011/*!
1012 \fn QTimePattern::forLocale(const QLocale &locale, QLocale::FormatType format)
1013 Construct a QTimePattern appropriate to the given \a locale.
1014
1015 The \a format can be used to select how compact or expansive the pattern is.
1016
1017 \sa fromQtFormat()
1018*/
1019
1020/*!
1021 \fn QTimePattern::isNull() const noexcept
1022
1023 Returns \c true if this pattern has no fields, otherwise \a false.
1024
1025 \sa fromQtFormat()
1026*/
1027
1028/*!
1029 \fn QTimePattern::isValid() const noexcept
1030
1031 \include qttemporalpattern.cpp {is-valid} {time}
1032
1033 \sa isNull()
1034*/
1035
1036/*!
1037 \fn QTimePattern::setLocale(const QLocale &loc) noexcept
1038
1039 \include qttemporalpattern.cpp set-locale
1040*/
1041
1042/*!
1043 \fn QTimePattern::locale() const noexcep
1044
1045 Returns the current locale in use by this pattern.
1046
1047 \sa setLocale()
1048*/
1049
1050/*!
1051 Parse and return the time represented by \a text.
1052
1053 \include qttemporalpattern.cpp parser-defaults
1054*/
1055
1056QtTemporalPattern::ParseResult<QTime>
1057QTimePattern::parse(QStringView text, QTime defaults) const
1058{
1059#if QT_CONFIG(datetimeparser)
1060 const auto seen = QtParseTemporal::prefix(text, m_fields, m_locale, QCalendar());
1061 if (!m_fields.isEmpty() && !seen) // Failed to parse.
1062 return {};
1063 return {seen.time(defaults), seen.size()};
1064#else
1065 Q_UNUSED(text);
1066 Q_UNUSED(defaults);
1067 return {};
1068#endif // datetimeparser
1069}
1070
1071/*!
1072 Serialize the given \a time to a string representation.
1073*/
1074
1075QString QTimePattern::serialize(const QTime &time) const
1076{
1077 Q_UNUSED(time);
1078 return {};
1079}
1080
1081/*!
1082 Construct a QTimePattern described by the given \a format string.
1083
1084 If the format is empty or malformed, the returned pattern's \c isNull() shall
1085 be \c true. Otherwise, \c isNull() shall be \c false.
1086
1087 \sa forLocale(), isNull()
1088*/
1089
1090QTimePattern QTimePattern::fromQtFormat(QStringView format)
1091{
1092 using namespace QtTemporalPattern;
1093 constexpr DateTimeParts form{DateTimePart::Time};
1094 const auto qt = QtParseQtTemporalFormat::prefix(format, form);
1095 if (qt.size() == format.size())
1096 return QTimePattern(qt.fields);
1097 return QTimePattern({});
1098}
1099
1100/*!
1101 \internal
1102 \since 6.12
1103 \class QDatePattern
1104 \brief A description of a serialization format for a date
1105*/
1106
1107/*!
1108 \fn QDatePattern::forLocale(const QLocale &locale, QLocale::FormatType format)
1109 Construct a QDatePattern appropriate to the given \a locale.
1110
1111 The \a format can be used to select how compact or expansive the pattern is.
1112
1113 \sa fromQtFormat()
1114*/
1115
1116/*!
1117 \fn QDatePattern::isNull() const noexcept
1118
1119 Returns \c true if this pattern has no fields, otherwise \a false.
1120
1121 \sa fromQtFormat()
1122*/
1123
1124/*!
1125 \fn QDatePattern::isValid() const noexcept
1126
1127 \include qttemporalpattern.cpp {is-valid} {date}
1128
1129//! [base-year-disambiguates]
1130 The ambiguity of two-digit years may be resolved by configuring the hundred
1131 years among which to select a matching years.
1132//! [base-year-disambiguates]
1133
1134 \sa setBaseYear(), isNull()
1135*/
1136
1137/*!
1138 \fn QDatePattern::setLocale(const QLocale &loc) noexcept
1139
1140 \include qttemporalpattern.cpp set-locale
1141*/
1142
1143/*!
1144 \fn QDatePattern::locale() const noexcep
1145
1146 Returns the current locale in use by this pattern.
1147
1148 \sa setLocale()
1149*/
1150
1151/*!
1152 \fn QDatePattern::setCalendar(QCalendar calendar) noexcept
1153
1154//! [set-calendar]
1155 Sets the calendar used by this pattern. This influences the names and
1156 lengths of months and how these vary from year to year. In some cases it may
1157 also influence the number of months in the year or even the pattern and
1158 names of days of the week.
1159
1160 By default the Gregorian calendar is used.
1161
1162 \sa getCalendar(), QCalendar
1163//! [set-calendar]
1164*/
1165
1166/*!
1167 \fn QDatePattern::calendar(QCalendar calendar) const noexcept
1168
1169 Returns the current calendar in use by this pattern.
1170
1171 \sa setCalendar()
1172*/
1173
1174/*!
1175 \fn QDatePattern::setBaseYear(int centuryStart) noexcept
1176
1177//! [set-base-year]
1178 Configures the handling of two-digit years, if any are present in the pattern.
1179
1180 If a two-digit year is present, the year ending in those two digits in the
1181 range from \a centuryStart to \c {centuryStart + 99} shall be its default
1182 interpretation. This may be amended if the month, day of the month and day
1183 of the week indicate some other nearby century.
1184
1185 \note the years here, including \a centuryStart, are expressed with respect
1186 to \c{calendar()}, whose year numbering need not match that of the Gregorian
1187 calendar.
1188
1189 Calling this method makes no difference unless the pattern does in fact use
1190 a two-digit year, nor does it affect serialization.
1191
1192 \sa clearBaseYear()
1193//! [set-base-year]
1194*/
1195
1196// TODO: should the default state be clear or some specific year ?
1197// That year could depend on the present, e.g. present minus 49 years.
1198
1199/*!
1200 \fn QDatePattern::clearBaseYear() noexcept
1201
1202//! [clear-base-year]
1203 Leaves the handling of two-digit years to other fields to disambiguate.
1204
1205 This is the default state, so has no effect unless \l setBaseYear() has
1206 previously been called.
1207
1208 If a two-digit year is present, this leaves unspecified which hundred years
1209 to presume it lies within. If a two-digit year is present and other fields
1210 of the pattern do not suffice to make clear which hundred years to select
1211 based on the given last two digits, the text produced when serializing with
1212 this format shall generally be ambiguous. While readers of the text may be
1213 able to disambiguate the year anyway, there is scope for misunderstanding if
1214 their heuristics for doing so do not match your expectation. On parsing, the
1215 pattern may deliver a result that is off by some whole number of centuries
1216 from what the parsed text's author intended.
1217
1218 \sa setBaseYear(), isValid()
1219//! [clear-base-year]
1220*/
1221
1222/*!
1223 \fn QDatePattern::baseYear() const noexcept
1224
1225//! [get-base-year]
1226
1227 Returns the current base year, with respect to \c{calendar()}, used by this
1228 pattern if it needs to resolve a two-digit year. The result is \c
1229 {std::nullopt} when no base year is set, which is the default state.
1230
1231 \sa setBaseYear()
1232//! [get-base-year]
1233*/
1234
1235/*!
1236 Parse and return the date represented by \a text.
1237
1238 \include qttemporalpattern.cpp parser-defaults
1239*/
1240
1241QtTemporalPattern::ParseResult<QDate>
1242QDatePattern::parse(QStringView text, QDate defaults) const
1243{
1244#if QT_CONFIG(datetimeparser)
1245 const auto seen = QtParseTemporal::prefix(text, m_fields, m_locale, m_calendar, m_baseYear);
1246 if (!m_fields.isEmpty() && !seen) // Failed to parse.
1247 return {};
1248 return {seen.date(m_calendar, defaults), seen.size()};
1249#else
1250 Q_UNUSED(text);
1251 Q_UNUSED(defaults);
1252 return {};
1253#endif // datetimeparser
1254}
1255
1256/*!
1257 Serialize the given \a date to a string representation.
1258
1259 \sa parse()
1260*/
1261
1262QString QDatePattern::serialize(const QDate &date) const
1263{
1264 Q_UNUSED(date);
1265 return {};
1266}
1267
1268/*!
1269 Construct a QDatePattern described by the given \a format string.
1270
1271 If the format is empty or malformed, the returned pattern's \c isNull() shall
1272 be \c true. Otherwise, \c isNull() shall be \c false.
1273
1274 \sa forLocale(), isNull()
1275*/
1276
1277QDatePattern QDatePattern::fromQtFormat(QStringView format)
1278{
1279 using namespace QtTemporalPattern;
1280 constexpr DateTimeParts form{DateTimePart::Date};
1281 const auto qt = QtParseQtTemporalFormat::prefix(format, form);
1282 if (qt.size() == format.size())
1283 return QDatePattern(qt.fields);
1284 return QDatePattern({});
1285}
1286
1287QT_END_NAMESPACE
Supporting types and functions for temporal patterns.
SupportType supports(DateTimeParts wanted, QSpan< const TemporalField > range, bool hasBaseYear) noexcept
#define CHECK(cvref)