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