/usr/include/QtCore/qdatetime.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (C) 2021 The Qt Company Ltd. |
2 | | // Copyright (C) 2021 Intel Corporation. |
3 | | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | | |
5 | | #ifndef QDATETIME_H |
6 | | #define QDATETIME_H |
7 | | |
8 | | #include <QtCore/qcalendar.h> |
9 | | #include <QtCore/qcompare.h> |
10 | | #include <QtCore/qlocale.h> |
11 | | #include <QtCore/qnamespace.h> |
12 | | #include <QtCore/qshareddata.h> |
13 | | #include <QtCore/qstring.h> |
14 | | |
15 | | #include <limits> |
16 | | #include <chrono> |
17 | | |
18 | | #if defined(Q_OS_DARWIN) || defined(Q_QDOC) |
19 | | Q_FORWARD_DECLARE_CF_TYPE(CFDate); |
20 | | Q_FORWARD_DECLARE_OBJC_CLASS(NSDate); |
21 | | #endif |
22 | | |
23 | | QT_BEGIN_NAMESPACE |
24 | | |
25 | | class QTimeZone; |
26 | | class QDateTime; |
27 | | |
28 | | class Q_CORE_EXPORT QDate |
29 | | { |
30 | | explicit constexpr QDate(qint64 julianDay) : jd(julianDay) {} |
31 | | public: |
32 | | constexpr QDate() : jd(nullJd()) {} |
33 | | QDate(int y, int m, int d); |
34 | | QDate(int y, int m, int d, QCalendar cal); |
35 | | // INTEGRITY incident-85878 (timezone and clock_cast are not supported) |
36 | | #if (__cpp_lib_chrono >= 201907L && !defined(Q_OS_INTEGRITY)) || defined(Q_QDOC) |
37 | | QT_POST_CXX17_API_IN_EXPORTED_CLASS |
38 | | Q_IMPLICIT constexpr QDate(std::chrono::year_month_day date) noexcept |
39 | | : jd(date.ok() ? stdSysDaysToJulianDay(date) : nullJd()) |
40 | | {} |
41 | | |
42 | | QT_POST_CXX17_API_IN_EXPORTED_CLASS |
43 | | Q_IMPLICIT constexpr QDate(std::chrono::year_month_day_last date) noexcept |
44 | | : jd(date.ok() ? stdSysDaysToJulianDay(date) : nullJd()) |
45 | | {} |
46 | | |
47 | | QT_POST_CXX17_API_IN_EXPORTED_CLASS |
48 | | Q_IMPLICIT constexpr QDate(std::chrono::year_month_weekday date) noexcept |
49 | | : jd(date.ok() ? stdSysDaysToJulianDay(date) : nullJd()) |
50 | | {} |
51 | | |
52 | | QT_POST_CXX17_API_IN_EXPORTED_CLASS |
53 | | Q_IMPLICIT constexpr QDate(std::chrono::year_month_weekday_last date) noexcept |
54 | | : jd(date.ok() ? stdSysDaysToJulianDay(date) : nullJd()) |
55 | | {} |
56 | | |
57 | | QT_POST_CXX17_API_IN_EXPORTED_CLASS |
58 | | static constexpr QDate fromStdSysDays(const std::chrono::sys_days &days) noexcept |
59 | | { |
60 | | return QDate(stdSysDaysToJulianDay(days)); |
61 | | } |
62 | | |
63 | | QT_POST_CXX17_API_IN_EXPORTED_CLASS |
64 | | constexpr std::chrono::sys_days toStdSysDays() const noexcept |
65 | | { |
66 | | const qint64 days = isValid() ? jd - unixEpochJd() : 0; |
67 | | return std::chrono::sys_days(std::chrono::days(days)); |
68 | | } |
69 | | #endif |
70 | | |
71 | | constexpr bool isNull() const { return !isValid(); } |
72 | | constexpr bool isValid() const { return jd >= minJd() && jd <= maxJd(); } |
73 | | |
74 | | // Gregorian-optimized: |
75 | | int year() const; |
76 | | int month() const; |
77 | | int day() const; |
78 | | int dayOfWeek() const; |
79 | | int dayOfYear() const; |
80 | | int daysInMonth() const; |
81 | | int daysInYear() const; |
82 | | int weekNumber(int *yearNum = nullptr) const; // ISO 8601, always Gregorian |
83 | | |
84 | | int year(QCalendar cal) const; |
85 | | int month(QCalendar cal) const; |
86 | | int day(QCalendar cal) const; |
87 | | int dayOfWeek(QCalendar cal) const; |
88 | | int dayOfYear(QCalendar cal) const; |
89 | | int daysInMonth(QCalendar cal) const; |
90 | | int daysInYear(QCalendar cal) const; |
91 | | |
92 | | #if QT_DEPRECATED_SINCE(6, 9) |
93 | | QT_DEPRECATED_VERSION_X_6_9("Pass QTimeZone instead") |
94 | | QDateTime startOfDay(Qt::TimeSpec spec, int offsetSeconds = 0) const; |
95 | | QT_DEPRECATED_VERSION_X_6_9("Pass QTimeZone instead") |
96 | | QDateTime endOfDay(Qt::TimeSpec spec, int offsetSeconds = 0) const; |
97 | | #endif |
98 | | |
99 | | QDateTime startOfDay(const QTimeZone &zone) const; |
100 | | QDateTime endOfDay(const QTimeZone &zone) const; |
101 | | QDateTime startOfDay() const; |
102 | | QDateTime endOfDay() const; |
103 | | |
104 | | #if QT_CONFIG(datestring) |
105 | | QString toString(Qt::DateFormat format = Qt::TextDate) const; |
106 | | QString toString(const QString &format) const; |
107 | | QString toString(const QString &format, QCalendar cal) const |
108 | 0 | { return toString(qToStringViewIgnoringNull(format), cal); } |
109 | | QString toString(QStringView format) const; |
110 | | QString toString(QStringView format, QCalendar cal) const; |
111 | | #endif |
112 | | bool setDate(int year, int month, int day); // Gregorian-optimized |
113 | | bool setDate(int year, int month, int day, QCalendar cal); |
114 | | |
115 | | void getDate(int *year, int *month, int *day) const; |
116 | | |
117 | | [[nodiscard]] QDate addDays(qint64 days) const; |
118 | | // INTEGRITY incident-85878 (timezone and clock_cast are not supported) |
119 | | #if (__cpp_lib_chrono >= 201907L && !defined(Q_OS_INTEGRITY)) || defined(Q_QDOC) |
120 | | QT_POST_CXX17_API_IN_EXPORTED_CLASS |
121 | | [[nodiscard]] QDate addDuration(std::chrono::days days) const |
122 | | { |
123 | | return addDays(days.count()); |
124 | | } |
125 | | #endif |
126 | | // Gregorian-optimized: |
127 | | [[nodiscard]] QDate addMonths(int months) const; |
128 | | [[nodiscard]] QDate addYears(int years) const; |
129 | | [[nodiscard]] QDate addMonths(int months, QCalendar cal) const; |
130 | | [[nodiscard]] QDate addYears(int years, QCalendar cal) const; |
131 | | qint64 daysTo(QDate d) const; |
132 | | |
133 | | static QDate currentDate(); |
134 | | #if QT_CONFIG(datestring) |
135 | | // No DateFormat accepts a two-digit year, so no need for baseYear: |
136 | | static QDate fromString(QStringView string, Qt::DateFormat format = Qt::TextDate); |
137 | | static QDate fromString(const QString &string, Qt::DateFormat format = Qt::TextDate) |
138 | | { return fromString(qToStringViewIgnoringNull(string), format); } |
139 | | |
140 | | // Accept calendar without over-ride of base year: |
141 | | static QDate fromString(QStringView string, QStringView format, QCalendar cal) |
142 | 0 | { return fromString(string.toString(), format, QLocale::DefaultTwoDigitBaseYear, cal); } |
143 | | QT_CORE_INLINE_SINCE(6, 7) |
144 | | static QDate fromString(const QString &string, QStringView format, QCalendar cal); |
145 | | static QDate fromString(const QString &string, const QString &format, QCalendar cal) |
146 | 0 | { return fromString(string, qToStringViewIgnoringNull(format), QLocale::DefaultTwoDigitBaseYear, cal); } |
147 | | |
148 | | // Overriding base year is likely more common than overriding calendar (and |
149 | | // likely to get more so, as the legacy base drops ever further behind us). |
150 | | static QDate fromString(QStringView string, QStringView format, |
151 | | int baseYear = QLocale::DefaultTwoDigitBaseYear) |
152 | 0 | { return fromString(string.toString(), format, baseYear); } |
153 | | static QDate fromString(QStringView string, QStringView format, |
154 | | int baseYear, QCalendar cal) |
155 | 0 | { return fromString(string.toString(), format, baseYear, cal); } |
156 | | static QDate fromString(const QString &string, QStringView format, |
157 | | int baseYear = QLocale::DefaultTwoDigitBaseYear); |
158 | | static QDate fromString(const QString &string, QStringView format, |
159 | | int baseYear, QCalendar cal); |
160 | | static QDate fromString(const QString &string, const QString &format, |
161 | | int baseYear = QLocale::DefaultTwoDigitBaseYear) |
162 | 0 | { return fromString(string, qToStringViewIgnoringNull(format), baseYear); } |
163 | | static QDate fromString(const QString &string, const QString &format, |
164 | | int baseYear, QCalendar cal) |
165 | 0 | { return fromString(string, qToStringViewIgnoringNull(format), baseYear, cal); } |
166 | | #endif |
167 | | static bool isValid(int y, int m, int d); |
168 | | static bool isLeapYear(int year); |
169 | | |
170 | | static constexpr inline QDate fromJulianDay(qint64 jd_) |
171 | | { return jd_ >= minJd() && jd_ <= maxJd() ? QDate(jd_) : QDate() ; } |
172 | | constexpr inline qint64 toJulianDay() const { return jd; } |
173 | | |
174 | | private: |
175 | | // using extra parentheses around min to avoid expanding it if it is a macro |
176 | | static constexpr inline qint64 nullJd() { return (std::numeric_limits<qint64>::min)(); } |
177 | | static constexpr inline qint64 minJd() { return Q_INT64_C(-784350574879); } |
178 | | static constexpr inline qint64 maxJd() { return Q_INT64_C( 784354017364); } |
179 | 0 | static constexpr inline qint64 unixEpochJd() { return Q_INT64_C(2440588); } |
180 | | |
181 | | // INTEGRITY incident-85878 (timezone and clock_cast are not supported) |
182 | | #if __cpp_lib_chrono >= 201907L && !defined(Q_OS_INTEGRITY) |
183 | | #if !QT_CORE_REMOVED_SINCE(6, 7) |
184 | | QT_POST_CXX17_API_IN_EXPORTED_CLASS |
185 | | #endif |
186 | | static constexpr qint64 |
187 | | stdSysDaysToJulianDay(const std::chrono::sys_days &days) noexcept |
188 | | { |
189 | | const auto epochDays = days.time_since_epoch().count(); |
190 | | // minJd() and maxJd() fit into 40 bits. |
191 | | if constexpr (sizeof(epochDays) * CHAR_BIT >= 41) { |
192 | | constexpr auto top = maxJd() - unixEpochJd(); |
193 | | constexpr auto bottom = minJd() - unixEpochJd(); |
194 | | if (epochDays > top || epochDays < bottom) |
195 | | return nullJd(); |
196 | | } |
197 | | return unixEpochJd() + epochDays; |
198 | | } |
199 | | #endif // __cpp_lib_chrono >= 201907L |
200 | | |
201 | | qint64 jd; |
202 | | |
203 | | friend class QDateTime; |
204 | | friend class QDateTimeParser; |
205 | | friend class QDateTimePrivate; |
206 | | |
207 | | friend constexpr bool comparesEqual(const QDate &lhs, const QDate &rhs) noexcept |
208 | | { return lhs.jd == rhs.jd; } |
209 | | friend constexpr Qt::strong_ordering |
210 | | compareThreeWay(const QDate &lhs, const QDate &rhs) noexcept |
211 | | { return Qt::compareThreeWay(lhs.jd, rhs.jd); } |
212 | | Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QDate) |
213 | | |
214 | | #ifndef QT_NO_DATASTREAM |
215 | | friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, QDate); |
216 | | friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDate &); |
217 | | #endif |
218 | | }; |
219 | | Q_DECLARE_TYPEINFO(QDate, Q_RELOCATABLE_TYPE); |
220 | | |
221 | | class Q_CORE_EXPORT QTime |
222 | | { |
223 | | explicit constexpr QTime(int ms) : mds(ms) |
224 | | {} |
225 | | public: |
226 | | constexpr QTime(): mds(NullTime) |
227 | | {} |
228 | | QTime(int h, int m, int s = 0, int ms = 0); |
229 | | |
230 | | constexpr bool isNull() const { return mds == NullTime; } |
231 | | bool isValid() const; |
232 | | |
233 | | int hour() const; |
234 | | int minute() const; |
235 | | int second() const; |
236 | | int msec() const; |
237 | | #if QT_CONFIG(datestring) |
238 | | QString toString(Qt::DateFormat f = Qt::TextDate) const; |
239 | | QString toString(const QString &format) const |
240 | 0 | { return toString(qToStringViewIgnoringNull(format)); } |
241 | | QString toString(QStringView format) const; |
242 | | #endif |
243 | | bool setHMS(int h, int m, int s, int ms = 0); |
244 | | |
245 | | [[nodiscard]] QTime addSecs(int secs) const; |
246 | | int secsTo(QTime t) const; |
247 | | [[nodiscard]] QTime addMSecs(int ms) const; |
248 | | int msecsTo(QTime t) const; |
249 | | |
250 | | static constexpr inline QTime fromMSecsSinceStartOfDay(int msecs) { return QTime(msecs); } |
251 | | constexpr inline int msecsSinceStartOfDay() const { return mds == NullTime ? 0 : mds; } |
252 | | |
253 | | static QTime currentTime(); |
254 | | #if QT_CONFIG(datestring) |
255 | | static QTime fromString(QStringView string, Qt::DateFormat format = Qt::TextDate); |
256 | | static QTime fromString(QStringView string, QStringView format) |
257 | 0 | { return fromString(string.toString(), format); } |
258 | | static QTime fromString(const QString &string, QStringView format); |
259 | | static QTime fromString(const QString &string, Qt::DateFormat format = Qt::TextDate) |
260 | | { return fromString(qToStringViewIgnoringNull(string), format); } |
261 | | static QTime fromString(const QString &string, const QString &format) |
262 | 0 | { return fromString(string, qToStringViewIgnoringNull(format)); } |
263 | | #endif |
264 | | static bool isValid(int h, int m, int s, int ms = 0); |
265 | | |
266 | | private: |
267 | | enum TimeFlag { NullTime = -1 }; |
268 | | constexpr inline int ds() const { return mds == -1 ? 0 : mds; } |
269 | | int mds; |
270 | | |
271 | | friend constexpr bool comparesEqual(const QTime &lhs, const QTime &rhs) noexcept |
272 | | { return lhs.mds == rhs.mds; } |
273 | | friend constexpr Qt::strong_ordering |
274 | | compareThreeWay(const QTime &lhs, const QTime &rhs) noexcept |
275 | | { return Qt::compareThreeWay(lhs.mds, rhs.mds); } |
276 | | Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QTime) |
277 | | |
278 | | friend class QDateTime; |
279 | | friend class QDateTimePrivate; |
280 | | #ifndef QT_NO_DATASTREAM |
281 | | friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, QTime); |
282 | | friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QTime &); |
283 | | #endif |
284 | | }; |
285 | | Q_DECLARE_TYPEINFO(QTime, Q_RELOCATABLE_TYPE); |
286 | | |
287 | | class QDateTimePrivate; |
288 | | |
289 | | class Q_CORE_EXPORT QDateTime |
290 | | { |
291 | | struct ShortData { |
292 | | #if QT_VERSION >= QT_VERSION_CHECK(7,0,0) || defined(QT_BOOTSTRAPPED) |
293 | | # if Q_BYTE_ORDER == Q_LITTLE_ENDIAN |
294 | | qint64 status : 8; |
295 | | # endif |
296 | | qint64 msecs : 56; |
297 | | |
298 | | # if Q_BYTE_ORDER == Q_BIG_ENDIAN |
299 | | qint64 status : 8; |
300 | | # endif |
301 | | #else |
302 | | # if Q_BYTE_ORDER == Q_LITTLE_ENDIAN |
303 | | quintptr status : 8; |
304 | | # endif |
305 | | // note: this is only 24 bits on 32-bit systems... |
306 | | qintptr msecs : sizeof(void *) * 8 - 8; |
307 | | |
308 | | # if Q_BYTE_ORDER == Q_BIG_ENDIAN |
309 | | quintptr status : 8; |
310 | | # endif |
311 | | #endif |
312 | | friend constexpr bool operator==(ShortData lhs, ShortData rhs) |
313 | | { return lhs.status == rhs.status && lhs.msecs == rhs.msecs; } |
314 | | }; |
315 | | |
316 | | union Data { |
317 | | // To be of any use, we need at least 60 years around 1970, which |
318 | | // is 1,893,456,000,000 ms. That requires 41 bits to store, plus |
319 | | // the sign bit. With the status byte, the minimum size is 50 bits. |
320 | | static constexpr bool CanBeSmall = sizeof(ShortData) * 8 > 50; |
321 | | |
322 | | Data() noexcept; |
323 | | Data(const QTimeZone &); |
324 | | Data(const Data &other) noexcept; |
325 | | Data(Data &&other) noexcept; |
326 | | Data &operator=(const Data &other) noexcept; |
327 | 0 | Data &operator=(Data &&other) noexcept { swap(other); return *this; } |
328 | | ~Data(); |
329 | | |
330 | | void swap(Data &other) noexcept |
331 | 2.32k | { std::swap(data, other.data); } |
332 | | |
333 | | bool isShort() const; |
334 | | inline void invalidate(); |
335 | | void detach(); |
336 | | QTimeZone timeZone() const; |
337 | | |
338 | | const QDateTimePrivate *operator->() const; |
339 | | QDateTimePrivate *operator->(); |
340 | | |
341 | | QDateTimePrivate *d; |
342 | | ShortData data; |
343 | | }; |
344 | | |
345 | | public: |
346 | | QDateTime() noexcept; |
347 | | |
348 | | enum class TransitionResolution { |
349 | | Reject = 0, |
350 | | RelativeToBefore, |
351 | | RelativeToAfter, |
352 | | PreferBefore, |
353 | | PreferAfter, |
354 | | PreferStandard, |
355 | | PreferDaylightSaving, |
356 | | // Closest match to behavior prior to introducing TransitionResolution: |
357 | | LegacyBehavior = RelativeToBefore |
358 | | }; |
359 | | |
360 | | #if QT_DEPRECATED_SINCE(6, 9) |
361 | | QT_DEPRECATED_VERSION_X_6_9("Pass QTimeZone instead") |
362 | | QDateTime(QDate date, QTime time, Qt::TimeSpec spec, int offsetSeconds = 0); |
363 | | #endif |
364 | | #if QT_CORE_REMOVED_SINCE(6, 7) |
365 | | QDateTime(QDate date, QTime time, const QTimeZone &timeZone); |
366 | | QDateTime(QDate date, QTime time); |
367 | | #endif |
368 | | QDateTime(QDate date, QTime time, const QTimeZone &timeZone, |
369 | | TransitionResolution resolve = TransitionResolution::LegacyBehavior); |
370 | | QDateTime(QDate date, QTime time, |
371 | | TransitionResolution resolve = TransitionResolution::LegacyBehavior); |
372 | | QDateTime(const QDateTime &other) noexcept; |
373 | | QDateTime(QDateTime &&other) noexcept; |
374 | | ~QDateTime(); |
375 | | |
376 | | QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QDateTime) |
377 | | QDateTime &operator=(const QDateTime &other) noexcept; |
378 | | |
379 | 2.32k | void swap(QDateTime &other) noexcept { d.swap(other.d); } |
380 | | |
381 | | bool isNull() const; |
382 | | bool isValid() const; |
383 | | |
384 | | QDate date() const; |
385 | | QTime time() const; |
386 | | Qt::TimeSpec timeSpec() const; |
387 | | int offsetFromUtc() const; |
388 | | QTimeZone timeRepresentation() const; |
389 | | #if QT_CONFIG(timezone) |
390 | | QTimeZone timeZone() const; |
391 | | #endif // timezone |
392 | | QString timeZoneAbbreviation() const; |
393 | | bool isDaylightTime() const; |
394 | | |
395 | | qint64 toMSecsSinceEpoch() const; |
396 | | qint64 toSecsSinceEpoch() const; |
397 | | |
398 | | #if QT_CORE_REMOVED_SINCE(6, 7) |
399 | | void setDate(QDate date); |
400 | | void setTime(QTime time); |
401 | | #endif |
402 | | void setDate(QDate date, TransitionResolution resolve = TransitionResolution::LegacyBehavior); |
403 | | void setTime(QTime time, TransitionResolution resolve = TransitionResolution::LegacyBehavior); |
404 | | |
405 | | #if QT_DEPRECATED_SINCE(6, 9) |
406 | | QT_DEPRECATED_VERSION_X_6_9("Use setTimeZone() instead") |
407 | | void setTimeSpec(Qt::TimeSpec spec); |
408 | | QT_DEPRECATED_VERSION_X_6_9("Use setTimeZone() instead") |
409 | | void setOffsetFromUtc(int offsetSeconds); |
410 | | #endif |
411 | | #if QT_CORE_REMOVED_SINCE(6, 7) |
412 | | void setTimeZone(const QTimeZone &toZone); |
413 | | #endif |
414 | | void setTimeZone(const QTimeZone &toZone, |
415 | | TransitionResolution resolve = TransitionResolution::LegacyBehavior); |
416 | | void setMSecsSinceEpoch(qint64 msecs); |
417 | | void setSecsSinceEpoch(qint64 secs); |
418 | | |
419 | | #if QT_CONFIG(datestring) |
420 | | QString toString(Qt::DateFormat format = Qt::TextDate) const; |
421 | | QString toString(const QString &format) const; |
422 | | QString toString(const QString &format, QCalendar cal) const |
423 | 0 | { return toString(qToStringViewIgnoringNull(format), cal); } |
424 | | QString toString(QStringView format) const; |
425 | | QString toString(QStringView format, QCalendar cal) const; |
426 | | #endif |
427 | | [[nodiscard]] QDateTime addDays(qint64 days) const; |
428 | | [[nodiscard]] QDateTime addMonths(int months) const; |
429 | | [[nodiscard]] QDateTime addYears(int years) const; |
430 | | [[nodiscard]] QDateTime addSecs(qint64 secs) const; |
431 | | [[nodiscard]] QDateTime addMSecs(qint64 msecs) const; |
432 | | [[nodiscard]] QDateTime addDuration(std::chrono::milliseconds msecs) const |
433 | 0 | { |
434 | 0 | return addMSecs(msecs.count()); |
435 | 0 | } |
436 | | |
437 | | #if QT_DEPRECATED_SINCE(6, 9) |
438 | | QT_DEPRECATED_VERSION_X_6_9("Use toTimeZone instead") |
439 | | QDateTime toTimeSpec(Qt::TimeSpec spec) const; |
440 | | #endif |
441 | | QDateTime toLocalTime() const; |
442 | | QDateTime toUTC() const; |
443 | | QDateTime toOffsetFromUtc(int offsetSeconds) const; |
444 | | QDateTime toTimeZone(const QTimeZone &toZone) const; |
445 | | |
446 | | qint64 daysTo(const QDateTime &) const; |
447 | | qint64 secsTo(const QDateTime &) const; |
448 | | qint64 msecsTo(const QDateTime &) const; |
449 | | |
450 | | static QDateTime currentDateTime(const QTimeZone &zone); |
451 | | static QDateTime currentDateTime(); |
452 | | static QDateTime currentDateTimeUtc(); |
453 | | #if QT_CONFIG(datestring) |
454 | | // No DateFormat accepts a two-digit year, so no need for baseYear: |
455 | | static QDateTime fromString(QStringView string, Qt::DateFormat format = Qt::TextDate); |
456 | | static QDateTime fromString(const QString &string, Qt::DateFormat format = Qt::TextDate) |
457 | 596 | { return fromString(qToStringViewIgnoringNull(string), format); } |
458 | | |
459 | | // Accept calendar without over-ride of base year: |
460 | | static QDateTime fromString(QStringView string, QStringView format, QCalendar cal) |
461 | 0 | { return fromString(string.toString(), format, QLocale::DefaultTwoDigitBaseYear, cal); } |
462 | | QT_CORE_INLINE_SINCE(6, 7) |
463 | | static QDateTime fromString(const QString &string, QStringView format, QCalendar cal); |
464 | | static QDateTime fromString(const QString &string, const QString &format, QCalendar cal) |
465 | 0 | { return fromString(string, qToStringViewIgnoringNull(format), QLocale::DefaultTwoDigitBaseYear, cal); } |
466 | | |
467 | | // Overriding base year is likely more common than overriding calendar (and |
468 | | // likely to get more so, as the legacy base drops ever further behind us). |
469 | | static QDateTime fromString(QStringView string, QStringView format, |
470 | | int baseYear = QLocale::DefaultTwoDigitBaseYear) |
471 | 0 | { return fromString(string.toString(), format, baseYear); } |
472 | | static QDateTime fromString(QStringView string, QStringView format, |
473 | | int baseYear, QCalendar cal) |
474 | 0 | { return fromString(string.toString(), format, baseYear, cal); } |
475 | | static QDateTime fromString(const QString &string, QStringView format, |
476 | | int baseYear = QLocale::DefaultTwoDigitBaseYear); |
477 | | static QDateTime fromString(const QString &string, QStringView format, |
478 | | int baseYear, QCalendar cal); |
479 | | static QDateTime fromString(const QString &string, const QString &format, |
480 | | int baseYear = QLocale::DefaultTwoDigitBaseYear) |
481 | 8.98k | { return fromString(string, qToStringViewIgnoringNull(format), baseYear); } |
482 | | static QDateTime fromString(const QString &string, const QString &format, |
483 | | int baseYear, QCalendar cal) |
484 | 0 | { return fromString(string, qToStringViewIgnoringNull(format), baseYear, cal); } |
485 | | #endif |
486 | | |
487 | | #if QT_DEPRECATED_SINCE(6, 9) |
488 | | QT_DEPRECATED_VERSION_X_6_9("Pass QTimeZone instead of time-spec, offset") |
489 | | static QDateTime fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec, int offsetFromUtc = 0); |
490 | | QT_DEPRECATED_VERSION_X_6_9("Pass QTimeZone instead of time-spec, offset") |
491 | | static QDateTime fromSecsSinceEpoch(qint64 secs, Qt::TimeSpec spec, int offsetFromUtc = 0); |
492 | | #endif |
493 | | |
494 | | static QDateTime fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone); |
495 | | static QDateTime fromSecsSinceEpoch(qint64 secs, const QTimeZone &timeZone); |
496 | | static QDateTime fromMSecsSinceEpoch(qint64 msecs); |
497 | | static QDateTime fromSecsSinceEpoch(qint64 secs); |
498 | | |
499 | | static qint64 currentMSecsSinceEpoch() noexcept; |
500 | | static qint64 currentSecsSinceEpoch() noexcept; |
501 | | |
502 | | #if defined(Q_OS_DARWIN) || defined(Q_QDOC) |
503 | | static QDateTime fromCFDate(CFDateRef date); |
504 | | CFDateRef toCFDate() const Q_DECL_CF_RETURNS_RETAINED; |
505 | | static QDateTime fromNSDate(const NSDate *date); |
506 | | NSDate *toNSDate() const Q_DECL_NS_RETURNS_AUTORELEASED; |
507 | | #endif |
508 | | |
509 | | static QDateTime fromStdTimePoint( |
510 | | std::chrono::time_point< |
511 | | std::chrono::system_clock, |
512 | | std::chrono::milliseconds |
513 | | > time |
514 | | ); |
515 | | |
516 | | // INTEGRITY incident-85878 (timezone and clock_cast are not supported) |
517 | | #if (__cpp_lib_chrono >= 201907L && !defined(Q_OS_INTEGRITY)) || defined(Q_QDOC) |
518 | | #if __cpp_concepts >= 201907L || defined(Q_QDOC) |
519 | | private: |
520 | | // The duration type of the result of a clock_cast<system_clock>. |
521 | | // This duration may differ from the duration of the input. |
522 | | template <typename Clock, typename Duration> |
523 | | using system_clock_cast_duration = decltype( |
524 | | std::chrono::clock_cast<std::chrono::system_clock>( |
525 | | std::declval<const std::chrono::time_point<Clock, Duration> &>() |
526 | | ).time_since_epoch() |
527 | | ); |
528 | | |
529 | | public: |
530 | | // Generic clock, as long as it's compatible with us (= system_clock) |
531 | | template <typename Clock, typename Duration> |
532 | | static QDateTime fromStdTimePoint(const std::chrono::time_point<Clock, Duration> &time) |
533 | | requires |
534 | | requires(const std::chrono::time_point<Clock, Duration> &t) { |
535 | | // the clock can be converted to system_clock |
536 | | std::chrono::clock_cast<std::chrono::system_clock>(t); |
537 | | // after the conversion to system_clock, the duration type |
538 | | // we get is convertible to milliseconds |
539 | | requires std::is_convertible_v< |
540 | | system_clock_cast_duration<Clock, Duration>, |
541 | | std::chrono::milliseconds |
542 | | >; |
543 | | } |
544 | | { |
545 | | using namespace std::chrono; |
546 | | const sys_time<milliseconds> sysTime = clock_cast<system_clock>(time); |
547 | | return fromStdTimePoint(sysTime); |
548 | | } |
549 | | #endif // __cpp_concepts |
550 | | |
551 | | // local_time |
552 | | QT_POST_CXX17_API_IN_EXPORTED_CLASS |
553 | | static QDateTime fromStdTimePoint(const std::chrono::local_time<std::chrono::milliseconds> &time) |
554 | | { |
555 | | return fromStdLocalTime(time); |
556 | | } |
557 | | |
558 | | QT_POST_CXX17_API_IN_EXPORTED_CLASS |
559 | | static QDateTime fromStdLocalTime(const std::chrono::local_time<std::chrono::milliseconds> &time) |
560 | | { |
561 | | QDateTime result(QDate(1970, 1, 1), QTime(0, 0, 0), TransitionResolution::LegacyBehavior); |
562 | | return result.addMSecs(time.time_since_epoch().count()); |
563 | | } |
564 | | |
565 | | #if QT_CONFIG(timezone) && (__cpp_lib_chrono >= 201907L || defined(Q_QDOC)) |
566 | | // zoned_time. defined in qtimezone.h |
567 | | QT_POST_CXX17_API_IN_EXPORTED_CLASS |
568 | | static QDateTime fromStdZonedTime(const std::chrono::zoned_time< |
569 | | std::chrono::milliseconds, |
570 | | const std::chrono::time_zone * |
571 | | > &time); |
572 | | #endif // QT_CONFIG(timezone) |
573 | | |
574 | | QT_POST_CXX17_API_IN_EXPORTED_CLASS |
575 | | std::chrono::sys_time<std::chrono::milliseconds> toStdSysMilliseconds() const |
576 | | { |
577 | | const std::chrono::milliseconds duration(toMSecsSinceEpoch()); |
578 | | return std::chrono::sys_time<std::chrono::milliseconds>(duration); |
579 | | } |
580 | | |
581 | | QT_POST_CXX17_API_IN_EXPORTED_CLASS |
582 | | std::chrono::sys_seconds toStdSysSeconds() const |
583 | | { |
584 | | const std::chrono::seconds duration(toSecsSinceEpoch()); |
585 | | return std::chrono::sys_seconds(duration); |
586 | | } |
587 | | #endif // __cpp_lib_chrono >= 201907L && !Q_OS_INTEGRITY |
588 | | |
589 | | friend std::chrono::milliseconds operator-(const QDateTime &lhs, const QDateTime &rhs) |
590 | 0 | { |
591 | 0 | return std::chrono::milliseconds(rhs.msecsTo(lhs)); |
592 | 0 | } |
593 | | |
594 | | friend QDateTime operator+(const QDateTime &dateTime, std::chrono::milliseconds duration) |
595 | 0 | { |
596 | 0 | return dateTime.addMSecs(duration.count()); |
597 | 0 | } |
598 | | |
599 | | friend QDateTime operator+(std::chrono::milliseconds duration, const QDateTime &dateTime) |
600 | 0 | { |
601 | 0 | return dateTime + duration; |
602 | 0 | } |
603 | | |
604 | | QDateTime &operator+=(std::chrono::milliseconds duration) |
605 | 0 | { |
606 | 0 | *this = addMSecs(duration.count()); |
607 | 0 | return *this; |
608 | 0 | } |
609 | | |
610 | | friend QDateTime operator-(const QDateTime &dateTime, std::chrono::milliseconds duration) |
611 | 0 | { |
612 | 0 | return dateTime.addMSecs(-duration.count()); |
613 | 0 | } |
614 | | |
615 | | QDateTime &operator-=(std::chrono::milliseconds duration) |
616 | 0 | { |
617 | 0 | *this = addMSecs(-duration.count()); |
618 | 0 | return *this; |
619 | 0 | } |
620 | | |
621 | | // (1<<63) ms is 292277024.6 (average Gregorian) years, counted from the start of 1970, so |
622 | | // Last is floor(1970 + 292277024.6); no year 0, so First is floor(1970 - 1 - 292277024.6) |
623 | | enum class YearRange : qint32 { First = -292275056, Last = +292278994 }; |
624 | | |
625 | | private: |
626 | | bool equals(const QDateTime &other) const; |
627 | | #if QT_CORE_REMOVED_SINCE(6, 7) |
628 | | bool precedes(const QDateTime &other) const; |
629 | | #endif |
630 | | friend class QDateTimePrivate; |
631 | | |
632 | | Data d; |
633 | | |
634 | | friend bool comparesEqual(const QDateTime &lhs, const QDateTime &rhs) |
635 | | { return lhs.equals(rhs); } |
636 | | friend Q_CORE_EXPORT Qt::weak_ordering |
637 | | compareThreeWay(const QDateTime &lhs, const QDateTime &rhs); |
638 | | Q_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT(QDateTime) |
639 | | |
640 | | #ifndef QT_NO_DATASTREAM |
641 | | friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDateTime &); |
642 | | friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDateTime &); |
643 | | #endif |
644 | | |
645 | | #if !defined(QT_NO_DEBUG_STREAM) && QT_CONFIG(datestring) |
646 | | friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QDateTime &); |
647 | | #endif |
648 | | }; |
649 | | Q_DECLARE_SHARED(QDateTime) |
650 | | |
651 | | #ifndef QT_NO_DATASTREAM |
652 | | Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, QDate); |
653 | | Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDate &); |
654 | | Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, QTime); |
655 | | Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QTime &); |
656 | | Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDateTime &); |
657 | | Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDateTime &); |
658 | | #endif // QT_NO_DATASTREAM |
659 | | |
660 | | #if !defined(QT_NO_DEBUG_STREAM) && QT_CONFIG(datestring) |
661 | | Q_CORE_EXPORT QDebug operator<<(QDebug, QDate); |
662 | | Q_CORE_EXPORT QDebug operator<<(QDebug, QTime); |
663 | | Q_CORE_EXPORT QDebug operator<<(QDebug, const QDateTime &); |
664 | | #endif |
665 | | |
666 | | // QDateTime is not noexcept for now -- to be revised once |
667 | | // timezone and calendaring support is added |
668 | | Q_CORE_EXPORT size_t qHash(const QDateTime &key, size_t seed = 0); |
669 | | Q_CORE_EXPORT size_t qHash(QDate key, size_t seed = 0) noexcept; |
670 | | Q_CORE_EXPORT size_t qHash(QTime key, size_t seed = 0) noexcept; |
671 | | |
672 | | #if QT_CONFIG(datestring) && QT_CORE_INLINE_IMPL_SINCE(6, 7) |
673 | | QDate QDate::fromString(const QString &string, QStringView format, QCalendar cal) |
674 | | { |
675 | | return fromString(string, format, QLocale::DefaultTwoDigitBaseYear, cal); |
676 | | } |
677 | | |
678 | | QDateTime QDateTime::fromString(const QString &string, QStringView format, QCalendar cal) |
679 | | { |
680 | | return fromString(string, format, QLocale::DefaultTwoDigitBaseYear, cal); |
681 | | } |
682 | | #endif |
683 | | |
684 | | QT_END_NAMESPACE |
685 | | |
686 | | #endif // QDATETIME_H |