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_p.h
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
5#ifndef QTTEMPORALPATTERN_P_H
6#define QTTEMPORALPATTERN_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an implementation
13// detail. This header file may change from version to version without notice,
14// or even be removed.
15//
16// We mean it.
17//
18
19#include <QtCore/qcalendar.h>
20#include <QtCore/qdatetime.h>
21#include <QtCore/qflags.h>
22#include <QtCore/qlist.h>
23#include <QtCore/qlocale.h>
24#include <QtCore/qmetaobject.h>
25#include <QtCore/qspan.h>
26#include <QtCore/qstring.h>
27#include <QtCore/qstringview.h>
28
29#include <optional>
30
32QT_BEGIN_NAMESPACE
33
34namespace QtTemporalPattern {
35
36 // Model the LDML spec's range of possible fields, see QTBUG-70516 and
37 // https://www.unicode.org/reports/tr35/tr35-dates.html#table-date-field-symbol-table
40
41 // Special:
43
44 // Time:
45 // MillisecondInDay = 17,
47 Minute = 24, // MinuteFraction = 25,
48 HourMod12 = 30, Hour = 31, // HourFraction = 32,
49 PeriodInDay = 33, // am/pm; LDML also has noon, midnight, "at night" and others.
50
51 // Date:
52 DayOfWeek = 64, DayOfMonth = 65, // DayOfYear = 68, JulianDay = 69,
53 // WeekOfMonth = 72,
54 // WeekOfYear = 73, // QTBUG-57212, QTBUG-83678, QTBUG-117055
55 Month = 80,
56 // Quarter = 84,
57 // RelatedGregorianYear = 90, Century = 91,
59 // Era = 100,
60
62 };
63 constexpr inline
65
67 Numeric = 1, Verbal = 2, Standalone = 4,
68 Narrow = 0x10, Abbreviated = 0x20, Short = 0x40, Wide = 0x80,
69 ZeroPad = 0x0100, // For TimeZone, ZeroPad applies only to hour fields.
70 SpacePad = 0x0200, FlexSpace = 0x0400, StrictSpace = 0x0800,
71 // Qt used to impose case on am/pm fields:
72 LowerCase = 0x1000, UpperCase = 0x2000, // Otherwise follow locale-supplied case.
73 IgnoreCase = 0x4000, // Parsing Literal or Verbal: match case insensitively
74 // (0x8000 free)
75 // Special cases:
76 RoundFraction = 0x01'0000, // Fractional part accepts extra digits, rounding suitably
77 // (0x02'0000, 0x04'0000 free)
78 YearSignIso8601 = 0x08'0000, // Require sign when excess digits
79 // Zone-specific:
80 LocalizedZone = 0x10'0000, // Localized forms, various.
81 Iso8601 = 0x20'0000, // Non-localized standard offset forms.
82 AcceptUtcPrefix = 0x40'0000, NeedNoUtcPrefix = 0x80'0000, // On offsets
83 AllowZSuffix = 0x0100'0000, // Iso8601 zero-offset may be indicated by Z.
84 // Time-types (if none specified, infer time type from date/time fields):
85 GenericTime = 0x0200'0000, StandardTime = 0x0400'0000, DaylightSavingTime = 0x0800'0000,
86 // (0x1000'0000, 0x2000'0000, 0x4000'0000 free)
87 // Local time from system info:
88 LocalTimeName = 0x8000'0000 // That's the last bit available to us.
89 };
92
93 namespace FieldGroup {
107 }
108
109 // Implement group-related tests:
110 constexpr inline
118
119 constexpr inline
127
128 // Classify the categories:
129 enum class DateTimePart { None, Date = 1, Time = 2, Zone = 4 };
132#ifdef QT_BUILD_INTERNAL
136#endif // For testing.
137
139 {
141 return DateTimePart::None;
142 if (quint8(category) < 16)
143 return DateTimePart::Zone;
144 if (quint8(category) < 64) // a.k.a. 0x40
145 return DateTimePart::Time;
146 return DateTimePart::Date;
147 }
148
149 // Combine with related information:
151 QString literal; // Only relevant to Literal
152 qsizetype width; // Lower bound, usually only relevant to Numeric.
155 DateTimePart part() const noexcept { return classify(category); }
156 friend bool comparesEqual(const TemporalField &lhs, const TemporalField &rhs) noexcept
157 {
158 return lhs.literal == rhs.literal
159 && lhs.width == rhs.width
160 && lhs.options == rhs.options
161 && lhs.category == rhs.category;
162 }
164 };
165
166 inline DateTimeParts hasFieldsFor(QSpan<const TemporalField> range)
167 {
168 DateTimeParts result = DateTimePart::None;
169 for (const TemporalField &it : range)
170 result |= it.part();
171 return result;
172 }
173
174 enum class SupportType { Partial = -1, None = 0, Clear = 1, HasStrays };
175 Q_CORE_EXPORT
177 bool hasBaseYear = false) noexcept;
178} // namespace QtTemporalPattern
179
180/* We may eventually want to make the following public API (along with a
181 forward-declaration of QtTemporalPattern::TemporalField), while leaving the
182 above in a private header. See QTBUG-70516, QTBUG-81056.
183
184 This may, of course, involve splitting the types below into a public facade
185 with the actual data members hidden from view behind a shared d-pointer to a
186 private internal class.
187
188 Please bear that in mind when considering the design of the APIs below, and
189 any future changes thereto.
190*/
191
192namespace QtTemporalPattern {
193template <typename Payload>
195{
196 Payload payload;
198};
199} // namespace QtTemporalPattern
200
202{
204 QList<Field> m_fields;
205 QLocale m_locale;
206 QCalendar m_calendar;
207 std::optional<int> m_baseYear;
208 explicit QDateTimePattern(const QList<Field> &fs) : m_fields(fs) {}
209 explicit QDateTimePattern(const QList<Field> &fs, int centuryStart)
210 : m_fields(fs), m_baseYear(centuryStart) {}
211
212 QtTemporalPattern::SupportType dateTimeSupport() const noexcept
213 {
214 using namespace QtTemporalPattern;
215 constexpr DateTimeParts NeededParts = DateTimePart::Date | DateTimePart::Time;
216 const DateTimeParts got = hasFieldsFor(m_fields);
217 // Must have date and time (zone optional) and support what it has:
218 if (got.testFlags(NeededParts))
219 return supports(got, m_fields, m_baseYear.has_value());
221 }
222public:
223 bool isNull() const noexcept { return m_fields.isEmpty(); }
224 bool isValid() const noexcept
225 {
226 return dateTimeSupport() == QtTemporalPattern::SupportType::Clear;
227 }
228 void setLocale(const QLocale &loc) { m_locale = loc; }
229 const QLocale &locale() const noexcept { return m_locale; }
230
231 void setBaseYear(int centuryStart) { m_baseYear = centuryStart; }
232 void clearBaseYear() noexcept { m_baseYear = std::nullopt; }
233 std::optional<int> baseYear() const noexcept { return m_baseYear; }
234
235 void setCalendar(QCalendar cal) { m_calendar = cal; }
236 QCalendar calendar() const noexcept { return m_calendar; }
237
239 parse(QStringView text, const QDateTime &defaults = {}) const;
240 Q_CORE_EXPORT QString serialize(const QDateTime &datetime) const;
241
242 static Q_CORE_EXPORT QDateTimePattern fromQtFormat(QStringView format);
243 static
244 QDateTimePattern forLocale(const QLocale &locale,
245 QLocale::FormatType format = QLocale::LongFormat)
246 {
247 auto pat = fromQtFormat(locale.dateTimeFormat(format));
248 pat.setLocale(locale);
249 return pat;
250 }
251};
252
254{
256 QList<Field> m_fields;
257 QLocale m_locale;
258 explicit QTimePattern(const QList<Field> &fs) : m_fields(fs) {}
259
260 QtTemporalPattern::SupportType timeSupport() const noexcept
261 {
262 using namespace QtTemporalPattern;
263 return supports({DateTimePart::Time}, m_fields);
264 }
265public:
266 bool isNull() const noexcept { return m_fields.isEmpty(); }
267 bool isValid() const noexcept
268 {
269 return timeSupport() == QtTemporalPattern::SupportType::Clear;
270 }
271 void setLocale(const QLocale &loc) { m_locale = loc; }
272 const QLocale &locale() const noexcept { return m_locale; }
273
275 parse(QStringView text, QTime defaults = {}) const;
276 Q_CORE_EXPORT QString serialize(const QTime &time) const;
277
278 static Q_CORE_EXPORT QTimePattern fromQtFormat(QStringView format);
279 static
280 QTimePattern forLocale(const QLocale &locale, QLocale::FormatType format = QLocale::LongFormat)
281 {
282 auto pat = fromQtFormat(locale.timeFormat(format));
283 pat.setLocale(locale);
284 return pat;
285 }
286};
287
289{
291 QList<Field> m_fields;
292 QLocale m_locale;
293 QCalendar m_calendar;
294 std::optional<int> m_baseYear;
295 explicit QDatePattern(const QList<Field> &fs) : m_fields(fs) {}
296 explicit QDatePattern(const QList<Field> &fs, int centuryStart)
297 : m_fields(fs), m_baseYear(centuryStart) {}
298
299 QtTemporalPattern::SupportType dateSupport() const noexcept
300 {
301 using namespace QtTemporalPattern;
302 return supports({DateTimePart::Date}, m_fields, m_baseYear.has_value());
303 }
304public:
305 bool isNull() const noexcept { return m_fields.isEmpty(); }
306 bool isValid() const noexcept
307 {
308 return dateSupport() == QtTemporalPattern::SupportType::Clear;
309 }
310 void setLocale(const QLocale &loc) { m_locale = loc; }
311 const QLocale &locale() const noexcept { return m_locale; }
312
313 void setBaseYear(int centuryStart) { m_baseYear = centuryStart; }
314 void clearBaseYear() noexcept { m_baseYear = std::nullopt; }
315 std::optional<int> baseYear() const noexcept { return m_baseYear; }
316
317 void setCalendar(QCalendar cal) { m_calendar = cal; }
318 QCalendar calendar() const noexcept { return m_calendar; }
319
321 parse(QStringView text, QDate defaults = {}) const;
322 Q_CORE_EXPORT QString serialize(const QDate &date) const;
323
324 static Q_CORE_EXPORT QDatePattern fromQtFormat(QStringView format);
325 static
326 QDatePattern forLocale(const QLocale &locale, QLocale::FormatType format = QLocale::LongFormat)
327 {
328 auto pat = fromQtFormat(locale.dateFormat(format));
329 pat.setLocale(locale);
330 return pat;
331 }
332};
333
334QT_END_NAMESPACE
335
336#endif // QTTEMPORALPATTERN_P_H
A description of a serialization format for a date.
void setBaseYear(int centuryStart)
const QLocale & locale() const noexcept
Returns the current locale in use by this pattern.
QCalendar calendar() const noexcept
Returns the current calendar in use by this pattern.
bool isValid() const noexcept
bool isNull() const noexcept
Returns true if this pattern has no fields, otherwise false.
static QDatePattern forLocale(const QLocale &locale, QLocale::FormatType format=QLocale::LongFormat)
Construct a QDatePattern appropriate to the given locale.
void setCalendar(QCalendar cal)
void setLocale(const QLocale &loc)
void clearBaseYear() noexcept
std::optional< int > baseYear() const noexcept
A description of a serialization format for a datetime.
bool isValid() const noexcept
void clearBaseYear() noexcept
void setBaseYear(int centuryStart)
QCalendar calendar() const noexcept
Returns the current calendar in use by this pattern.
bool isNull() const noexcept
Returns true if this pattern has no fields, otherwise false.
void setCalendar(QCalendar cal)
static QDateTimePattern forLocale(const QLocale &locale, QLocale::FormatType format=QLocale::LongFormat)
Construct a QDateTimePattern appropriate to the given locale.
std::optional< int > baseYear() const noexcept
void setLocale(const QLocale &loc)
const QLocale & locale() const noexcept
Returns the current locale in use by this pattern.
A description of a serialization format for a time.
void setLocale(const QLocale &loc)
bool isValid() const noexcept
static QTimePattern forLocale(const QLocale &locale, QLocale::FormatType format=QLocale::LongFormat)
Construct a QTimePattern appropriate to the given locale.
bool isNull() const noexcept
Returns true if this pattern has no fields, otherwise false.
const QLocale & locale() const noexcept
Returns the current locale in use by this pattern.
Supporting types and functions for temporal patterns.
constexpr auto EndTemporalFieldCategories
DateTimeParts hasFieldsFor(QSpan< const TemporalField > range)
Identify the parts to which the given fields contribute data.
QT_REQUIRE_CONFIG(datestring)