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
qdatetimeparser_p.h
Go to the documentation of this file.
1// Copyright (C) 2021 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
4#ifndef QDATETIMEPARSER_P_H
5#define QDATETIMEPARSER_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/private/qglobal_p.h>
19#include "qplatformdefs.h"
20#include "QtCore/qatomic.h"
21#include "QtCore/qcalendar.h"
22#include "QtCore/qcoreapplication.h"
23#include "QtCore/qdatetime.h"
24#include "QtCore/qlist.h"
25#include "QtCore/qlocale.h"
26#include "QtCore/qstringlist.h"
27#include "QtCore/qtimezone.h"
28#ifndef QT_BOOTSTRAPPED
29# include "QtCore/qvariant.h"
30#endif
31
33
34#define QDATETIMEEDIT_TIME_MIN QTime(0, 0) // Prefer QDate::startOfDay()
35#define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999) // Prefer QDate::endOfDay()
36#define QDATETIMEEDIT_DATE_MIN QDate(100, 1, 1)
37#define QDATETIMEEDIT_COMPAT_DATE_MIN QDate(1752, 9, 14)
38#define QDATETIMEEDIT_DATE_MAX QDate(9999, 12, 31)
39#define QDATETIMEEDIT_DATE_INITIAL QDate(2000, 1, 1)
40
42
44{
45public:
46 enum Context {
47 FromString,
48 DateTimeEdit
49 };
50 QDateTimeParser(QMetaType::Type t, Context ctx, QCalendar cal = QCalendar())
51 : defaultLocale(QLocale::system()), parserType(t), context(ctx), calendar(cal)
52 {
53 }
54 virtual ~QDateTimeParser();
55
56 enum Section {
57 NoSection = 0x00000,
58 AmPmSection = 0x00001,
59 MSecSection = 0x00002,
60 SecondSection = 0x00004,
61 MinuteSection = 0x00008,
62 Hour12Section = 0x00010,
63 Hour24Section = 0x00020,
64 TimeZoneSection = 0x00040,
65 HourSectionMask = (Hour12Section | Hour24Section),
66 TimeSectionMask = (MSecSection | SecondSection | MinuteSection |
67 HourSectionMask | AmPmSection | TimeZoneSection),
68
69 DaySection = 0x00100,
70 MonthSection = 0x00200,
71 YearSection = 0x00400,
72 YearSection2Digits = 0x00800,
73 YearSectionMask = YearSection | YearSection2Digits,
74 DayOfWeekSectionShort = 0x01000,
75 DayOfWeekSectionLong = 0x02000,
76 DayOfWeekSectionMask = DayOfWeekSectionShort | DayOfWeekSectionLong,
77 DaySectionMask = DaySection | DayOfWeekSectionMask,
78 DateSectionMask = DaySectionMask | MonthSection | YearSectionMask,
79
80 Internal = 0x10000,
81 FirstSection = 0x20000 | Internal,
82 LastSection = 0x40000 | Internal,
83 CalendarPopupSection = 0x80000 | Internal,
84 }; // extending qdatetimeedit.h's equivalent
85 Q_DECLARE_FLAGS(Sections, Section)
86
87 static constexpr int NoSectionIndex = -1;
88 static constexpr int FirstSectionIndex = -2;
89 static constexpr int LastSectionIndex = -3;
90
91 struct Q_CORE_EXPORT SectionNode
92 {
93 constexpr SectionNode(Section tp, int ps, int ct, int zs = 0)
94 : type(tp), pos(ps), count(ct), zeroesAdded(zs) {}
95 Section type;
96 mutable int pos;
97 int count; // (used as Case(count) indicator for AmPmSection)
98 int zeroesAdded;
99
100 static QString name(Section s);
101 QString name() const { return name(type); }
102 QString format() const;
103 int maxChange() const;
104 };
105
106 enum State { // duplicated from QValidator
107 Invalid,
108 Intermediate,
109 Acceptable
110 };
111
112 struct StateNode {
113 StateNode() : state(Invalid), padded(0), conflicts(false) {}
114 StateNode(const QDateTime &val, State ok=Acceptable, int pad=0, bool bad=false)
115 : value(val), state(ok), padded(pad), conflicts(bad) {}
116 QDateTime value;
117 State state;
118 int padded;
119 bool conflicts;
120 };
121
122 enum AmPm {
123 AmText,
124 PmText
125 };
126
127 StateNode parse(const QString &input, int position,
128 const QDateTime &defaultValue, bool fixup) const;
129 bool fromString(const QString &text, QDate *date, QTime *time,
130 int baseYear = QLocale::DefaultTwoDigitBaseYear) const;
131 bool fromString(const QString &text, QDateTime *datetime, int baseYear) const;
132 bool parseFormat(QStringView format);
133
134 enum FieldInfoFlag {
135 Numeric = 0x01,
136 FixedWidth = 0x02,
137 AllowPartial = 0x04,
138 Fraction = 0x08
139 };
140 Q_DECLARE_FLAGS(FieldInfo, FieldInfoFlag)
141
142 FieldInfo fieldInfo(int index) const;
143
144 void setDefaultLocale(const QLocale &loc) { defaultLocale = loc; }
145 virtual QString displayText() const { return m_text; }
146 void setCalendar(QCalendar calendar);
147
148private:
149 int sectionMaxSize(Section s, int count) const;
150 QString sectionText(const QString &text, int sectionIndex, int index) const;
151 StateNode scanString(const QDateTime &defaultValue, bool fixup) const;
152 struct ParsedSection {
153 int value;
154 int used;
155 int zeroes;
156 State state;
157 constexpr ParsedSection(State ok = Invalid,
158 int val = 0, int read = 0, int zs = 0)
159 : value(ok == Invalid ? -1 : val), used(read), zeroes(zs), state(ok)
160 {}
161 };
162 ParsedSection parseSection(const QDateTime &currentValue, int sectionIndex, int offset) const;
163 int findMonth(QStringView str, int monthstart, int sectionIndex,
164 int year, QString *monthName = nullptr, int *used = nullptr) const;
165 int findDay(QStringView str, int intDaystart, int sectionIndex,
166 QString *dayName = nullptr, int *used = nullptr) const;
167 ParsedSection findUtcOffset(QStringView str, int mode) const;
168 ParsedSection findTimeZoneName(QStringView str, const QDateTime &when) const;
169 ParsedSection findTimeZone(QStringView str, const QDateTime &when,
170 int maxVal, int minVal, int mode) const;
171
172 enum AmPmFinder {
173 Neither = -1,
174 AM = 0,
175 PM = 1,
176 PossibleAM = 2,
177 PossiblePM = 3,
178 PossibleBoth = 4
179 };
180 AmPmFinder findAmPm(QString &str, int index, int *used = nullptr) const;
181
182 bool potentialValue(QStringView str, int min, int max, int index,
183 const QDateTime &currentValue, int insert) const;
184 bool potentialValue(const QString &str, int min, int max, int index,
185 const QDateTime &currentValue, int insert) const
186 {
187 return potentialValue(QStringView(str), min, max, index, currentValue, insert);
188 }
189
190 enum Case {
191 NativeCase,
192 LowerCase,
193 UpperCase
194 };
195
196 QString getAmPmText(AmPm ap, Case cs) const;
197 QDateTime baseDate(const QTimeZone &zone) const;
198
199 friend class QDTPUnitTestParser;
200
201protected: // for the benefit of QDateTimeEditPrivate
202 int sectionSize(int index) const;
203 int sectionMaxSize(int index) const;
204 int sectionPos(int index) const;
205 int sectionPos(SectionNode sn) const;
206
207 const SectionNode &sectionNode(int index) const;
208 Section sectionType(int index) const;
209 QString sectionText(int sectionIndex) const;
210 int getDigit(const QDateTime &dt, int index) const;
211 bool setDigit(QDateTime &t, int index, int newval) const;
212
213 int absoluteMax(int index, const QDateTime &value = QDateTime()) const;
214 int absoluteMin(int index) const;
215
216 bool skipToNextSection(int section, const QDateTime &current, QStringView sectionText) const;
217 bool skipToNextSection(int section, const QDateTime &current, const QString &sectionText) const
218 {
219 return skipToNextSection(section, current, QStringView(sectionText));
220 }
221 QString stateName(State s) const;
222
223 virtual QDateTime getMinimum(const QTimeZone &zone) const;
224 virtual QDateTime getMaximum(const QTimeZone &zone) const;
225 virtual int cursorPosition() const { return -1; }
226 virtual QLocale locale() const { return defaultLocale; }
227
228 mutable int currentSectionIndex = int(NoSectionIndex);
229 mutable int defaultCenturyStart = QLocale::DefaultTwoDigitBaseYear;
230 Sections display;
231 /*
232 This stores the most recently selected day.
233 It is useful when considering the following scenario:
234
235 1. Date is: 31/01/2000
236 2. User increments month: 29/02/2000
237 3. User increments month: 31/03/2000
238
239 At step 1, cachedDay stores 31. At step 2, the 31 is invalid for February, so the cachedDay is not updated.
240 At step 3, the month is changed to March, for which 31 is a valid day. Since 29 < 31, the day is set to cachedDay.
241 This is good for when users have selected their desired day and are scrolling up or down in the month or year section
242 and do not want smaller months (or non-leap years) to alter the day that they chose.
243 */
244 mutable int cachedDay = -1;
245 mutable QString m_text;
246 QList<SectionNode> sectionNodes;
247 QStringList separators;
248 QString displayFormat;
249 QLocale defaultLocale;
250 QMetaType::Type parserType;
251 bool fixday = false;
252 Context context;
253 QCalendar calendar;
254};
255Q_DECLARE_TYPEINFO(QDateTimeParser::SectionNode, Q_PRIMITIVE_TYPE);
256
257Q_CORE_EXPORT bool operator==(QDateTimeParser::SectionNode s1, QDateTimeParser::SectionNode s2);
258
259Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::Sections)
260Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::FieldInfo)
261
262QT_END_NAMESPACE
263
264#endif // QDATETIME_P_H
bool operator==(QDateTimeParser::SectionNode s1, QDateTimeParser::SectionNode s2)
QT_REQUIRE_CONFIG(datetimeparser)