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
qdatetime.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 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// Qt-Security score:critical reason:data-parser
5
6#include "qdatetime.h"
7
8#include "qcalendar.h"
9#include "qdatastream.h"
10#include "qdebug.h"
11#include "qlocale.h"
12#include "qset.h"
13
14#include "private/qcalendarmath_p.h"
15#include "private/qdatetime_p.h"
16#if QT_CONFIG(datetimeparser)
17#include "private/qdatetimeparser_p.h"
18#endif
19#ifdef Q_OS_DARWIN
20#include "private/qcore_mac_p.h"
21#endif
22#include "private/qgregoriancalendar_p.h"
23#include "private/qlocale_tools_p.h"
24#include "private/qlocaltime_p.h"
25#include "private/qnumeric_p.h"
26#include "private/qstringconverter_p.h"
27#include "private/qstringiterator_p.h"
28#if QT_CONFIG(timezone)
29#include "private/qtimezoneprivate_p.h"
30#endif
31
32#include <cmath>
33#ifdef Q_OS_WIN
34# include <qt_windows.h>
35#endif
36
37#include <private/qtools_p.h>
38
39QT_BEGIN_NAMESPACE
40
41using namespace Qt::StringLiterals;
42using namespace QtPrivate::DateTimeConstants;
43using namespace QtMiscUtils;
44
45/*****************************************************************************
46 Date/Time Constants
47 *****************************************************************************/
48
49/*****************************************************************************
50 QDate static helper functions
51 *****************************************************************************/
52static_assert(std::is_trivially_copyable_v<QCalendar::YearMonthDay>);
53
54static inline QDate fixedDate(QCalendar::YearMonthDay parts, QCalendar cal)
55{
56 if ((parts.year < 0 && !cal.isProleptic()) || (parts.year == 0 && !cal.hasYearZero()))
57 return QDate();
58
59 parts.day = qMin(parts.day, cal.daysInMonth(parts.month, parts.year));
60 return cal.dateFromParts(parts);
61}
62
63static inline QDate fixedDate(QCalendar::YearMonthDay parts)
64{
65 if (parts.year) {
66 parts.day = qMin(parts.day, QGregorianCalendar::monthLength(parts.month, parts.year));
67 const auto jd = QGregorianCalendar::julianFromParts(parts.year, parts.month, parts.day);
68 if (jd)
69 return QDate::fromJulianDay(*jd);
70 }
71 return QDate();
72}
73
74/*****************************************************************************
75 Date/Time formatting helper functions
76 *****************************************************************************/
77
78#if QT_CONFIG(textdate)
79static const char qt_shortMonthNames[][4] = {
80 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
81 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
82};
83
84static int fromShortMonthName(QStringView monthName)
85{
86 for (unsigned int i = 0; i < sizeof(qt_shortMonthNames) / sizeof(qt_shortMonthNames[0]); ++i) {
87 if (monthName == QLatin1StringView(qt_shortMonthNames[i], 3))
88 return i + 1;
89 }
90 return -1;
91}
92#endif // textdate
93
94#if QT_CONFIG(datestring) // depends on, so implies, textdate
95namespace {
96using ParsedInt = QSimpleParsedNumber<qulonglong>;
97
98/*
99 Reads a whole number that must be the whole text.
100*/
101ParsedInt readInt(QLatin1StringView text)
102{
103 // Various date formats' fields (e.g. all in ISO) should not accept spaces
104 // or signs, so check that the string starts with a digit and that qstrntoull()
105 // converted the whole string.
106
107 if (text.isEmpty() || !isAsciiDigit(text.front().toLatin1()))
108 return {};
109
110 QSimpleParsedNumber res = qstrntoull(text.data(), text.size(), 10);
111 return res.used == text.size() ? res : ParsedInt{};
112}
113
114ParsedInt readInt(QStringView text)
115{
116 if (text.isEmpty())
117 return {};
118
119 // Converting to Latin-1 because QStringView::toULongLong() works with
120 // US-ASCII only by design anyway.
121 // Also QStringView::toULongLong() can't be used here as it will happily ignore
122 // spaces and accept signs; but various date formats' fields (e.g. all in ISO)
123 // should not.
124 QVarLengthArray<char> latin1(text.size());
125 QLatin1::convertFromUnicode(latin1.data(), text);
126 return readInt(QLatin1StringView{latin1.data(), latin1.size()});
127}
128
129} // namespace
130
131struct ParsedRfcDateTime {
132 QDate date;
133 QTime time;
134 int utcOffset = 0;
135};
136
137static int shortDayFromName(QStringView name)
138{
139 const char16_t shortDayNames[] = u"MonTueWedThuFriSatSun";
140 for (int i = 0; i < 7; i++) {
141 if (name == QStringView(shortDayNames + 3 * i, 3))
142 return i + 1;
143 }
144 return 0;
145}
146
147static ParsedRfcDateTime rfcDateImpl(QStringView s)
148{
149 // Matches "[ddd,] dd MMM yyyy[ hh:mm[:ss]] [±hhmm]" - correct RFC 822, 2822, 5322 format -
150 // or "ddd MMM dd[ hh:mm:ss] yyyy [±hhmm]" - permissive RFC 850, 1036 (read only)
151 ParsedRfcDateTime result;
152
153 QVarLengthArray<QStringView, 6> words;
154
155 auto tokens = s.tokenize(u' ', Qt::SkipEmptyParts);
156 auto it = tokens.begin();
157 for (int i = 0; i < 6 && it != tokens.end(); ++i, ++it)
158 words.emplace_back(*it);
159
160 if (words.size() < 3 || it != tokens.end())
161 return result;
162 const QChar colon(u':');
163 bool ok = true;
164 QDate date;
165
166 const auto isShortName = [](QStringView name) {
167 return (name.size() == 3 && name[0].isUpper()
168 && name[1].isLower() && name[2].isLower());
169 };
170
171 /* Reject entirely (return) if the string is malformed; however, if the date
172 * is merely invalid, (break, so as to) go on to parsing of the time.
173 */
174 int yearIndex;
175 do { // "loop" so that we can use break on merely invalid, but "right shape" date.
176 QStringView dayName;
177 bool rfcX22 = true;
178 const QStringView maybeDayName = words.front();
179 if (maybeDayName.endsWith(u',')) {
180 dayName = maybeDayName.chopped(1);
181 words.erase(words.begin());
182 } else if (!maybeDayName.front().isDigit()) {
183 dayName = maybeDayName;
184 words.erase(words.begin());
185 rfcX22 = false;
186 } // else: dayName is not specified (so we can only be RFC *22)
187 if (words.size() < 3 || words.size() > 5)
188 return result;
189
190 // Don't break before setting yearIndex.
191 int dayIndex, monthIndex;
192 if (rfcX22) {
193 // dd MMM yyyy [hh:mm[:ss]] [±hhmm]
194 dayIndex = 0;
195 monthIndex = 1;
196 yearIndex = 2;
197 } else {
198 // MMM dd[ hh:mm:ss] yyyy [±hhmm]
199 dayIndex = 1;
200 monthIndex = 0;
201 yearIndex = words.size() > 3 && words.at(2).contains(colon) ? 3 : 2;
202 }
203 if (words.at(yearIndex).size() != 4)
204 return result;
205
206 int dayOfWeek = 0;
207 if (!dayName.isEmpty()) {
208 if (!isShortName(dayName))
209 return result;
210 dayOfWeek = shortDayFromName(dayName);
211 if (!dayOfWeek)
212 break;
213 }
214
215 const int day = words.at(dayIndex).toInt(&ok);
216 if (!ok)
217 return result;
218 const int year = words.at(yearIndex).toInt(&ok);
219 if (!ok)
220 return result;
221 const QStringView monthName = words.at(monthIndex);
222 if (!isShortName(monthName))
223 return result;
224 int month = fromShortMonthName(monthName);
225 if (month < 0)
226 break;
227
228 date = QDate(year, month, day);
229 if (dayOfWeek && date.dayOfWeek() != dayOfWeek)
230 date = QDate();
231 } while (false);
232 words.remove(yearIndex);
233 words.remove(0, 2); // month and day-of-month, in some order
234
235 // Time: [hh:mm[:ss]]
236 QTime time;
237 if (words.size() && words.at(0).contains(colon)) {
238 const QStringView when = words.front();
239 words.erase(words.begin());
240 if (when.size() < 5 || when[2] != colon
241 || (when.size() == 8 ? when[5] != colon : when.size() > 5)) {
242 return result;
243 }
244 const int hour = when.first(2).toInt(&ok);
245 if (!ok)
246 return result;
247 const int minute = when.sliced(3, 2).toInt(&ok);
248 if (!ok)
249 return result;
250 const auto secs = when.size() == 8 ? when.last(2).toInt(&ok) : 0;
251 if (!ok)
252 return result;
253 time = QTime(hour, minute, secs);
254 }
255
256 // Offset: [±hh[mm]]
257 int offset = 0;
258 if (words.size()) {
259 const QStringView zone = words.front();
260 words.erase(words.begin());
261 if (words.size() || !(zone.size() == 3 || zone.size() == 5))
262 return result;
263 bool negate = false;
264 if (zone[0] == u'-')
265 negate = true;
266 else if (zone[0] != u'+')
267 return result;
268 const int hour = zone.sliced(1, 2).toInt(&ok);
269 if (!ok)
270 return result;
271 const auto minute = zone.size() == 5 ? zone.last(2).toInt(&ok) : 0;
272 if (!ok)
273 return result;
274 offset = (hour * 60 + minute) * 60;
275 if (negate)
276 offset = -offset;
277 }
278
279 result.date = date;
280 result.time = time;
281 result.utcOffset = offset;
282 return result;
283}
284#endif // datestring
285
286// Return offset in ±HH:mm format
287static QString toOffsetString(Qt::DateFormat format, int offset)
288{
289 return QString::asprintf("%c%02d%s%02d",
290 offset >= 0 ? '+' : '-',
291 qAbs(offset) / int(SECS_PER_HOUR),
292 // Qt::ISODate puts : between the hours and minutes, but Qt:TextDate does not:
293 format == Qt::TextDate ? "" : ":",
294 (qAbs(offset) / 60) % 60);
295}
296
297#if QT_CONFIG(datestring)
298// Parse offset in ±HH[[:]mm] format
299static int fromOffsetString(QStringView offsetString, bool *valid) noexcept
300{
301 *valid = false;
302
303 const qsizetype size = offsetString.size();
304 if (size < 2 || size > 6)
305 return 0;
306
307 // sign will be +1 for a positive and -1 for a negative offset
308 int sign;
309
310 // First char must be + or -
311 const QChar signChar = offsetString[0];
312 if (signChar == u'+')
313 sign = 1;
314 else if (signChar == u'-')
315 sign = -1;
316 else
317 return 0;
318
319 // Split the hour and minute parts
320 const QStringView time = offsetString.sliced(1);
321 qsizetype hhLen = time.indexOf(u':');
322 qsizetype mmIndex;
323 if (hhLen == -1)
324 mmIndex = hhLen = 2; // ±HHmm or ±HH format
325 else
326 mmIndex = hhLen + 1;
327
328 const QStringView hhRef = time.first(qMin(hhLen, time.size()));
329 bool ok = false;
330 const int hour = hhRef.toInt(&ok);
331 if (!ok || hour > 23) // More generous than QTimeZone::MaxUtcOffsetSecs
332 return 0;
333
334 const QStringView mmRef = time.sliced(qMin(mmIndex, time.size()));
335 const int minute = mmRef.isEmpty() ? 0 : mmRef.toInt(&ok);
336 if (!ok || minute < 0 || minute > 59)
337 return 0;
338
339 *valid = true;
340 return sign * ((hour * 60) + minute) * 60;
341}
342#endif // datestring
343
344/*****************************************************************************
345 QDate member functions
346 *****************************************************************************/
347
348/*!
349 \class QDate
350 \inmodule QtCore
351 \reentrant
352 \brief The QDate class provides date functions.
353
354 \compares strong
355 \compareswith strong std::chrono::year_month_day std::chrono::year_month_day_last \
356 std::chrono::year_month_weekday std::chrono::year_month_weekday_last
357 These comparison operators are only available when using C++20.
358 \endcompareswith
359
360 A QDate object represents a particular day, regardless of calendar, locale
361 or other settings used when creating it or supplied by the system. It can
362 report the year, month and day of the month that represent the day with
363 respect to the proleptic Gregorian calendar or any calendar supplied as a
364 QCalendar object. QDate objects should be passed by value rather than by
365 reference to const; they simply package \c qint64.
366
367 A QDate object is typically created by giving the year, month, and day
368 numbers explicitly. Note that QDate interprets year numbers less than 100 as
369 presented, i.e., as years 1 through 99, without adding any offset. The
370 static function currentDate() creates a QDate object containing the date
371 read from the system clock. An explicit date can also be set using
372 setDate(). The fromString() function returns a QDate given a string and a
373 date format which is used to interpret the date within the string.
374
375 The year(), month(), and day() functions provide access to the year, month,
376 and day numbers. When more than one of these values is needed, it is more
377 efficient to call QCalendar::partsFromDate(), to save repeating (potentially
378 expensive) calendrical calculations.
379
380 Also, dayOfWeek() and dayOfYear() functions are provided. The same
381 information is provided in textual format by toString(). QLocale can map the
382 day numbers to names, QCalendar can map month numbers to names.
383
384 QDate provides a full set of operators to compare two QDate
385 objects where smaller means earlier, and larger means later.
386
387 You can increment (or decrement) a date by a given number of days
388 using addDays(). Similarly you can use addMonths() and addYears().
389 The daysTo() function returns the number of days between two
390 dates.
391
392 The daysInMonth() and daysInYear() functions return how many days there are
393 in this date's month and year, respectively. The isLeapYear() function
394 indicates whether a date is in a leap year. QCalendar can also supply this
395 information, in some cases more conveniently.
396
397 \section1 Remarks
398
399 \note All conversion to and from string formats is done using the C locale.
400 For localized conversions, see QLocale.
401
402 In the Gregorian calendar, there is no year 0. Dates in that year are
403 considered invalid. The year -1 is the year "1 before Christ" or "1 before
404 common era." The day before 1 January 1 CE, QDate(1, 1, 1), is 31 December
405 1 BCE, QDate(-1, 12, 31). Various other calendars behave similarly; see
406 QCalendar::hasYearZero().
407
408 \section2 Range of Valid Dates
409
410 Dates are stored internally as a modified Julian Day number, an integer
411 count of every day in a contiguous range, with 24 November 4714 BCE in the
412 Gregorian calendar being Julian Day 0 (1 January 4713 BCE in the Julian
413 calendar). As well as being an efficient and accurate way of storing an
414 absolute date, it is suitable for converting a date into other calendar
415 systems such as Hebrew, Islamic or Chinese. For the purposes of QDate,
416 Julian Days are delimited at midnight and, for those of QDateTime, in the
417 zone used by the datetime. (This departs from the formal definition, which
418 delimits Julian Days at UTC noon.) The Julian Day number can be obtained
419 using QDate::toJulianDay() and can be set using QDate::fromJulianDay().
420
421 The range of Julian Day numbers that QDate can represent is, for technical
422 reasons, limited to between -784350574879 and 784354017364, which means from
423 before 2 billion BCE to after 2 billion CE. This is more than seven times as
424 wide as the range of dates a QDateTime can represent.
425
426 \sa QTime, QDateTime, QCalendar, QDateTime::YearRange, QDateEdit, QDateTimeEdit, QCalendarWidget
427*/
428
429/*!
430 \fn QDate::QDate()
431
432 Constructs a null date. Null dates are invalid.
433
434 \sa isNull(), isValid()
435*/
436
437/*!
438 Constructs a date with year \a y, month \a m and day \a d.
439
440 The date is understood in terms of the Gregorian calendar. If the specified
441 date is invalid, the date is not set and isValid() returns \c false.
442
443 \warning Years 1 to 99 are interpreted as is. Year 0 is invalid.
444
445 \sa isValid(), QCalendar::dateFromParts()
446*/
447
448QDate::QDate(int y, int m, int d)
449{
450 static_assert(maxJd() == JulianDayMax);
451 static_assert(minJd() == JulianDayMin);
452 jd = QGregorianCalendar::julianFromParts(y, m, d).value_or(nullJd());
453}
454
455QDate::QDate(int y, int m, int d, QCalendar cal)
456{
457 *this = cal.dateFromParts(y, m, d);
458}
459
460/*!
461 \fn QDate::QDate(std::chrono::year_month_day date)
462 \fn QDate::QDate(std::chrono::year_month_day_last date)
463 \fn QDate::QDate(std::chrono::year_month_weekday date)
464 \fn QDate::QDate(std::chrono::year_month_weekday_last date)
465
466 \since 6.4
467
468 Constructs a QDate representing the same date as \a date. This allows for
469 easy interoperability between the Standard Library calendaring classes and
470 Qt datetime classes.
471
472 For example:
473
474 \snippet code/src_corelib_time_qdatetime.cpp 22
475
476 \note Unlike QDate, std::chrono::year and the related classes feature the
477 year zero. This means that if \a date is in the year zero or before, the
478 resulting QDate object will have an year one less than the one specified by
479 \a date.
480
481 \note This function requires C++20.
482*/
483
484/*!
485 \fn QDate QDate::fromStdSysDays(const std::chrono::sys_days &days)
486 \since 6.4
487
488 Returns a QDate \a days days after January 1st, 1970 (the UNIX epoch). If
489 \a days is negative, the returned date will be before the epoch.
490
491 \note This function requires C++20.
492
493 \sa toStdSysDays()
494*/
495
496/*!
497 \fn std::chrono::sys_days QDate::toStdSysDays() const
498
499 Returns the number of days between January 1st, 1970 (the UNIX epoch) and
500 this date, represented as a \c{std::chrono::sys_days} object. If this date
501 is before the epoch, the number of days will be negative.
502
503 \note This function requires C++20.
504
505 \sa fromStdSysDays(), daysTo()
506*/
507
508/*!
509 \fn bool QDate::isNull() const
510
511 Returns \c true if the date is null; otherwise returns \c false. A null
512 date is invalid.
513
514 \note The behavior of this function is equivalent to isValid().
515
516 \sa isValid()
517*/
518
519/*!
520 \overload primary
521 \fn bool QDate::isValid() const
522
523 Returns \c true if this date is valid; otherwise returns \c false.
524
525 \sa isNull(), QCalendar::isDateValid()
526*/
527
528/*!
529 \overload primary
530
531 Returns the year of this date.
532
533 Uses \a cal as calendar, if supplied, else the Gregorian calendar.
534
535 Returns 0 if the date is invalid. For some calendars, dates before their
536 first year may all be invalid.
537
538 If using a calendar which has a year 0, check using isValid() if the return
539 is 0. Such calendars use negative year numbers in the obvious way, with
540 year 1 preceded by year 0, in turn preceded by year -1 and so on.
541
542 Some calendars, despite having no year 0, have a conventional numbering of
543 the years before their first year, counting backwards from 1. For example,
544 in the proleptic Gregorian calendar, successive years before 1 CE (the first
545 year) are identified as 1 BCE, 2 BCE, 3 BCE and so on. For such calendars,
546 negative year numbers are used to indicate these years before year 1, with
547 -1 indicating the year before 1.
548
549 \sa month(), day(), QCalendar::hasYearZero(), QCalendar::isProleptic(), QCalendar::partsFromDate()
550*/
551
552int QDate::year(QCalendar cal) const
553{
554 if (isValid()) {
555 const auto parts = cal.partsFromDate(*this);
556 if (parts.isValid())
557 return parts.year;
558 }
559 return 0;
560}
561
562/*!
563 \overload year()
564*/
565
566int QDate::year() const
567{
568 if (isValid()) {
569 const auto parts = QGregorianCalendar::partsFromJulian(jd);
570 if (parts.isValid())
571 return parts.year;
572 }
573 return 0;
574}
575
576/*!
577 \overload primary
578
579 Returns the month-number for the date.
580
581 Numbers the months of the year starting with 1 for the first. Uses \a cal
582 as calendar if supplied, else the Gregorian calendar, for which the month
583 numbering is as follows:
584
585 \list
586 \li 1 = "January"
587 \li 2 = "February"
588 \li 3 = "March"
589 \li 4 = "April"
590 \li 5 = "May"
591 \li 6 = "June"
592 \li 7 = "July"
593 \li 8 = "August"
594 \li 9 = "September"
595 \li 10 = "October"
596 \li 11 = "November"
597 \li 12 = "December"
598 \endlist
599
600 Returns 0 if the date is invalid. Note that some calendars may have more
601 than 12 months in some years.
602
603 \sa year(), day(), QCalendar::partsFromDate()
604*/
605
606int QDate::month(QCalendar cal) const
607{
608 if (isValid()) {
609 const auto parts = cal.partsFromDate(*this);
610 if (parts.isValid())
611 return parts.month;
612 }
613 return 0;
614}
615
616/*!
617 \overload month()
618*/
619
620int QDate::month() const
621{
622 if (isValid()) {
623 const auto parts = QGregorianCalendar::partsFromJulian(jd);
624 if (parts.isValid())
625 return parts.month;
626 }
627 return 0;
628}
629
630/*!
631 \overload primary
632
633 Returns the day of the month for this date.
634
635 Uses \a cal as calendar if supplied, else the Gregorian calendar (for which
636 the return ranges from 1 to 31). Returns 0 if the date is invalid.
637
638 \sa year(), month(), dayOfWeek(), QCalendar::partsFromDate()
639*/
640
641int QDate::day(QCalendar cal) const
642{
643 if (isValid()) {
644 const auto parts = cal.partsFromDate(*this);
645 if (parts.isValid())
646 return parts.day;
647 }
648 return 0;
649}
650
651/*!
652 \overload day()
653*/
654
655int QDate::day() const
656{
657 if (isValid()) {
658 const auto parts = QGregorianCalendar::partsFromJulian(jd);
659 if (parts.isValid())
660 return parts.day;
661 }
662 return 0;
663}
664
665/*!
666 \overload primary
667
668 Returns the weekday (1 = Monday to 7 = Sunday) for this date.
669
670 Uses \a cal as calendar if supplied, else the Gregorian calendar. Returns 0
671 if the date is invalid. Some calendars may give special meaning
672 (e.g. intercallary days) to values greater than 7.
673
674 \sa day(), dayOfYear(), QCalendar::dayOfWeek(), Qt::DayOfWeek
675*/
676
677int QDate::dayOfWeek(QCalendar cal) const
678{
679 if (isNull())
680 return 0;
681
682 return cal.dayOfWeek(*this);
683}
684
685/*!
686 \overload dayOfWeek()
687*/
688
689int QDate::dayOfWeek() const
690{
691 return isValid() ? QGregorianCalendar::weekDayOfJulian(jd) : 0;
692}
693
694/*!
695 \overload primary
696
697 Returns the day of the year (1 for the first day) for this date.
698
699 Uses \a cal as calendar if supplied, else the Gregorian calendar.
700 Returns 0 if either the date or the first day of its year is invalid.
701
702 \sa day(), dayOfWeek(), QCalendar::daysInYear()
703*/
704
705int QDate::dayOfYear(QCalendar cal) const
706{
707 if (isValid()) {
708 QDate firstDay = cal.dateFromParts(year(cal), 1, 1);
709 if (firstDay.isValid())
710 return firstDay.daysTo(*this) + 1;
711 }
712 return 0;
713}
714
715/*!
716 \overload dayOfYear()
718
719int QDate::dayOfYear() const
720{
721 if (isValid()) {
722 if (const auto first = QGregorianCalendar::julianFromParts(year(), 1, 1))
723 return jd - *first + 1;
724 }
725 return 0;
726}
727
728/*!
729 \overload primary
730
731 Returns the number of days in the month for this date.
732
733 Uses \a cal as calendar if supplied, else the Gregorian calendar (for which
734 the result ranges from 28 to 31). Returns 0 if the date is invalid.
735
736 \sa day(), daysInYear(), QCalendar::daysInMonth(),
737 QCalendar::maximumDaysInMonth(), QCalendar::minimumDaysInMonth()
738*/
739
740int QDate::daysInMonth(QCalendar cal) const
741{
742 if (isValid()) {
743 const auto parts = cal.partsFromDate(*this);
744 if (parts.isValid())
745 return cal.daysInMonth(parts.month, parts.year);
746 }
747 return 0;
748}
749
750/*!
751 \overload daysInMonth()
752*/
753
754int QDate::daysInMonth() const
755{
756 if (isValid()) {
757 const auto parts = QGregorianCalendar::partsFromJulian(jd);
758 if (parts.isValid())
759 return QGregorianCalendar::monthLength(parts.month, parts.year);
760 }
761 return 0;
762}
763
764/*!
765 \overload primary
766
767 Returns the number of days in the year for this date.
768
769 Uses \a cal as calendar if supplied, else the Gregorian calendar (for which
770 the result is 365 or 366). Returns 0 if the date is invalid.
771
772 \sa day(), daysInMonth(), QCalendar::daysInYear(), QCalendar::maximumMonthsInYear()
773*/
774
775int QDate::daysInYear(QCalendar cal) const
776{
777 if (isNull())
778 return 0;
779
780 return cal.daysInYear(year(cal));
781}
782
783/*!
784 \overload daysInYear()
785*/
786
787int QDate::daysInYear() const
788{
789 return isValid() ? QGregorianCalendar::leapTest(year()) ? 366 : 365 : 0;
790}
791
792/*!
793 Returns the ISO 8601 week number (1 to 53).
794
795 Returns 0 if the date is invalid. Otherwise, returns the week number for the
796 date. If \a yearNumber is not \nullptr (its default), stores the year as
797 *\a{yearNumber}.
798
799 In accordance with ISO 8601, each week falls in the year to which most of
800 its days belong, in the Gregorian calendar. As ISO 8601's week starts on
801 Monday, this is the year in which the week's Thursday falls. Most years have
802 52 weeks, but some have 53.
803
804 \note *\a{yearNumber} is not always the same as year(). For example, 1
805 January 2000 has week number 52 in the year 1999, and 31 December
806 2002 has week number 1 in the year 2003.
807
808 \sa isValid()
809*/
810
811int QDate::weekNumber(int *yearNumber) const
812{
813 if (!isValid())
814 return 0;
815
816 // This could be replaced by use of QIso8601Calendar, once we implement it.
817 // The Thursday of the same week determines our answer:
818 const QDate thursday(addDays(4 - dayOfWeek()));
819 if (yearNumber)
820 *yearNumber = thursday.year();
821
822 // Week n's Thurs's DOY has 1 <= DOY - 7*(n-1) < 8, so 0 <= DOY + 6 - 7*n < 7:
823 return (thursday.dayOfYear() + 6) / 7;
824}
825
826#if QT_DEPRECATED_SINCE(6, 9)
827// Only called by deprecated methods (so bootstrap builds warn unused without this #if).
828static QTimeZone asTimeZone(Qt::TimeSpec spec, int offset, const char *warner)
829{
830 if (warner) {
831 switch (spec) {
832 case Qt::TimeZone:
833 qWarning("%s: Pass a QTimeZone instead of Qt::TimeZone.", warner);
834 break;
835 case Qt::LocalTime:
836 if (offset) {
837 qWarning("%s: Ignoring offset (%d seconds) passed with Qt::LocalTime",
838 warner, offset);
839 }
840 break;
841 case Qt::UTC:
842 if (offset) {
843 qWarning("%s: Ignoring offset (%d seconds) passed with Qt::UTC",
844 warner, offset);
845 offset = 0;
846 }
847 break;
848 case Qt::OffsetFromUTC:
849 break;
850 }
851 }
852 return QTimeZone::isUtcOrFixedOffset(spec)
853 ? QTimeZone::fromSecondsAheadOfUtc(offset)
854 : QTimeZone(QTimeZone::LocalTime);
855}
856#endif // Helper for 6.9 deprecation
857
858enum class DaySide { Start, End };
859
860static bool inDateTimeRange(qint64 jd, DaySide side)
861{
862 using Bounds = std::numeric_limits<qint64>;
863 if (jd < Bounds::min() + JULIAN_DAY_FOR_EPOCH)
864 return false;
865 jd -= JULIAN_DAY_FOR_EPOCH;
866 const qint64 maxDay = Bounds::max() / MSECS_PER_DAY;
867 const qint64 minDay = Bounds::min() / MSECS_PER_DAY - 1;
868 // (Divisions rounded towards zero, as MSECS_PER_DAY is even - so doesn't
869 // divide max() - and has factors other than two, so doesn't divide min().)
870 // Range includes start of last day and end of first:
871 switch (side) {
872 case DaySide::Start:
873 return jd > minDay && jd <= maxDay;
874 case DaySide::End:
875 return jd >= minDay && jd < maxDay;
876 }
877 Q_UNREACHABLE_RETURN(false);
878}
879
880static QDateTime toEarliest(QDate day, const QTimeZone &zone)
881{
882 Q_ASSERT(!zone.isUtcOrFixedOffset());
883 // And the day starts in a gap. First find a moment not in that gap.
884 const auto moment = [=](QTime time) {
885 return QDateTime(day, time, zone, QDateTime::TransitionResolution::Reject);
886 };
887 // Longest routine time-zone transition is 2 hours:
888 QDateTime when = moment(QTime(2, 0));
889 if (!when.isValid()) {
890 // Noon should be safe ...
891 when = moment(QTime(12, 0));
892 if (!when.isValid()) {
893 // ... unless it's a 24-hour jump (moving the date-line)
894 when = moment(QTime(23, 59, 59, 999));
895 if (!when.isValid())
896 return QDateTime();
897 }
898 }
899 int high = when.time().msecsSinceStartOfDay() / 60000;
900 int low = 0;
901 // Binary chop to the right minute
902 while (high > low + 1) {
903 const int mid = (high + low) / 2;
904 const QDateTime probe = QDateTime(day, QTime(mid / 60, mid % 60), zone,
905 QDateTime::TransitionResolution::PreferBefore);
906 if (probe.isValid() && probe.date() == day) {
907 high = mid;
908 when = probe;
909 } else {
910 low = mid;
911 }
912 }
913 // Transitions out of local solar mean time, and the few international
914 // date-line crossings before that (Alaska, Philippines), may have happened
915 // between minute boundaries. Don't try to fix milliseconds.
916 if (QDateTime p = moment(when.time().addSecs(-1)); Q_UNLIKELY(p.isValid() && p.date() == day)) {
917 high *= 60;
918 low *= 60;
919 while (high > low + 1) {
920 const int mid = (high + low) / 2;
921 const int min = mid / 60;
922 const QDateTime probe = moment(QTime(min / 60, min % 60, mid % 60));
923 if (probe.isValid() && probe.date() == day) {
924 high = mid;
925 when = probe;
926 } else {
927 low = mid;
928 }
929 }
930 }
931 return when.isValid() ? when : QDateTime();
932}
933
934/*!
935 \since 5.14
936 \overload primary
937
938 Returns the start-moment of the day.
939
940 When a day starts depends on a how time is described: each day starts and
941 ends earlier for those in time-zones further west and later for those in
942 time-zones further east. The time representation to use can be specified by
943 an optional time \a zone. The default time representation is the system's
944 local time.
945
946 Usually, the start of the day is midnight, 00:00: however, if a time-zone
947 transition causes the given date to skip over that midnight (e.g. a DST
948 spring-forward skipping over the first hour of the day day), the actual
949 earliest time in the day is returned. This can only arise when the time
950 representation is a time-zone or local time.
951
952 When \a zone has a timeSpec() of is Qt::OffsetFromUTC or Qt::UTC, the time
953 representation has no transitions so the start of the day is QTime(0, 0).
954
955 In the rare case of a date that was entirely skipped (this happens when a
956 zone east of the international date-line switches to being west of it), the
957 return shall be invalid. Passing an invalid time-zone as \a zone will also
958 produce an invalid result, as shall dates that start outside the range
959 representable by QDateTime.
960
961 \sa endOfDay()
962*/
963QDateTime QDate::startOfDay(const QTimeZone &zone) const
964{
965 if (!inDateTimeRange(jd, DaySide::Start) || !zone.isValid())
966 return QDateTime();
967
968 QDateTime when(*this, QTime(0, 0), zone,
969 QDateTime::TransitionResolution::RelativeToBefore);
970 if (Q_UNLIKELY(!when.isValid() || when.date() != *this)) {
971#if QT_CONFIG(timezone)
972 // The start of the day must have fallen in a spring-forward's gap; find the spring-forward:
973 if (zone.timeSpec() == Qt::TimeZone && zone.hasTransitions()) {
974 QTimeZone::OffsetData tran
975 // There's unlikely to be another transition before noon tomorrow.
976 // However, the whole of today may have been skipped !
977 = zone.previousTransition(QDateTime(addDays(1), QTime(12, 0), zone));
978 const QDateTime &at = tran.atUtc.toTimeZone(zone);
979 if (at.isValid() && at.date() == *this)
980 return at;
981 }
982#endif
983
984 when = toEarliest(*this, zone);
985 }
986
987 return when;
988}
989
990/*!
991 \since 6.5
992 \overload startOfDay()
994QDateTime QDate::startOfDay() const
995{
996 return startOfDay(QTimeZone::LocalTime);
997}
998
999#if QT_DEPRECATED_SINCE(6, 9)
1000/*!
1001 \since 5.14
1002 \overload startOfDay()
1003 \deprecated [6.9] Use \c{startOfDay(const QTimeZone &)} instead.
1004
1005 Returns the start-moment of the day.
1006
1007 When a day starts depends on a how time is described: each day starts and
1008 ends earlier for those with higher offsets from UTC and later for those with
1009 lower offsets from UTC. The time representation to use can be specified
1010 either by a \a spec and \a offsetSeconds (ignored unless \a spec is
1011 Qt::OffsetSeconds) or by a time zone.
1012
1013 Usually, the start of the day is midnight, 00:00: however, if a local time
1014 transition causes the given date to skip over that midnight (e.g. a DST
1015 spring-forward skipping over the first hour of the day day), the actual
1016 earliest time in the day is returned.
1017
1018 When \a spec is Qt::OffsetFromUTC, \a offsetSeconds gives an implied zone's
1019 offset from UTC. As UTC and such zones have no transitions, the start of the
1020 day is QTime(0, 0) in these cases.
1021
1022 In the rare case of a date that was entirely skipped (this happens when a
1023 zone east of the international date-line switches to being west of it), the
1024 return shall be invalid. Passing Qt::TimeZone as \a spec (instead of passing
1025 a QTimeZone) will also produce an invalid result, as shall dates that start
1026 outside the range representable by QDateTime.
1027*/
1028QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const
1029{
1030 QTimeZone zone = asTimeZone(spec, offsetSeconds, "QDate::startOfDay");
1031 // If spec was Qt::TimeZone, zone's is Qt::LocalTime.
1032 return zone.timeSpec() == spec ? startOfDay(zone) : QDateTime();
1033}
1034#endif // 6.9 deprecation
1035
1036static QDateTime toLatest(QDate day, const QTimeZone &zone)
1037{
1038 Q_ASSERT(!zone.isUtcOrFixedOffset());
1039 // And the day ends in a gap. First find a moment not in that gap:
1040 const auto moment = [=](QTime time) {
1041 return QDateTime(day, time, zone, QDateTime::TransitionResolution::Reject);
1042 };
1043 // Longest routine time-zone transition is 2 hours:
1044 QDateTime when = moment(QTime(21, 59, 59, 999));
1045 if (!when.isValid()) {
1046 // Noon should be safe ...
1047 when = moment(QTime(12, 0));
1048 if (!when.isValid()) {
1049 // ... unless it's a 24-hour jump (moving the date-line)
1050 when = moment(QTime(0, 0));
1051 if (!when.isValid())
1052 return QDateTime();
1053 }
1054 }
1055 int high = 24 * 60;
1056 int low = when.time().msecsSinceStartOfDay() / 60000;
1057 // Binary chop to the right minute
1058 while (high > low + 1) {
1059 const int mid = (high + low) / 2;
1060 const QDateTime probe = QDateTime(day, QTime(mid / 60, mid % 60, 59, 999), zone,
1061 QDateTime::TransitionResolution::PreferAfter);
1062 if (probe.isValid() && probe.date() == day) {
1063 low = mid;
1064 when = probe;
1065 } else {
1066 high = mid;
1067 }
1068 }
1069 // Transitions out of local solar mean time, and the few international
1070 // date-line crossings before that (Alaska, Philippines), may have happened
1071 // between minute boundaries. Don't try to fix milliseconds.
1072 if (QDateTime p = moment(when.time().addSecs(1)); Q_UNLIKELY(p.isValid() && p.date() == day)) {
1073 high *= 60;
1074 low *= 60;
1075 while (high > low + 1) {
1076 const int mid = (high + low) / 2;
1077 const int min = mid / 60;
1078 const QDateTime probe = moment(QTime(min / 60, min % 60, mid % 60, 999));
1079 if (probe.isValid() && probe.date() == day) {
1080 low = mid;
1081 when = probe;
1082 } else {
1083 high = mid;
1084 }
1085 }
1086 }
1087 return when.isValid() ? when : QDateTime();
1088}
1089
1090/*!
1091 \since 5.14
1092 \overload primary
1093
1094 Returns the end-moment of the day.
1095
1096 When a day ends depends on a how time is described: each day starts and ends
1097 earlier for those in time-zones further west and later for those in
1098 time-zones further east. The time representation to use can be specified by
1099 an optional time \a zone. The default time representation is the system's
1100 local time.
1101
1102 Usually, the end of the day is one millisecond before the midnight, 24:00:
1103 however, if a time-zone transition causes the given date to skip over that
1104 moment (e.g. a DST spring-forward skipping over 23:00 and the following
1105 hour), the actual latest time in the day is returned. This can only arise
1106 when the time representation is a time-zone or local time.
1107
1108 When \a zone has a timeSpec() of Qt::OffsetFromUTC or Qt::UTC, the time
1109 representation has no transitions so the end of the day is QTime(23, 59, 59,
1110 999).
1111
1112 In the rare case of a date that was entirely skipped (this happens when a
1113 zone east of the international date-line switches to being west of it), the
1114 return shall be invalid. Passing an invalid time-zone as \a zone will also
1115 produce an invalid result, as shall dates that end outside the range
1116 representable by QDateTime.
1117
1118 \sa startOfDay()
1119*/
1120QDateTime QDate::endOfDay(const QTimeZone &zone) const
1121{
1122 if (!inDateTimeRange(jd, DaySide::End) || !zone.isValid())
1123 return QDateTime();
1124
1125 QDateTime when(*this, QTime(23, 59, 59, 999), zone,
1126 QDateTime::TransitionResolution::RelativeToAfter);
1127 if (Q_UNLIKELY(!when.isValid() || when.date() != *this)) {
1128#if QT_CONFIG(timezone)
1129 // The end of the day must have fallen in a spring-forward's gap; find the spring-forward:
1130 if (zone.timeSpec() == Qt::TimeZone && zone.hasTransitions()) {
1131 QTimeZone::OffsetData tran
1132 // It's unlikely there's been another transition since yesterday noon.
1133 // However, the whole of today may have been skipped !
1134 = zone.nextTransition(QDateTime(addDays(-1), QTime(12, 0), zone));
1135 const QDateTime &at = tran.atUtc.toTimeZone(zone);
1136 if (at.isValid() && at.date() == *this)
1137 return at;
1138 }
1139#endif
1140
1141 when = toLatest(*this, zone);
1142 }
1143 return when;
1144}
1145
1146/*!
1147 \since 6.5
1148 \overload endOfDay()
1150QDateTime QDate::endOfDay() const
1151{
1152 return endOfDay(QTimeZone::LocalTime);
1153}
1154
1155#if QT_DEPRECATED_SINCE(6, 9)
1156/*!
1157 \since 5.14
1158 \overload endOfDay()
1159 \deprecated [6.9] Use \c{endOfDay(const QTimeZone &) instead.
1160
1161 Returns the end-moment of the day.
1162
1163 When a day ends depends on a how time is described: each day starts and ends
1164 earlier for those with higher offsets from UTC and later for those with
1165 lower offsets from UTC. The time representation to use can be specified
1166 either by a \a spec and \a offsetSeconds (ignored unless \a spec is
1167 Qt::OffsetSeconds) or by a time zone.
1168
1169 Usually, the end of the day is one millisecond before the midnight, 24:00:
1170 however, if a local time transition causes the given date to skip over that
1171 moment (e.g. a DST spring-forward skipping over 23:00 and the following
1172 hour), the actual latest time in the day is returned.
1173
1174 When \a spec is Qt::OffsetFromUTC, \a offsetSeconds gives the implied zone's
1175 offset from UTC. As UTC and such zones have no transitions, the end of the
1176 day is QTime(23, 59, 59, 999) in these cases.
1177
1178 In the rare case of a date that was entirely skipped (this happens when a
1179 zone east of the international date-line switches to being west of it), the
1180 return shall be invalid. Passing Qt::TimeZone as \a spec (instead of passing
1181 a QTimeZone) will also produce an invalid result, as shall dates that end
1182 outside the range representable by QDateTime.
1183*/
1184QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const
1185{
1186 QTimeZone zone = asTimeZone(spec, offsetSeconds, "QDate::endOfDay");
1187 // If spec was Qt::TimeZone, zone's is Qt::LocalTime.
1188 return endOfDay(zone);
1189}
1190#endif // 6.9 deprecation
1191
1192#if QT_CONFIG(datestring) // depends on, so implies, textdate
1193
1194static QString toStringTextDate(QDate date)
1195{
1196 if (date.isValid()) {
1197 QCalendar cal; // Always Gregorian
1198 const auto parts = cal.partsFromDate(date);
1199 if (parts.isValid()) {
1200 const QLatin1Char sp(' ');
1201 return QLocale::c().dayName(cal.dayOfWeek(date), QLocale::ShortFormat) + sp
1202 + cal.monthName(QLocale::c(), parts.month, parts.year, QLocale::ShortFormat)
1203 // Documented to use 4-digit year
1204 + sp + QString::asprintf("%d %04d", parts.day, parts.year);
1205 }
1206 }
1207 return QString();
1208}
1209
1210static QString toStringIsoDate(QDate date)
1211{
1212 const auto parts = QCalendar().partsFromDate(date);
1213 if (parts.isValid() && parts.year >= 0 && parts.year <= 9999)
1214 return QString::asprintf("%04d-%02d-%02d", parts.year, parts.month, parts.day);
1215 return QString();
1216}
1217
1218/*!
1219 \overload toString()
1220
1221 Returns the date as a string. The \a format parameter determines the format
1222 of the string.
1223
1224 If the \a format is Qt::TextDate, the string is formatted in the default
1225 way. The day and month names will be in English. An example of this
1226 formatting is "Sat May 20 1995". For localized formatting, see
1227 \l{QLocale::toString()}.
1228
1229 If the \a format is Qt::ISODate, the string format corresponds
1230 to the ISO 8601 extended specification for representations of
1231 dates and times, taking the form yyyy-MM-dd, where yyyy is the
1232 year, MM is the month of the year (between 01 and 12), and dd is
1233 the day of the month between 01 and 31.
1234
1235 If the \a format is Qt::RFC2822Date, the string is formatted in
1236 an \l{RFC 2822} compatible way. An example of this formatting is
1237 "20 May 1995".
1238
1239 If the date is invalid, an empty string will be returned.
1240
1241 \warning The Qt::ISODate format is only valid for years in the
1242 range 0 to 9999.
1243
1244 \sa fromString(), QLocale::toString()
1245*/
1246QString QDate::toString(Qt::DateFormat format) const
1247{
1248 if (!isValid())
1249 return QString();
1250
1251 switch (format) {
1252 case Qt::RFC2822Date:
1253 return QLocale::c().toString(*this, u"dd MMM yyyy");
1254 default:
1255 case Qt::TextDate:
1256 return toStringTextDate(*this);
1257 case Qt::ISODate:
1258 case Qt::ISODateWithMs:
1259 // No calendar dependence
1260 return toStringIsoDate(*this);
1261 }
1262}
1263
1264/*!
1265 \since 5.14
1266 \overload primary
1267 \fn QString QDate::toString(const QString &format, QCalendar cal) const
1268 \fn QString QDate::toString(QStringView format, QCalendar cal) const
1269
1270 Returns the date as a string. The \a format parameter determines the format
1271 of the result string. If \a cal is supplied, it determines the calendar used
1272 to represent the date; it defaults to Gregorian. Prior to Qt 5.14, there was
1273 no \a cal parameter and the Gregorian calendar was always used.
1274
1275 These expressions may be used in the \a format parameter:
1276
1277 \table
1278 \header \li Expression \li Output
1279 \row \li d \li The day as a number without a leading zero (1 to 31)
1280 \row \li dd \li The day as a number with a leading zero (01 to 31)
1281 \row \li ddd \li The abbreviated day name ('Mon' to 'Sun').
1282 \row \li dddd \li The long day name ('Monday' to 'Sunday').
1283 \row \li M \li The month as a number without a leading zero (1 to 12)
1284 \row \li MM \li The month as a number with a leading zero (01 to 12)
1285 \row \li MMM \li The abbreviated month name ('Jan' to 'Dec').
1286 \row \li MMMM \li The long month name ('January' to 'December').
1287 \row \li yy \li The year as a two digit number (00 to 99)
1288 \row \li yyyy \li The year as a four digit number. If the year is negative,
1289 a minus sign is prepended, making five characters.
1290 \endtable
1291
1292 Any sequence of characters enclosed in single quotes will be included
1293 verbatim in the output string (stripped of the quotes), even if it contains
1294 formatting characters. Two consecutive single quotes ("''") are replaced by
1295 a single quote in the output. All other characters in the format string are
1296 included verbatim in the output string.
1297
1298 Formats without separators (e.g. "ddMM") are supported but must be used with
1299 care, as the resulting strings aren't always reliably readable (e.g. if "dM"
1300 produces "212" it could mean either the 2nd of December or the 21st of
1301 February).
1302
1303 Example format strings (assuming that the QDate is the 20 July
1304 1969):
1305
1306 \table
1307 \header \li Format \li Result
1308 \row \li dd.MM.yyyy \li 20.07.1969
1309 \row \li ddd MMMM d yy \li Sun July 20 69
1310 \row \li 'The day is' dddd \li The day is Sunday
1311 \endtable
1312
1313 If the datetime is invalid, an empty string will be returned.
1314
1315 \note Day and month names are given in English (C locale). To get localized
1316 month and day names, use QLocale::system().toString().
1317
1318 \note If a format character is repeated more times than the longest
1319 expression in the table above using it, this part of the format will be read
1320 as several expressions with no separator between them; the longest above,
1321 possibly repeated as many times as there are copies of it, ending with a
1322 residue that may be a shorter expression. Thus \c{'MMMMMMMMMM'} for a date
1323 in May will contribute \c{"MayMay05"} to the output.
1324
1325 \sa fromString(), QDateTime::toString(), QTime::toString(), QLocale::toString()
1326*/
1327QString QDate::toString(QStringView format, QCalendar cal) const
1328{
1329 return QLocale::c().toString(*this, format, cal);
1330}
1331
1332// Out-of-line no-calendar overloads, since QCalendar is a non-trivial type
1333/*!
1334 \since 5.10
1335 \overload toString()
1336*/
1337QString QDate::toString(QStringView format) const
1338{
1339 return QLocale::c().toString(*this, format, QCalendar());
1340}
1341
1342/*!
1343 \since 4.6
1344 \overload toString()
1345*/
1346QString QDate::toString(const QString &format) const
1347{
1348 return QLocale::c().toString(*this, qToStringViewIgnoringNull(format), QCalendar());
1349}
1350#endif // datestring
1351
1352/*!
1353 \since 4.2
1354
1355 Sets this to represent the date, in the Gregorian calendar, with the given
1356 \a year, \a month and \a day numbers. Returns true if the resulting date is
1357 valid, otherwise it sets this to represent an invalid date and returns
1358 false.
1359
1360 \sa isValid(), QCalendar::dateFromParts()
1361*/
1362bool QDate::setDate(int year, int month, int day)
1363{
1364 const auto maybe = QGregorianCalendar::julianFromParts(year, month, day);
1365 jd = maybe.value_or(nullJd());
1366 return bool(maybe);
1367}
1368
1369/*!
1370 \since 5.14
1371
1372 Sets this to represent the date, in the given calendar \a cal, with the
1373 given \a year, \a month and \a day numbers. Returns true if the resulting
1374 date is valid, otherwise it sets this to represent an invalid date and
1375 returns false.
1376
1377 \sa isValid(), QCalendar::dateFromParts()
1378*/
1379
1380bool QDate::setDate(int year, int month, int day, QCalendar cal)
1381{
1382 *this = QDate(year, month, day, cal);
1383 return isValid();
1384}
1385
1386/*!
1387 \since 4.5
1388
1389 Extracts the date's year, month, and day, and assigns them to
1390 *\a year, *\a month, and *\a day. The pointers may be null.
1391
1392 Returns 0 if the date is invalid.
1393
1394 \note In Qt versions prior to 5.7, this function is marked as non-\c{const}.
1395
1396 \sa year(), month(), day(), isValid(), QCalendar::partsFromDate()
1397*/
1398void QDate::getDate(int *year, int *month, int *day) const
1399{
1400 QCalendar::YearMonthDay parts; // invalid by default
1401 if (isValid())
1402 parts = QGregorianCalendar::partsFromJulian(jd);
1403
1404 const bool ok = parts.isValid();
1405 if (year)
1406 *year = ok ? parts.year : 0;
1407 if (month)
1408 *month = ok ? parts.month : 0;
1409 if (day)
1410 *day = ok ? parts.day : 0;
1411}
1412
1413/*!
1414 Returns a QDate object containing a date \a ndays later than the
1415 date of this object (or earlier if \a ndays is negative).
1416
1417 Returns a null date if the current date is invalid or the new date is
1418 out of range.
1419
1420 \sa addMonths(), addYears(), daysTo()
1421*/
1422
1423QDate QDate::addDays(qint64 ndays) const
1424{
1425 if (isNull())
1426 return QDate();
1427
1428 if (qint64 r; Q_UNLIKELY(qAddOverflow(jd, ndays, &r)))
1429 return QDate();
1430 else
1431 return fromJulianDay(r);
1432}
1433
1434/*!
1435 \since 6.4
1436 \fn QDate QDate::addDuration(std::chrono::days ndays) const
1437
1438 Returns a QDate object containing a date \a ndays later than the
1439 date of this object (or earlier if \a ndays is negative).
1440
1441 Returns a null date if the current date is invalid or the new date is
1442 out of range.
1443
1444 \note Adding durations expressed in \c{std::chrono::months} or
1445 \c{std::chrono::years} does not yield the same result obtained by using
1446 addMonths() or addYears(). The former are fixed durations, calculated in
1447 relation to the solar year; the latter use the Gregorian calendar definitions
1448 of months/years.
1449
1450 \note This function requires C++20.
1451
1452 \sa addMonths(), addYears(), daysTo()
1453*/
1454
1455/*!
1456 \overload primary
1457
1458 Returns a QDate object containing a date \a nmonths later than the
1459 date of this object (or earlier if \a nmonths is negative).
1460
1461 Uses \a cal as calendar, if supplied, else the Gregorian calendar.
1462
1463 \note If the ending day/month combination does not exist in the resulting
1464 month/year, this function will return a date that is the latest valid date
1465 in the selected month.
1466
1467 \sa addDays(), addYears()
1468*/
1469
1470QDate QDate::addMonths(int nmonths, QCalendar cal) const
1471{
1472 if (!isValid())
1473 return QDate();
1474
1475 if (nmonths == 0)
1476 return *this;
1477
1478 auto parts = cal.partsFromDate(*this);
1479
1480 if (!parts.isValid())
1481 return QDate();
1482 Q_ASSERT(parts.year || cal.hasYearZero());
1483
1484 parts.month += nmonths;
1485 while (parts.month <= 0) {
1486 if (--parts.year || cal.hasYearZero())
1487 parts.month += cal.monthsInYear(parts.year);
1488 }
1489 int count = cal.monthsInYear(parts.year);
1490 while (parts.month > count) {
1491 parts.month -= count;
1492 count = (++parts.year || cal.hasYearZero()) ? cal.monthsInYear(parts.year) : 0;
1493 }
1494
1495 return fixedDate(parts, cal);
1496}
1497
1498/*!
1499 \overload addMonths()
1500*/
1501
1502QDate QDate::addMonths(int nmonths) const
1503{
1504 if (isNull())
1505 return QDate();
1506
1507 if (nmonths == 0)
1508 return *this;
1509
1510 auto parts = QGregorianCalendar::partsFromJulian(jd);
1511
1512 if (!parts.isValid())
1513 return QDate();
1514 Q_ASSERT(parts.year);
1515
1516 parts.month += nmonths;
1517 while (parts.month <= 0) {
1518 if (--parts.year) // skip over year 0
1519 parts.month += 12;
1520 }
1521 while (parts.month > 12) {
1522 parts.month -= 12;
1523 if (!++parts.year) // skip over year 0
1524 ++parts.year;
1525 }
1526
1527 return fixedDate(parts);
1528}
1529
1530/*!
1531 \overload primary
1532
1533 Returns a QDate object containing a date \a nyears later than the
1534 date of this object (or earlier if \a nyears is negative).
1535
1536 Uses \a cal as calendar, if supplied, else the Gregorian calendar.
1537
1538 \note If the ending day/month combination does not exist in the resulting
1539 year (e.g., for the Gregorian calendar, if the date was Feb 29 and the final
1540 year is not a leap year), this function will return a date that is the
1541 latest valid date in the given month (in the example, Feb 28).
1542
1543 \sa addDays(), addMonths()
1544*/
1545
1546QDate QDate::addYears(int nyears, QCalendar cal) const
1547{
1548 if (!isValid())
1549 return QDate();
1550
1551 auto parts = cal.partsFromDate(*this);
1552 if (!parts.isValid())
1553 return QDate();
1554
1555 int old_y = parts.year;
1556 parts.year += nyears;
1557
1558 // If we just crossed (or hit) a missing year zero, adjust year by ±1:
1559 if (!cal.hasYearZero() && ((old_y > 0) != (parts.year > 0) || !parts.year))
1560 parts.year += nyears > 0 ? +1 : -1;
1561
1562 return fixedDate(parts, cal);
1563}
1564
1565/*!
1566 \overload addYears()
1567*/
1568
1569QDate QDate::addYears(int nyears) const
1570{
1571 if (isNull())
1572 return QDate();
1573
1574 auto parts = QGregorianCalendar::partsFromJulian(jd);
1575 if (!parts.isValid())
1576 return QDate();
1577
1578 int old_y = parts.year;
1579 parts.year += nyears;
1580
1581 // If we just crossed (or hit) a missing year zero, adjust year by ±1:
1582 if ((old_y > 0) != (parts.year > 0) || !parts.year)
1583 parts.year += nyears > 0 ? +1 : -1;
1584
1585 return fixedDate(parts);
1586}
1587
1588/*!
1589 Returns the number of days from this date to \a d (which is
1590 negative if \a d is earlier than this date).
1591
1592 Returns 0 if either date is invalid.
1593
1594 Example:
1595 \snippet code/src_corelib_time_qdatetime.cpp 0
1596
1597 \sa addDays()
1598*/
1599
1600qint64 QDate::daysTo(QDate d) const
1601{
1602 if (isNull() || d.isNull())
1603 return 0;
1604
1605 // Due to limits on minJd() and maxJd() we know this will never overflow
1606 return d.jd - jd;
1607}
1608
1609
1610/*!
1611 \fn bool QDate::operator==(const QDate &lhs, const QDate &rhs)
1612
1613 Returns \c true if \a lhs and \a rhs represent the same day, otherwise
1614 \c false.
1615*/
1616
1617/*!
1618 \fn bool QDate::operator!=(const QDate &lhs, const QDate &rhs)
1619
1620 Returns \c true if \a lhs and \a rhs represent distinct days; otherwise
1621 returns \c false.
1622
1623 \sa operator==()
1624*/
1625
1626/*!
1627 \fn bool QDate::operator<(const QDate &lhs, const QDate &rhs)
1628
1629 Returns \c true if \a lhs is earlier than \a rhs; otherwise returns \c false.
1630*/
1631
1632/*!
1633 \fn bool QDate::operator<=(const QDate &lhs, const QDate &rhs)
1634
1635 Returns \c true if \a lhs is earlier than or equal to \a rhs;
1636 otherwise returns \c false.
1637*/
1638
1639/*!
1640 \fn bool QDate::operator>(const QDate &lhs, const QDate &rhs)
1641
1642 Returns \c true if \a lhs is later than \a rhs; otherwise returns \c false.
1643*/
1644
1645/*!
1646 \fn bool QDate::operator>=(const QDate &lhs, const QDate &rhs)
1647
1648 Returns \c true if \a lhs is later than or equal to \a rhs;
1649 otherwise returns \c false.
1650*/
1651
1652/*!
1653 \fn QDate::currentDate()
1654 Returns the system clock's current date.
1655
1656 \sa QTime::currentTime(), QDateTime::currentDateTime()
1657*/
1658
1659#if QT_CONFIG(datestring) // depends on, so implies, textdate
1660
1661/*!
1662 \overload
1663 \fn QDate QDate::fromString(const QString &string, Qt::DateFormat format)
1664
1665 Returns the QDate represented by the \a string, using the
1666 \a format given, or an invalid date if the string cannot be
1667 parsed.
1668
1669 Note for Qt::TextDate: only English month names (e.g. "Jan" in short form or
1670 "January" in long form) are recognized.
1671
1672 \sa toString(), QLocale::toDate()
1673*/
1674
1675/*!
1676 \since 6.0
1677 \overload fromString()
1678*/
1679QDate QDate::fromString(QStringView string, Qt::DateFormat format)
1680{
1681 if (string.isEmpty())
1682 return QDate();
1683
1684 switch (format) {
1685 case Qt::RFC2822Date:
1686 return rfcDateImpl(string).date;
1687 default:
1688 case Qt::TextDate: {
1689 // Documented as "ddd MMM d yyyy"
1690 QVarLengthArray<QStringView, 4> parts;
1691 auto tokens = string.tokenize(u' ', Qt::SkipEmptyParts);
1692 auto it = tokens.begin();
1693 for (int i = 0; i < 4 && it != tokens.end(); ++i, ++it)
1694 parts.emplace_back(*it);
1695
1696 if (parts.size() != 4 || it != tokens.end())
1697 return QDate();
1698
1699 bool ok = false;
1700 int year = parts.at(3).toInt(&ok);
1701 int day = ok ? parts.at(2).toInt(&ok) : 0;
1702 if (!ok || !day)
1703 return QDate();
1704
1705 const int month = fromShortMonthName(parts.at(1));
1706 if (month == -1) // Month name matches no English or localised name.
1707 return QDate();
1708
1709 return QDate(year, month, day);
1710 }
1711 case Qt::ISODate:
1712 // Semi-strict parsing, must be long enough and have punctuators as separators
1713 if (string.size() >= 10 && string[4].isPunct() && string[7].isPunct()
1714 && (string.size() == 10 || !string[10].isDigit())) {
1715 const ParsedInt year = readInt(string.first(4));
1716 const ParsedInt month = readInt(string.sliced(5, 2));
1717 const ParsedInt day = readInt(string.sliced(8, 2));
1718 if (year.ok() && year.result > 0 && year.result <= 9999 && month.ok() && day.ok())
1719 return QDate(year.result, month.result, day.result);
1720 }
1721 break;
1722 }
1723 return QDate();
1724}
1725
1726/*!
1727 \overload primary
1728 \fn QDate QDate::fromString(const QString &string, const QString &format, int baseYear, QCalendar cal)
1729
1730 Returns the QDate represented by the \a string, using the \a
1731 format given, or an invalid date if the string cannot be parsed.
1732
1733 Uses \a cal as calendar if supplied, else the Gregorian calendar. Ranges of
1734 values in the format descriptions below are for the latter; they may be
1735 different for other calendars.
1736
1737 These expressions may be used for the format:
1738
1739 \table
1740 \header \li Expression \li Output
1741 \row \li d \li The day as a number without a leading zero (1 to 31)
1742 \row \li dd \li The day as a number with a leading zero (01 to 31)
1743 \row \li ddd \li The abbreviated day name ('Mon' to 'Sun').
1744 \row \li dddd \li The long day name ('Monday' to 'Sunday').
1745 \row \li M \li The month as a number without a leading zero (1 to 12)
1746 \row \li MM \li The month as a number with a leading zero (01 to 12)
1747 \row \li MMM \li The abbreviated month name ('Jan' to 'Dec').
1748 \row \li MMMM \li The long month name ('January' to 'December').
1749 \row \li yy \li The year as a two digit number (00 to 99)
1750 \row \li yyyy \li The year as a four digit number, possibly plus a leading
1751 minus sign for negative years.
1752 \endtable
1753
1754 \note Day and month names must be given in English (C locale). If localized
1755 month and day names are to be recognized, use QLocale::system().toDate().
1756
1757 All other input characters will be treated as text. Any non-empty sequence
1758 of characters enclosed in single quotes will also be treated (stripped of
1759 the quotes) as text and not be interpreted as expressions. For example:
1760
1761 \snippet code/src_corelib_time_qdatetime.cpp 1
1762
1763 If the format is not satisfied, an invalid QDate is returned. The
1764 expressions that don't expect leading zeroes (d, M) will be
1765 greedy. This means that they will use two digits even if this
1766 will put them outside the accepted range of values and leaves too
1767 few digits for other sections. For example, the following format
1768 string could have meant January 30 but the M will grab two
1769 digits, resulting in an invalid date:
1770
1771 \snippet code/src_corelib_time_qdatetime.cpp 2
1772
1773 For any field that is not represented in the format the following
1774 defaults are used:
1775
1776 \table
1777 \header \li Field \li Default value
1778 \row \li Year \li \a baseYear (or 1900)
1779 \row \li Month \li 1 (January)
1780 \row \li Day \li 1
1781 \endtable
1782
1783 When \a format only specifies the last two digits of a year, the 100 years
1784 starting at \a baseYear are the candidates first considered. Prior to 6.7
1785 there was no \a baseYear parameter and 1900 was always used. This is the
1786 default for \a baseYear, selecting a year from then to 1999. Passing 1976 as
1787 \a baseYear will select a year from 1976 through 2075, for example. When the
1788 format also includes month, day (of month) and day-of-week, these suffice to
1789 imply the century. In such a case, a matching date is selected in the
1790 nearest century to the one indicated by \a baseYear, prefering later over
1791 earlier. See \l QCalendar::matchCenturyToWeekday() and \l {Date ambiguities}
1792 for further details,
1793
1794 The following examples demonstrate the default values:
1795
1796 \snippet code/src_corelib_time_qdatetime.cpp 3
1797
1798 \note If a format character is repeated more times than the longest
1799 expression in the table above using it, this part of the format will be read
1800 as several expressions with no separator between them; the longest above,
1801 possibly repeated as many times as there are copies of it, ending with a
1802 residue that may be a shorter expression. Thus \c{'MMMMMMMMMM'} would match
1803 \c{"MayMay05"} and set the month to May. Likewise, \c{'MMMMMM'} would match
1804 \c{"May08"} and find it inconsistent, leading to an invalid date.
1805
1806 \section2 Date ambiguities
1807
1808 Different cultures use different formats for dates and, as a result, users
1809 may mix up the order in which date fields should be given. For example,
1810 \c{"Wed 28-Nov-01"} might mean either 2028 November 1st or the 28th of
1811 November, 2001 (each of which happens to be a Wednesday). Using format
1812 \c{"ddd yy-MMM-dd"} it shall be interpreted the first way, using \c{"ddd
1813 dd-MMM-yy"} the second. However, which the user meant may depend on the way
1814 the user normally writes dates, rather than the format the code was
1815 expecting.
1816
1817 The example considered above mixed up day of the month and a two-digit year.
1818 Similar confusion can arise over interchanging the month and day of the
1819 month, when both are given as numbers. In these cases, including a day of
1820 the week field in the date format can provide some redundancy, that may help
1821 to catch errors of this kind. However, as in the example above, this is not
1822 always effective: the interchange of two fields (or their meanings) may
1823 produce dates with the same day of the week.
1824
1825 Including a day of the week in the format can also resolve the century of a
1826 date specified using only the last two digits of its year. Unfortunately,
1827 when combined with a date in which the user (or other source of data) has
1828 mixed up two of the fields, this resolution can lead to finding a date which
1829 does match the format's reading but isn't the one intended by its author.
1830 Likewise, if the user simply gets the day of the week wrong, in an otherwise
1831 correct date, this can lead a date in a different century. In each case,
1832 finding a date in a different century can turn a wrongly-input date into a
1833 wildly different one.
1834
1835 The best way to avoid date ambiguities is to use four-digit years and months
1836 specified by name (whether full or abbreviated), ideally collected via user
1837 interface idioms that make abundantly clear to the user which part of the
1838 date they are selecting. Including a day of the week can also help by
1839 providing the means to check consistency of the data. Where data comes from
1840 the user, using a format supplied by a locale selected by the user, it is
1841 best to use a long format as short formats are more likely to use two-digit
1842 years. Of course, it is not always possible to control the format - data may
1843 come from a source you do not control, for example.
1844
1845 As a result of these possible sources of confusion, particularly when you
1846 cannot be sure an unambiguous format is in use, it is important to check
1847 that the result of reading a string as a date is not just valid but
1848 reasonable for the purpose for which it was supplied. If the result is
1849 outside some range of reasonable values, it may be worth getting the user to
1850 confirm their date selection, showing the date read from the string in a
1851 long format that does include month name and four-digit year, to make it
1852 easier for them to recognize any errors.
1853
1854 \sa toString(), QDateTime::fromString(), QTime::fromString(),
1855 QLocale::toDate()
1856*/
1857
1858/*!
1859 \since 6.0
1860 \overload fromString()
1861 \fn QDate QDate::fromString(QStringView string, QStringView format, QCalendar cal)
1862*/
1863
1864/*!
1865 \since 6.0
1866 \overload fromString()
1867*/
1868QDate QDate::fromString(const QString &string, QStringView format, int baseYear, QCalendar cal)
1869{
1870 QDate date;
1871#if QT_CONFIG(datetimeparser)
1872 QDateTimeParser dt(QMetaType::QDate, QDateTimeParser::FromString, cal);
1873 dt.setDefaultLocale(QLocale::c());
1874 if (dt.parseFormat(format))
1875 dt.fromString(string, &date, nullptr, baseYear);
1876#else
1877 Q_UNUSED(string);
1878 Q_UNUSED(format);
1879 Q_UNUSED(baseYear);
1880 Q_UNUSED(cal);
1881#endif
1882 return date;
1883}
1884
1885/*!
1886 \since 5.14
1887 \overload fromString()
1888 \fn QDate QDate::fromString(const QString &string, const QString &format, QCalendar cal)
1889*/
1890
1891/*!
1892 \since 6.0
1893 \overload fromString()
1894 \fn QDate QDate::fromString(const QString &string, QStringView format, QCalendar cal)
1895*/
1896
1897/*!
1898 \since 6.7
1899 \overload fromString()
1900 \fn QDate QDate::fromString(QStringView string, QStringView format, int baseYear, QCalendar cal)
1901*/
1902
1903/*!
1904 \since 6.7
1905 \overload fromString()
1906 \fn QDate QDate::fromString(QStringView string, QStringView format, int baseYear)
1907
1908 Uses a default-constructed QCalendar.
1909*/
1910
1911/*!
1912 \since 6.7
1913 \overload fromString()
1914
1915 Uses a default-constructed QCalendar.
1916*/
1917QDate QDate::fromString(const QString &string, QStringView format, int baseYear)
1918{
1919 return fromString(string, format, baseYear, QCalendar());
1920}
1921
1922/*!
1923 \since 6.7
1924 \overload fromString()
1925 \fn QDate QDate::fromString(const QString &string, const QString &format, int baseYear)
1926
1927 Uses a default-constructed QCalendar.
1928*/
1929#endif // datestring
1930
1931/*!
1932 \overload isValid()
1933
1934 Returns \c true if the specified date (\a year, \a month, and \a day) is
1935 valid in the Gregorian calendar; otherwise returns \c false.
1936
1937 Example:
1938 \snippet code/src_corelib_time_qdatetime.cpp 4
1939
1940 \sa isNull(), setDate(), QCalendar::isDateValid()
1941*/
1942
1943bool QDate::isValid(int year, int month, int day)
1944{
1945 return QGregorianCalendar::validParts(year, month, day);
1946}
1947
1948/*!
1949 \fn bool QDate::isLeapYear(int year)
1950
1951 Returns \c true if the specified \a year is a leap year in the Gregorian
1952 calendar; otherwise returns \c false.
1953
1954 \sa QCalendar::isLeapYear()
1955*/
1956
1957bool QDate::isLeapYear(int y)
1958{
1959 return QGregorianCalendar::leapTest(y);
1960}
1961
1962/*! \fn static QDate QDate::fromJulianDay(qint64 jd)
1963
1964 Converts the Julian day \a jd to a QDate.
1965
1966 \sa toJulianDay()
1967*/
1968
1969/*! \fn int QDate::toJulianDay() const
1970
1971 Converts the date to a Julian day.
1972
1973 \sa fromJulianDay()
1974*/
1975
1976/*****************************************************************************
1977 QTime member functions
1978 *****************************************************************************/
1979
1980/*!
1981 \class QTime
1982 \inmodule QtCore
1983 \reentrant
1984
1985 \brief The QTime class provides clock time functions.
1986
1987 \compares strong
1988
1989 A QTime object contains a clock time, which it can express as the numbers of
1990 hours, minutes, seconds, and milliseconds since midnight. It provides
1991 functions for comparing times and for manipulating a time by adding a number
1992 of milliseconds. QTime objects should be passed by value rather than by
1993 reference to const; they simply package \c int.
1994
1995 QTime uses the 24-hour clock format; it has no concept of AM/PM.
1996 Unlike QDateTime, QTime knows nothing about time zones or
1997 daylight-saving time (DST).
1998
1999 A QTime object is typically created either by giving the number of hours,
2000 minutes, seconds, and milliseconds explicitly, or by using the static
2001 function currentTime(), which creates a QTime object that represents the
2002 system's local time.
2003
2004 The hour(), minute(), second(), and msec() functions provide
2005 access to the number of hours, minutes, seconds, and milliseconds
2006 of the time. The same information is provided in textual format by
2007 the toString() function.
2008
2009 The addSecs() and addMSecs() functions provide the time a given
2010 number of seconds or milliseconds later than a given time.
2011 Correspondingly, the number of seconds or milliseconds
2012 between two times can be found using secsTo() or msecsTo().
2013
2014 QTime provides a full set of operators to compare two QTime
2015 objects; an earlier time is considered smaller than a later one;
2016 if A.msecsTo(B) is positive, then A < B.
2017
2018 QTime objects can also be created from a text representation using
2019 fromString() and converted to a string representation using toString(). All
2020 conversion to and from string formats is done using the C locale. For
2021 localized conversions, see QLocale.
2022
2023 \sa QDate, QDateTime
2024*/
2025
2026/*!
2027 \fn QTime::QTime()
2028
2029 Constructs a null time object. For a null time, isNull() returns \c true and
2030 isValid() returns \c false. If you need a zero time, use QTime(0, 0). For
2031 the start of a day, see QDate::startOfDay().
2032
2033 \sa isNull(), isValid()
2034*/
2035
2036/*!
2037 Constructs a time with hour \a h, minute \a m, seconds \a s and
2038 milliseconds \a ms.
2039
2040 \a h must be in the range 0 to 23, \a m and \a s must be in the
2041 range 0 to 59, and \a ms must be in the range 0 to 999.
2042
2043 \sa isValid()
2044*/
2045
2046QTime::QTime(int h, int m, int s, int ms)
2047{
2048 setHMS(h, m, s, ms);
2049}
2050
2051
2052/*!
2053 \fn bool QTime::isNull() const
2054
2055 Returns \c true if the time is null (i.e., the QTime object was
2056 constructed using the default constructor); otherwise returns
2057 false. A null time is also an invalid time.
2058
2059 \sa isValid()
2060*/
2061
2062/*!
2063 \overload primary
2064
2065 Returns \c true if the time is valid; otherwise returns \c false. For example,
2066 the time 23:30:55.746 is valid, but 24:12:30 is invalid.
2067
2068 \sa isNull()
2069*/
2070
2071bool QTime::isValid() const
2072{
2073 return mds > NullTime && mds < MSECS_PER_DAY;
2074}
2075
2076
2077/*!
2078 Returns the hour part (0 to 23) of the time.
2079
2080 Returns -1 if the time is invalid.
2081
2082 \sa minute(), second(), msec()
2083*/
2084
2085int QTime::hour() const
2086{
2087 if (!isValid())
2088 return -1;
2089
2090 return ds() / MSECS_PER_HOUR;
2091}
2092
2093/*!
2094 Returns the minute part (0 to 59) of the time.
2095
2096 Returns -1 if the time is invalid.
2097
2098 \sa hour(), second(), msec()
2099*/
2100
2101int QTime::minute() const
2102{
2103 if (!isValid())
2104 return -1;
2105
2106 return (ds() % MSECS_PER_HOUR) / MSECS_PER_MIN;
2107}
2108
2109/*!
2110 Returns the second part (0 to 59) of the time.
2111
2112 Returns -1 if the time is invalid.
2113
2114 \sa hour(), minute(), msec()
2115*/
2116
2117int QTime::second() const
2118{
2119 if (!isValid())
2120 return -1;
2121
2122 return (ds() / MSECS_PER_SEC) % SECS_PER_MIN;
2123}
2124
2125/*!
2126 Returns the millisecond part (0 to 999) of the time.
2127
2128 Returns -1 if the time is invalid.
2129
2130 \sa hour(), minute(), second()
2131*/
2132
2133int QTime::msec() const
2134{
2135 if (!isValid())
2136 return -1;
2137
2138 return ds() % MSECS_PER_SEC;
2139}
2140
2141#if QT_CONFIG(datestring) // depends on, so implies, textdate
2142/*!
2143 \overload toString()
2144
2145 Returns the time as a string. The \a format parameter determines
2146 the format of the string.
2147
2148 If \a format is Qt::TextDate, the string format is HH:mm:ss;
2149 e.g. 1 second before midnight would be "23:59:59".
2150
2151 If \a format is Qt::ISODate, the string format corresponds to the
2152 ISO 8601 extended specification for representations of dates,
2153 represented by HH:mm:ss. To include milliseconds in the ISO 8601
2154 date, use the \a format Qt::ISODateWithMs, which corresponds to
2155 HH:mm:ss.zzz.
2156
2157 If the \a format is Qt::RFC2822Date, the string is formatted in
2158 an \l{RFC 2822} compatible way. An example of this formatting is
2159 "23:59:20".
2160
2161 If the time is invalid, an empty string will be returned.
2162
2163 \sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
2164*/
2165
2166QString QTime::toString(Qt::DateFormat format) const
2167{
2168 if (!isValid())
2169 return QString();
2170
2171 switch (format) {
2172 case Qt::ISODateWithMs:
2173 return QString::asprintf("%02d:%02d:%02d.%03d", hour(), minute(), second(), msec());
2174 case Qt::RFC2822Date:
2175 case Qt::ISODate:
2176 case Qt::TextDate:
2177 default:
2178 return QString::asprintf("%02d:%02d:%02d", hour(), minute(), second());
2179 }
2180}
2181
2182/*!
2183 \overload primary
2184 \fn QString QTime::toString(const QString &format) const
2185 \fn QString QTime::toString(QStringView format) const
2186
2187 Returns a string representing the time.
2188
2189 The \a format parameter determines the format of the result string. If the
2190 time is invalid, an empty string will be returned.
2191
2192 These expressions may be used:
2193
2194 \table
2195 \header \li Expression \li Output
2196 \row \li h
2197 \li The hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
2198 \row \li hh
2199 \li The hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
2200 \row \li H
2201 \li The hour without a leading zero (0 to 23, even with AM/PM display)
2202 \row \li HH
2203 \li The hour with a leading zero (00 to 23, even with AM/PM display)
2204 \row \li m \li The minute without a leading zero (0 to 59)
2205 \row \li mm \li The minute with a leading zero (00 to 59)
2206 \row \li s \li The whole second, without any leading zero (0 to 59)
2207 \row \li ss \li The whole second, with a leading zero where applicable (00 to 59)
2208 \row \li z or zz
2209 \li The fractional part of the second, to go after a decimal point,
2210 without trailing zeroes. Thus \c{"s.z"} reports the seconds to full
2211 available (millisecond) precision without trailing zeroes (0 to
2212 999). For example, \c{"s.z"} would produce \c{"0.25"} for a time a
2213 quarter second into a minute.
2214 \row \li zzz
2215 \li The fractional part of the second, to millisecond precision,
2216 including trailing zeroes where applicable (000 to 999). For
2217 example, \c{"ss.zzz"} would produce \c{"00.250"} for a time a
2218 quarter second into a minute.
2219 \row \li AP or A
2220 \li Use AM/PM display. \c A/AP will be replaced by 'AM' or 'PM'. In
2221 localized forms (only relevant to \l{QLocale::toString()}), the
2222 locale-appropriate text is converted to upper-case.
2223 \row \li ap or a
2224 \li Use am/pm display. \c a/ap will be replaced by 'am' or 'pm'. In
2225 localized forms (only relevant to \l{QLocale::toString()}), the
2226 locale-appropriate text is converted to lower-case.
2227 \row \li aP or Ap
2228 \li Use AM/PM display (since 6.3). \c aP/Ap will be replaced by 'AM' or
2229 'PM'. In localized forms (only relevant to
2230 \l{QLocale::toString()}), the locale-appropriate text (returned by
2231 \l{QLocale::amText()} or \l{QLocale::pmText()}) is used without
2232 change of case.
2233 \row \li t
2234 \li The timezone abbreviation (for example "CEST"). Note that time zone
2235 abbreviations are not unique. In particular, \l fromString() cannot
2236 parse this.
2237 \row \li tt
2238 \li The timezone's offset from UTC with no colon between the hours and
2239 minutes (for example "+0200").
2240 \row \li ttt
2241 \li The timezone's offset from UTC with a colon between the hours and
2242 minutes (for example "+02:00").
2243 \row \li tttt
2244 \li The timezone name, as provided by \l QTimeZone::displayName() with
2245 the \l QTimeZone::LongName type. This may depend on the operating
2246 system in use. If no such name is available, the IANA ID of the
2247 zone (such as "Europe/Berlin") may be used. It may give no
2248 indication of whether the datetime was in daylight-saving time or
2249 standard time, which may lead to ambiguity if the datetime falls in
2250 an hour repeated by a transition between the two.
2251 \endtable
2252
2253 \note To get localized forms of AM or PM (the \c{AP}, \c{ap}, \c{A}, \c{a},
2254 \c{aP} or \c{Ap} formats) or of time zone representations (the \c{t}
2255 formats), use QLocale::system().toString().
2256
2257 When the timezone cannot be determined or no suitable representation of it
2258 is available, the \c{t} forms to represent it may be skipped. See \l
2259 QTimeZone::displayName() for details of when it returns an empty string.
2260
2261 Any non-empty sequence of characters enclosed in single quotes will be
2262 included verbatim in the output string (stripped of the quotes), even if it
2263 contains formatting characters. Two consecutive single quotes ("''") are
2264 replaced by a single quote in the output. All other characters in the format
2265 string are included verbatim in the output string.
2266
2267 Formats without separators (e.g. "hhmm") are supported but must be used with
2268 care, as the resulting strings aren't always reliably readable (e.g. if "Hm"
2269 produces "212" it could mean either 02:12 or 21:02).
2270
2271 Example format strings (assuming that the QTime is 14:13:09.042)
2272
2273 \table
2274 \header \li Format \li Result
2275 \row \li hh:mm:ss.zzz \li 14:13:09.042
2276 \row \li h:m:s ap \li 2:13:9 pm
2277 \row \li H:m:s a \li 14:13:9 pm
2278 \endtable
2279
2280 \note If a format character is repeated more times than the longest
2281 expression in the table above using it, this part of the format will be read
2282 as several expressions with no separator between them; the longest above,
2283 possibly repeated as many times as there are copies of it, ending with a
2284 residue that may be a shorter expression. Thus \c{'HHHHH'} for the time
2285 08:00 will contribute \c{"08088"} to the output.
2286
2287 \sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
2288*/
2289QString QTime::toString(QStringView format) const
2290{
2291 return QLocale::c().toString(*this, format);
2292}
2293// ### Qt 7 The 't' format specifiers should be specific to QDateTime (compare fromString).
2294#endif // datestring
2295
2296/*!
2297 Sets the time to hour \a h, minute \a m, seconds \a s and
2298 milliseconds \a ms.
2299
2300 \a h must be in the range 0 to 23, \a m and \a s must be in the
2301 range 0 to 59, and \a ms must be in the range 0 to 999.
2302 Returns \c true if the set time is valid; otherwise returns \c false.
2303
2304 \sa isValid()
2305*/
2306
2307bool QTime::setHMS(int h, int m, int s, int ms)
2308{
2309 if (!isValid(h,m,s,ms)) {
2310 mds = NullTime; // make this invalid
2311 return false;
2312 }
2313 mds = ((h * MINS_PER_HOUR + m) * SECS_PER_MIN + s) * MSECS_PER_SEC + ms;
2314 Q_ASSERT(mds >= 0 && mds < MSECS_PER_DAY);
2315 return true;
2316}
2317
2318/*!
2319 Returns a QTime object containing a time \a s seconds later
2320 than the time of this object (or earlier if \a s is negative).
2321
2322 Note that the time will wrap if it passes midnight.
2323
2324 Returns a null time if this time is invalid.
2325
2326 Example:
2327
2328 \snippet code/src_corelib_time_qdatetime.cpp 5
2329
2330 \sa addMSecs(), secsTo(), QDateTime::addSecs()
2331*/
2332
2333QTime QTime::addSecs(int s) const
2334{
2335 s %= SECS_PER_DAY;
2336 return addMSecs(s * MSECS_PER_SEC);
2337}
2338
2339/*!
2340 Returns the number of seconds from this time to \a t.
2341 If \a t is earlier than this time, the number of seconds returned
2342 is negative.
2343
2344 Because QTime measures time within a day and there are 86400
2345 seconds in a day, the result is always between -86400 and 86400.
2346
2347 secsTo() does not take into account any milliseconds.
2348
2349 Returns 0 if either time is invalid.
2350
2351 \sa addSecs(), QDateTime::secsTo()
2352*/
2353
2354int QTime::secsTo(QTime t) const
2355{
2356 if (!isValid() || !t.isValid())
2357 return 0;
2358
2359 // Truncate milliseconds as we do not want to consider them.
2360 int ourSeconds = ds() / MSECS_PER_SEC;
2361 int theirSeconds = t.ds() / MSECS_PER_SEC;
2362 return theirSeconds - ourSeconds;
2363}
2364
2365/*!
2366 Returns a QTime object containing a time \a ms milliseconds later
2367 than the time of this object (or earlier if \a ms is negative).
2368
2369 Note that the time will wrap if it passes midnight. See addSecs()
2370 for an example.
2371
2372 Returns a null time if this time is invalid.
2373
2374 \sa addSecs(), msecsTo(), QDateTime::addMSecs()
2375*/
2376
2377QTime QTime::addMSecs(int ms) const
2378{
2379 QTime t;
2380 if (isValid())
2381 t.mds = QRoundingDown::qMod<MSECS_PER_DAY>(ds() + ms);
2382 return t;
2383}
2384
2385/*!
2386 Returns the number of milliseconds from this time to \a t.
2387 If \a t is earlier than this time, the number of milliseconds returned
2388 is negative.
2389
2390 Because QTime measures time within a day and there are 86400
2391 seconds in a day, the result is always between -86400000 and
2392 86400000 ms.
2393
2394 Returns 0 if either time is invalid.
2395
2396 \sa secsTo(), addMSecs(), QDateTime::msecsTo()
2397*/
2398
2399int QTime::msecsTo(QTime t) const
2400{
2401 if (!isValid() || !t.isValid())
2402 return 0;
2403 return t.ds() - ds();
2404}
2405
2406
2407/*!
2408 \fn bool QTime::operator==(const QTime &lhs, const QTime &rhs)
2409
2410 Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false.
2411*/
2412
2413/*!
2414 \fn bool QTime::operator!=(const QTime &lhs, const QTime &rhs)
2415
2416 Returns \c true if \a lhs is different from \a rhs; otherwise returns \c false.
2417*/
2418
2419/*!
2420 \fn bool QTime::operator<(const QTime &lhs, const QTime &rhs)
2421
2422 Returns \c true if \a lhs is earlier than \a rhs; otherwise returns \c false.
2423*/
2424
2425/*!
2426 \fn bool QTime::operator<=(const QTime &lhs, const QTime &rhs)
2427
2428 Returns \c true if \a lhs is earlier than or equal to \a rhs;
2429 otherwise returns \c false.
2430*/
2431
2432/*!
2433 \fn bool QTime::operator>(const QTime &lhs, const QTime &rhs)
2434
2435 Returns \c true if \a lhs is later than \a rhs; otherwise returns \c false.
2436*/
2437
2438/*!
2439 \fn bool QTime::operator>=(const QTime &lhs, const QTime &rhs)
2440
2441 Returns \c true if \a lhs is later than or equal to \a rhs;
2442 otherwise returns \c false.
2443*/
2444
2445/*!
2446 \fn QTime QTime::fromMSecsSinceStartOfDay(int msecs)
2447
2448 Returns a new QTime instance with the time set to the number of \a msecs
2449 since the start of the day, i.e. since 00:00:00.
2450
2451 If \a msecs falls outside the valid range an invalid QTime will be returned.
2452
2453 \sa msecsSinceStartOfDay()
2454*/
2455
2456/*!
2457 \fn int QTime::msecsSinceStartOfDay() const
2458
2459 Returns the number of msecs since the start of the day, i.e. since 00:00:00.
2460
2461 \sa fromMSecsSinceStartOfDay()
2462*/
2463
2464/*!
2465 \fn QTime::currentTime()
2466
2467 Returns the current time as reported by the system clock.
2468
2469 Note that the accuracy depends on the accuracy of the underlying
2470 operating system; not all systems provide 1-millisecond accuracy.
2471
2472 Furthermore, currentTime() only increases within each day; it shall drop by
2473 24 hours each time midnight passes; and, beside this, changes in it may not
2474 correspond to elapsed time, if a daylight-saving transition intervenes.
2475
2476 \sa QDateTime::currentDateTime(), QDateTime::currentDateTimeUtc()
2477*/
2478
2479#if QT_CONFIG(datestring) // depends on, so implies, textdate
2480
2481static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *isMidnight24)
2482{
2483 Q_ASSERT(format == Qt::TextDate || format == Qt::ISODate || format == Qt::ISODateWithMs);
2484 if (isMidnight24)
2485 *isMidnight24 = false;
2486 // Match /\d\d(:\d\d(:\d\d)?)?([,.]\d+)?/ as "HH[:mm[:ss]][.zzz]"
2487 // The fractional part, if present, is in the same units as the field it follows.
2488 // TextDate restricts fractional parts to the seconds field.
2489
2490 QStringView tail;
2491 const qsizetype dot = string.indexOf(u'.'), comma = string.indexOf(u',');
2492 if (dot != -1) {
2493 tail = string.sliced(dot + 1);
2494 if (tail.indexOf(u'.') != -1) // Forbid second dot:
2495 return QTime();
2496 string = string.first(dot);
2497 } else if (comma != -1) {
2498 tail = string.sliced(comma + 1);
2499 string = string.first(comma);
2500 }
2501 if (tail.indexOf(u',') != -1) // Forbid comma after first dot-or-comma:
2502 return QTime();
2503
2504 const ParsedInt frac = readInt(tail);
2505 // There must be *some* digits in a fractional part; and it must be all digits:
2506 if (tail.isEmpty() ? dot != -1 || comma != -1 : !frac.ok())
2507 return QTime();
2508 Q_ASSERT(frac.ok() ^ tail.isEmpty());
2509 double fraction = frac.ok() ? frac.result * std::pow(0.1, tail.size()) : 0.0;
2510
2511 const qsizetype size = string.size();
2512 if (size < 2 || size > 8)
2513 return QTime();
2514
2515 ParsedInt hour = readInt(string.first(2));
2516 if (!hour.ok() || hour.result > (format == Qt::TextDate ? 23 : 24))
2517 return QTime();
2518
2519 ParsedInt minute{};
2520 if (string.size() > 2) {
2521 if (string[2] == u':' && string.size() > 4)
2522 minute = readInt(string.sliced(3, 2));
2523 if (!minute.ok() || minute.result >= MINS_PER_HOUR)
2524 return QTime();
2525 } else if (format == Qt::TextDate) { // Requires minutes
2526 return QTime();
2527 } else if (frac.ok()) {
2528 Q_ASSERT(!(fraction < 0.0) && fraction < 1.0);
2529 fraction *= MINS_PER_HOUR;
2530 minute.result = qulonglong(fraction);
2531 fraction -= minute.result;
2532 }
2533
2534 ParsedInt second{};
2535 if (string.size() > 5) {
2536 if (string[5] == u':' && string.size() == 8)
2537 second = readInt(string.sliced(6, 2));
2538 if (!second.ok() || second.result >= SECS_PER_MIN)
2539 return QTime();
2540 } else if (frac.ok()) {
2541 if (format == Qt::TextDate) // Doesn't allow fraction of minutes
2542 return QTime();
2543 Q_ASSERT(!(fraction < 0.0) && fraction < 1.0);
2544 fraction *= SECS_PER_MIN;
2545 second.result = qulonglong(fraction);
2546 fraction -= second.result;
2547 }
2548
2549 Q_ASSERT(!(fraction < 0.0) && fraction < 1.0);
2550 // Round millis to nearest (unlike minutes and seconds, rounded down):
2551 int msec = frac.ok() ? qRound(MSECS_PER_SEC * fraction) : 0;
2552 // But handle overflow gracefully:
2553 if (msec == MSECS_PER_SEC) {
2554 // If we can (when data were otherwise valid) validly propagate overflow
2555 // into other fields, do so:
2556 if (isMidnight24 || hour.result < 23 || minute.result < 59 || second.result < 59) {
2557 msec = 0;
2558 if (++second.result == SECS_PER_MIN) {
2559 second.result = 0;
2560 if (++minute.result == MINS_PER_HOUR) {
2561 minute.result = 0;
2562 ++hour.result;
2563 // May need to propagate further via isMidnight24, see below
2564 }
2565 }
2566 } else {
2567 // QTime::fromString() or Qt::TextDate: rounding up would cause
2568 // 23:59:59.999... to become invalid; clip to 999 ms instead:
2569 msec = MSECS_PER_SEC - 1;
2570 }
2571 }
2572
2573 // For ISO date format, 24:0:0 means 0:0:0 on the next day:
2574 if (hour.result == 24 && minute.result == 0 && second.result == 0 && msec == 0) {
2575 Q_ASSERT(format != Qt::TextDate); // It clipped hour at 23, above.
2576 if (isMidnight24)
2577 *isMidnight24 = true;
2578 hour.result = 0;
2579 }
2580
2581 return QTime(hour.result, minute.result, second.result, msec);
2582}
2583
2584/*!
2585 \overload
2586 \fn QTime QTime::fromString(const QString &string, Qt::DateFormat format)
2587
2588 Returns the time represented in the \a string as a QTime using the
2589 \a format given, or an invalid time if this is not possible.
2590
2591 \sa toString(), QLocale::toTime()
2592*/
2593
2594/*!
2595 \since 6.0
2596 \overload fromString()
2597*/
2598QTime QTime::fromString(QStringView string, Qt::DateFormat format)
2599{
2600 if (string.isEmpty())
2601 return QTime();
2602
2603 switch (format) {
2604 case Qt::RFC2822Date:
2605 return rfcDateImpl(string).time;
2606 case Qt::ISODate:
2607 case Qt::ISODateWithMs:
2608 case Qt::TextDate:
2609 default:
2610 return fromIsoTimeString(string, format, nullptr);
2611 }
2612}
2613
2614/*!
2615 \overload primary
2616 \fn QTime QTime::fromString(const QString &string, const QString &format)
2617
2618 Returns the QTime represented by the \a string, using the \a
2619 format given, or an invalid time if the string cannot be parsed.
2620
2621 These expressions may be used for the format:
2622
2623 \table
2624 \header \li Expression \li Output
2625 \row \li h
2626 \li The hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
2627 \row \li hh
2628 \li The hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
2629 \row \li H
2630 \li The hour without a leading zero (0 to 23, even with AM/PM display)
2631 \row \li HH
2632 \li The hour with a leading zero (00 to 23, even with AM/PM display)
2633 \row \li m \li The minute without a leading zero (0 to 59)
2634 \row \li mm \li The minute with a leading zero (00 to 59)
2635 \row \li s \li The whole second, without any leading zero (0 to 59)
2636 \row \li ss \li The whole second, with a leading zero where applicable (00 to 59)
2637 \row \li z or zz
2638 \li The fractional part of the second, as would usually follow a
2639 decimal point, without requiring trailing zeroes (0 to 999). Thus
2640 \c{"s.z"} matches the seconds with up to three digits of fractional
2641 part supplying millisecond precision, without needing trailing
2642 zeroes. For example, \c{"s.z"} would recognize either \c{"00.250"}
2643 or \c{"0.25"} as representing a time a quarter second into its
2644 minute.
2645 \row \li zzz
2646 \li Three digit fractional part of the second, to millisecond
2647 precision, including trailing zeroes where applicable (000 to 999).
2648 For example, \c{"ss.zzz"} would reject \c{"0.25"} but recognize
2649 \c{"00.250"} as representing a time a quarter second into its
2650 minute.
2651 \row \li AP, A, ap, a, aP or Ap
2652 \li Either 'AM' indicating a time before 12:00 or 'PM' for later times,
2653 matched case-insensitively.
2654 \endtable
2655
2656 All other input characters will be treated as text. Any non-empty sequence
2657 of characters enclosed in single quotes will also be treated (stripped of
2658 the quotes) as text and not be interpreted as expressions.
2659
2660 \snippet code/src_corelib_time_qdatetime.cpp 6
2661
2662 If the format is not satisfied, an invalid QTime is returned.
2663 Expressions that do not expect leading zeroes to be given (h, m, s
2664 and z) are greedy. This means that they will use two digits (or three, for z) even if
2665 this puts them outside the range of accepted values and leaves too
2666 few digits for other sections. For example, the following string
2667 could have meant 00:07:10, but the m will grab two digits, resulting
2668 in an invalid time:
2669
2670 \snippet code/src_corelib_time_qdatetime.cpp 7
2671
2672 Any field that is not represented in the format will be set to zero.
2673 For example:
2674
2675 \snippet code/src_corelib_time_qdatetime.cpp 8
2676
2677 \note If localized forms of am or pm (the AP, ap, Ap, aP, A or a formats)
2678 are to be recognized, use QLocale::system().toTime().
2679
2680 \note If a format character is repeated more times than the longest
2681 expression in the table above using it, this part of the format will be read
2682 as several expressions with no separator between them; the longest above,
2683 possibly repeated as many times as there are copies of it, ending with a
2684 residue that may be a shorter expression. Thus \c{'HHHHH'} would match
2685 \c{"08088"} or \c{"080808"} and set the hour to 8; if the time string
2686 contained "070809" it would "match" but produce an inconsistent result,
2687 leading to an invalid time.
2688
2689 \sa toString(), QDateTime::fromString(), QDate::fromString(),
2690 QLocale::toTime(), QLocale::toDateTime()
2691*/
2692
2693/*!
2694 \since 6.0
2695 \overload fromString()
2696 \fn QTime QTime::fromString(QStringView string, QStringView format)
2697*/
2698
2699/*!
2700 \since 6.0
2701 \overload fromString()
2702*/
2703QTime QTime::fromString(const QString &string, QStringView format)
2704{
2705 QTime time;
2706#if QT_CONFIG(datetimeparser)
2707 QDateTimeParser dt(QMetaType::QTime, QDateTimeParser::FromString, QCalendar());
2708 dt.setDefaultLocale(QLocale::c());
2709 if (dt.parseFormat(format))
2710 dt.fromString(string, nullptr, &time);
2711#else
2712 Q_UNUSED(string);
2713 Q_UNUSED(format);
2714#endif
2715 return time;
2716}
2717#endif // datestring
2718
2719
2720/*!
2721 \overload isValid()
2722
2723 Returns \c true if the specified time is valid; otherwise returns
2724 false.
2725
2726 The time is valid if \a h is in the range 0 to 23, \a m and
2727 \a s are in the range 0 to 59, and \a ms is in the range 0 to 999.
2728
2729 Example:
2730
2731 \snippet code/src_corelib_time_qdatetime.cpp 9
2732*/
2733
2734bool QTime::isValid(int h, int m, int s, int ms)
2735{
2736 return (uint(h) < 24 && uint(m) < MINS_PER_HOUR && uint(s) < SECS_PER_MIN
2737 && uint(ms) < MSECS_PER_SEC);
2738}
2739
2740/*****************************************************************************
2741 QDateTime static helper functions
2742 *****************************************************************************/
2743
2744// get the types from QDateTime (through QDateTimePrivate)
2747
2748// Converts milliseconds since the start of 1970 into a date and/or time:
2749static qint64 msecsToJulianDay(qint64 msecs)
2750{
2751 return JULIAN_DAY_FOR_EPOCH + QRoundingDown::qDiv<MSECS_PER_DAY>(msecs);
2752}
2753
2754static QDate msecsToDate(qint64 msecs)
2755{
2756 return QDate::fromJulianDay(msecsToJulianDay(msecs));
2757}
2758
2759static QTime msecsToTime(qint64 msecs)
2760{
2761 return QTime::fromMSecsSinceStartOfDay(QRoundingDown::qMod<MSECS_PER_DAY>(msecs));
2762}
2763
2764// True if combining days with millis overflows; otherwise, stores result in *sumMillis
2765// The inputs should not have opposite signs.
2766static inline bool daysAndMillisOverflow(qint64 days, qint64 millisInDay, qint64 *sumMillis)
2767{
2768 return qMulOverflow(days, std::integral_constant<qint64, MSECS_PER_DAY>(), sumMillis)
2769 || qAddOverflow(*sumMillis, millisInDay, sumMillis);
2770}
2771
2772// Converts a date/time value into msecs
2773static qint64 timeToMSecs(QDate date, QTime time)
2774{
2775 qint64 days = date.toJulianDay() - JULIAN_DAY_FOR_EPOCH;
2776 qint64 msecs, dayms = time.msecsSinceStartOfDay();
2777 if (days < 0 && dayms > 0) {
2778 ++days;
2779 dayms -= MSECS_PER_DAY;
2780 }
2781 if (daysAndMillisOverflow(days, dayms, &msecs)) {
2782 using Bound = std::numeric_limits<qint64>;
2783 return days < 0 ? Bound::min() : Bound::max();
2784 }
2785 return msecs;
2786}
2787
2788/*!
2789 \internal
2790 Tests whether system functions can handle a given time.
2791
2792 The range of milliseconds for which the time_t-based functions work depends
2793 somewhat on platform (see computeSystemMillisRange() for details). This
2794 function tests whether the UTC time \a millis milliseconds from the epoch is
2795 in the supported range.
2796
2797 To test a local time, pass an upper bound on the magnitude of time-zone
2798 correction potentially needed as \a slack: in this case the range is
2799 extended by this many milliseconds at each end (where applicable). The
2800 function then returns true precisely if \a millis is within this (possibly)
2801 widened range. This doesn't guarantee that the time_t functions can handle
2802 the time, so check their returns to be sure. Values for which the function
2803 returns false should be assumed unrepresentable.
2804*/
2805static inline bool millisInSystemRange(qint64 millis, qint64 slack = 0)
2806{
2807 static const auto bounds = QLocalTime::computeSystemMillisRange();
2808 return (bounds.minClip || millis >= bounds.min - slack)
2809 && (bounds.maxClip || millis <= bounds.max + slack);
2810}
2811
2812/*!
2813 \internal
2814 Returns a year, in the system range, with the same day-of-week pattern
2815
2816 Returns the number of a year, in the range supported by system time_t
2817 functions, that starts and ends on the same days of the week as \a year.
2818 This implies it is a leap year precisely if \a year is. If year is before
2819 the epoch, a year early in the supported range is used; otherwise, one late
2820 in that range. For a leap year, this may be as much as 26 years years from
2821 the range's relevant end; for normal years at most a decade from the end.
2822
2823 This ensures that any DST rules based on, e.g., the last Sunday in a
2824 particular month will select the same date in the returned year as they
2825 would if applied to \a year. Of course, the zone's rules may be different in
2826 \a year than in the selected year, but it's hard to do better.
2827*/
2828static int systemTimeYearMatching(int year)
2829{
2830#if defined(Q_OS_WIN) || defined(Q_OS_WASM)// They don't support times before the epoch
2831 static constexpr int forLeapEarly[] = { 1984, 1996, 1980, 1992, 1976, 1988, 1972 };
2832 static constexpr int regularEarly[] = { 1978, 1973, 1974, 1975, 1970, 1971, 1977 };
2833#else // First year fully in 32-bit time_t range is 1902
2834 static constexpr int forLeapEarly[] = { 1928, 1912, 1924, 1908, 1920, 1904, 1916 };
2835 static constexpr int regularEarly[] = { 1905, 1906, 1907, 1902, 1903, 1909, 1910 };
2836#endif
2837 static constexpr int forLeapLate[] = { 2012, 2024, 2036, 2020, 2032, 2016, 2028 };
2838 static constexpr int regularLate[] = { 2034, 2035, 2030, 2031, 2037, 2027, 2033 };
2839 const int dow = QGregorianCalendar::yearStartWeekDay(year);
2840 Q_ASSERT(dow == QDate(year, 1, 1).dayOfWeek());
2841 const int res = (QGregorianCalendar::leapTest(year)
2842 ? (year < 1970 ? forLeapEarly : forLeapLate)
2843 : (year < 1970 ? regularEarly : regularLate))[dow == 7 ? 0 : dow];
2844 Q_ASSERT(QDate(res, 1, 1).dayOfWeek() == dow);
2845 Q_ASSERT(QDate(res, 12, 31).dayOfWeek() == QDate(year, 12, 31).dayOfWeek());
2846 return res;
2847}
2848
2849// Sets up d and status to represent local time at the given UTC msecs since epoch:
2850QDateTimePrivate::ZoneState QDateTimePrivate::expressUtcAsLocal(qint64 utcMSecs)
2851{
2852 ZoneState result{utcMSecs};
2853 // Within the time_t supported range, localtime() can handle it:
2854 if (millisInSystemRange(utcMSecs)) {
2855 result = QLocalTime::utcToLocal(utcMSecs);
2856 if (result.valid)
2857 return result;
2858 }
2859
2860 // Docs state any LocalTime after 2038-01-18 *will* have any DST applied.
2861 // When this falls outside the supported range, we need to fake it.
2862#if QT_CONFIG(timezone) // Use the system time-zone.
2863 if (const auto sys = QTimeZone::systemTimeZone(); sys.isValid()) {
2864 result.offset = sys.d->offsetFromUtc(utcMSecs);
2865 if (result.offset != QTimeZonePrivate::invalidSeconds()) {
2866 if (qAddOverflow(utcMSecs, result.offset * MSECS_PER_SEC, &result.when))
2867 return result;
2868 result.dst = sys.d->isDaylightTime(utcMSecs) ? DaylightTime : StandardTime;
2869 result.valid = true;
2870 return result;
2871 }
2872 }
2873#endif // timezone
2874
2875 // Kludge
2876 // Do the conversion in a year with the same days of the week, so DST
2877 // dates might be right, and adjust by the number of days that was off:
2878 const qint64 jd = msecsToJulianDay(utcMSecs);
2879 const auto ymd = QGregorianCalendar::partsFromJulian(jd);
2880 qint64 diffMillis, fakeUtc;
2881 const auto fakeJd = QGregorianCalendar::julianFromParts(systemTimeYearMatching(ymd.year),
2882 ymd.month, ymd.day);
2883 if (Q_UNLIKELY(!fakeJd
2884 || qMulOverflow(jd - *fakeJd, std::integral_constant<qint64, MSECS_PER_DAY>(),
2885 &diffMillis)
2886 || qSubOverflow(utcMSecs, diffMillis, &fakeUtc))) {
2887 return result;
2888 }
2889
2890 result = QLocalTime::utcToLocal(fakeUtc);
2891 // Now correct result.when for the use of the fake date:
2892 if (!result.valid || qAddOverflow(result.when, diffMillis, &result.when)) {
2893 // If utcToLocal() failed, its return has the fake when; restore utcMSecs.
2894 // Fail on overflow, but preserve offset and DST-ness.
2895 result.when = utcMSecs;
2896 result.valid = false;
2897 }
2898 return result;
2899}
2900
2901static auto millisToWithinRange(qint64 millis)
2902{
2903 struct R {
2904 qint64 shifted = 0;
2905 bool good = false;
2906 } result;
2907 qint64 jd = msecsToJulianDay(millis);
2908 auto ymd = QGregorianCalendar::partsFromJulian(jd);
2909 const auto fakeJd = QGregorianCalendar::julianFromParts(systemTimeYearMatching(ymd.year),
2910 ymd.month, ymd.day);
2911 result.good = fakeJd && !daysAndMillisOverflow(*fakeJd - jd, millis, &result.shifted);
2912 return result;
2913}
2914
2915/*!
2916 \internal
2917 \enum QDateTimePrivate::TransitionOption
2918
2919 This enumeration is used to resolve datetime combinations which fall in \l
2920 {Timezone transitions}. The transition is described as a "gap" if there are
2921 time representations skipped over by the zone, as is common in the "spring
2922 forward" transitions in many zones on entering daylight-saving time. The
2923 transition is described as a "fold" if there are time representations
2924 repeated in the zone, as in a "fall back" transition out of daylight-saving
2925 time.
2926
2927 When the options specified do not determine a resolution for a datetime, it
2928 is marked invalid.
2929
2930 The prepared option sets above are in fact composed from low-level atomic
2931 options. For each of gap and fold you can chose between two candidate times,
2932 one before or after the transition, based on the time requested; or you can
2933 pick the moment of transition, or the start or end of the transition
2934 interval. For a gap, the start and end of the interval are the moment of the
2935 transition, but for a repeated interval the start of the first pass is the
2936 start of the transition interval, the end of the second pass is the end of
2937 the transition interval and the moment of the transition itself is both the
2938 end of the first pass and the start of the second.
2939
2940 \value GapUseBefore For a time in a gap, use a time before the transition,
2941 as if stepping back from a later time.
2942 \value GapUseAfter For a time in a gap, use a time after the transition, as
2943 if stepping forward from an earlier time.
2944 \value FoldUseBefore For a repeated time, use the first candidate, which is
2945 before the transition.
2946 \value FoldUseAfter For a repeated time, use the second candidate, which is
2947 after the transition.
2948 \value FlipForReverseDst For "reversed" DST, this reverses the preceding
2949 four options (see below).
2950
2951 The last has no effect unless the "daylight-saving" time side of the
2952 transition is known to have a lower offset from UTC than the standard time
2953 side. (This is the "reversed" DST case of \l {Timezone transitions}.) In
2954 that case, if other options would select a time after the transition, a time
2955 before is used instead, and vice versa. This effectively turns a preference
2956 for the side with lower offset into a preference for the side that is
2957 officially standard time, even if it has higher offset; and conversely a
2958 preference for higher offset into a preference for daylight-saving time,
2959 even if it has a lower offset. This option has no effect on a resolution
2960 that selects the moment of transition or the start or end of the transition
2961 interval.
2962
2963 The result of combining more than one of the \c GapUse* options is
2964 undefined; likewise for the \c FoldUse*. Each of QDateTime's
2965 TransitionResolution values, aside from Reject, maps to a combination that
2966 incorporates one from each of these sets.
2967*/
2968
2969constexpr static QDateTimePrivate::TransitionOptions
2970toTransitionOptions(QDateTime::TransitionResolution res)
2971{
2972 switch (res) {
2973 case QDateTime::TransitionResolution::RelativeToBefore:
2974 return QDateTimePrivate::GapUseAfter | QDateTimePrivate::FoldUseBefore;
2975 case QDateTime::TransitionResolution::RelativeToAfter:
2976 return QDateTimePrivate::GapUseBefore | QDateTimePrivate::FoldUseAfter;
2977 case QDateTime::TransitionResolution::PreferBefore:
2978 return QDateTimePrivate::GapUseBefore | QDateTimePrivate::FoldUseBefore;
2979 case QDateTime::TransitionResolution::PreferAfter:
2980 return QDateTimePrivate::GapUseAfter | QDateTimePrivate::FoldUseAfter;
2981 case QDateTime::TransitionResolution::PreferStandard:
2982 return QDateTimePrivate::GapUseBefore
2983 | QDateTimePrivate::FoldUseAfter
2984 | QDateTimePrivate::FlipForReverseDst;
2985 case QDateTime::TransitionResolution::PreferDaylightSaving:
2986 return QDateTimePrivate::GapUseAfter
2987 | QDateTimePrivate::FoldUseBefore
2988 | QDateTimePrivate::FlipForReverseDst;
2989 case QDateTime::TransitionResolution::Reject: break;
2990 }
2991 return {};
2992}
2993
2994constexpr static QDateTimePrivate::TransitionOptions
2995toTransitionOptions(QDateTimePrivate::DaylightStatus dst)
2996{
2997 return toTransitionOptions(dst == QDateTimePrivate::DaylightTime
2998 ? QDateTime::TransitionResolution::PreferDaylightSaving
2999 : QDateTime::TransitionResolution::PreferStandard);
3000}
3001
3002QString QDateTimePrivate::localNameAtMillis(qint64 millis, DaylightStatus dst)
3003{
3004 const QDateTimePrivate::TransitionOptions resolve = toTransitionOptions(dst);
3005 QString abbreviation;
3006 if (millisInSystemRange(millis, MSECS_PER_DAY)) {
3007 abbreviation = QLocalTime::localTimeAbbbreviationAt(millis, resolve);
3008 if (!abbreviation.isEmpty())
3009 return abbreviation;
3010 }
3011
3012 // Otherwise, outside the system range.
3013#if QT_CONFIG(timezone)
3014 // Use the system zone:
3015 const auto sys = QTimeZone::systemTimeZone();
3016 if (sys.isValid()) {
3017 ZoneState state = zoneStateAtMillis(sys, millis, resolve);
3018 if (state.valid)
3019 return sys.d->abbreviation(state.when - state.offset * MSECS_PER_SEC);
3020 }
3021#endif // timezone
3022
3023 // Kludge
3024 // Use a time in the system range with the same day-of-week pattern to its year:
3025 auto fake = millisToWithinRange(millis);
3026 if (Q_LIKELY(fake.good))
3027 return QLocalTime::localTimeAbbbreviationAt(fake.shifted, resolve);
3028
3029 // Overflow, apparently.
3030 return {};
3031}
3032
3033// Determine the offset from UTC at the given local time as millis.
3034QDateTimePrivate::ZoneState QDateTimePrivate::localStateAtMillis(
3035 qint64 millis, QDateTimePrivate::TransitionOptions resolve)
3036{
3037 // First, if millis is within a day of the viable range, try mktime() in
3038 // case it does fall in the range and gets useful information:
3039 if (millisInSystemRange(millis, MSECS_PER_DAY)) {
3040 auto result = QLocalTime::mapLocalTime(millis, resolve);
3041 if (result.valid)
3042 return result;
3043 }
3044
3045 // Otherwise, outside the system range.
3046#if QT_CONFIG(timezone)
3047 // Use the system zone:
3048 const auto sys = QTimeZone::systemTimeZone();
3049 if (sys.isValid())
3050 return zoneStateAtMillis(sys, millis, resolve);
3051#endif // timezone
3052
3053 // Kludge
3054 // Use a time in the system range with the same day-of-week pattern to its year:
3055 auto fake = millisToWithinRange(millis);
3056 if (Q_LIKELY(fake.good)) {
3057 auto result = QLocalTime::mapLocalTime(fake.shifted, resolve);
3058 if (result.valid) {
3059 qint64 adjusted;
3060 if (Q_UNLIKELY(qAddOverflow(result.when, millis - fake.shifted, &adjusted))) {
3061 using Bound = std::numeric_limits<qint64>;
3062 adjusted = millis < fake.shifted ? Bound::min() : Bound::max();
3063 }
3064 result.when = adjusted;
3065 } else {
3066 result.when = millis;
3067 }
3068 return result;
3069 }
3070 // Overflow, apparently.
3071 return {millis};
3072}
3073
3074#if QT_CONFIG(timezone)
3075// For a TimeZone and a time expressed in zone msecs encoding, compute the
3076// actual DST-ness and offset, adjusting the time if needed to escape a
3077// spring-forward.
3078QDateTimePrivate::ZoneState QDateTimePrivate::zoneStateAtMillis(
3079 const QTimeZone &zone, qint64 millis, QDateTimePrivate::TransitionOptions resolve)
3080{
3081 Q_ASSERT(zone.isValid());
3082 Q_ASSERT(zone.timeSpec() == Qt::TimeZone);
3083 return zone.d->stateAtZoneTime(millis, resolve);
3084}
3085#endif // timezone
3086
3087static inline QDateTimePrivate::ZoneState stateAtMillis(const QTimeZone &zone, qint64 millis,
3088 QDateTimePrivate::TransitionOptions resolve)
3089{
3090 if (zone.timeSpec() == Qt::LocalTime)
3091 return QDateTimePrivate::localStateAtMillis(millis, resolve);
3092#if QT_CONFIG(timezone)
3093 if (zone.timeSpec() == Qt::TimeZone && zone.isValid())
3094 return QDateTimePrivate::zoneStateAtMillis(zone, millis, resolve);
3095#endif
3096 return {millis};
3097}
3098
3099static inline bool specCanBeSmall(Qt::TimeSpec spec)
3100{
3101 return spec == Qt::LocalTime || spec == Qt::UTC;
3102}
3103
3104static inline bool msecsCanBeSmall(qint64 msecs)
3105{
3106 if constexpr (!QDateTimeData::CanBeSmall)
3107 return false;
3108
3109 ShortData sd;
3110 sd.msecs = qintptr(msecs);
3111 return sd.msecs == msecs;
3112}
3113
3114static constexpr inline
3115QDateTimePrivate::StatusFlags mergeSpec(QDateTimePrivate::StatusFlags status, Qt::TimeSpec spec)
3116{
3117 status &= ~QDateTimePrivate::TimeSpecMask;
3118 status |= QDateTimePrivate::StatusFlags::fromInt(int(spec) << QDateTimePrivate::TimeSpecShift);
3119 return status;
3120}
3121
3122static constexpr inline Qt::TimeSpec extractSpec(QDateTimePrivate::StatusFlags status)
3123{
3124 return Qt::TimeSpec((status & QDateTimePrivate::TimeSpecMask).toInt() >> QDateTimePrivate::TimeSpecShift);
3125}
3126
3127// Set the Daylight Status if LocalTime set via msecs
3128static constexpr inline QDateTimePrivate::StatusFlags
3129mergeDaylightStatus(QDateTimePrivate::StatusFlags sf, QDateTimePrivate::DaylightStatus status)
3130{
3131 sf &= ~QDateTimePrivate::DaylightMask;
3132 if (status == QDateTimePrivate::DaylightTime) {
3133 sf |= QDateTimePrivate::SetToDaylightTime;
3134 } else if (status == QDateTimePrivate::StandardTime) {
3135 sf |= QDateTimePrivate::SetToStandardTime;
3136 }
3137 return sf;
3138}
3139
3140// Get the DST Status if LocalTime set via msecs
3141static constexpr inline
3142QDateTimePrivate::DaylightStatus extractDaylightStatus(QDateTimePrivate::StatusFlags status)
3143{
3144 if (status.testFlag(QDateTimePrivate::SetToDaylightTime))
3145 return QDateTimePrivate::DaylightTime;
3146 if (status.testFlag(QDateTimePrivate::SetToStandardTime))
3147 return QDateTimePrivate::StandardTime;
3148 return QDateTimePrivate::UnknownDaylightTime;
3149}
3150
3151static inline qint64 getMSecs(const QDateTimeData &d)
3152{
3153 if (d.isShort()) {
3154 // same as, but producing better code
3155 //return d.data.msecs;
3156 return qintptr(d.d) >> 8;
3157 }
3158 return d->m_msecs;
3159}
3160
3162{
3163 if (d.isShort()) {
3164 // same as, but producing better code
3165 //return StatusFlag(d.data.status);
3166 return QDateTimePrivate::StatusFlag(qintptr(d.d) & 0xFF);
3167 }
3168 return d->m_status;
3169}
3170
3171static inline Qt::TimeSpec getSpec(const QDateTimeData &d)
3172{
3173 return extractSpec(getStatus(d));
3174}
3175
3176/* True if we *can cheaply determine* that a and b use the same offset.
3177 If they use different offsets or it would be expensive to find out, false.
3178 Calls to toMSecsSinceEpoch() are expensive, for these purposes.
3179 See QDateTime's comparison operators and areFarEnoughApart().
3180*/
3181static inline bool usesSameOffset(const QDateTimeData &a, const QDateTimeData &b)
3182{
3183 const auto status = getStatus(a);
3184 if (status != getStatus(b))
3185 return false;
3186 // Status includes DST-ness, so we now know they match in it.
3187
3188 switch (extractSpec(status)) {
3189 case Qt::LocalTime:
3190 case Qt::UTC:
3191 return true;
3192
3193 case Qt::TimeZone:
3194 /* TimeZone always determines its offset during construction of the
3195 private data. Even if we're in different zones, what matters is the
3196 offset actually in effect at the specific time. (DST can cause things
3197 with the same time-zone to use different offsets, but we already
3198 checked their DSTs match.) */
3199 case Qt::OffsetFromUTC: // always knows its offset, which is all that matters.
3200 Q_ASSERT(!a.isShort() && !b.isShort());
3201 return a->m_offsetFromUtc == b->m_offsetFromUtc;
3202 }
3203 Q_UNREACHABLE_RETURN(false);
3204}
3205
3206/* Even datetimes with different offset can be ordered by their getMSecs()
3207 provided the difference is bigger than the largest difference in offset we're
3208 prepared to believe in. Technically, it may be possible to construct a zone
3209 with an offset outside the range and get wrong results - but the answer to
3210 someone doing that is that their contrived timezone and its consequences are
3211 their own responsibility.
3212
3213 If two datetimes' millis lie within the offset range of one another, we can't
3214 take any short-cuts, even if they're in the same zone, because there may be a
3215 zone transition between them. (The full 32-hour difference would only arise
3216 before 1845, for one date-time in The Philippines, the other in Alaska.)
3217*/
3218bool areFarEnoughApart(qint64 leftMillis, qint64 rightMillis)
3219{
3220 constexpr quint64 UtcOffsetMillisRange
3221 = quint64(QTimeZone::MaxUtcOffsetSecs - QTimeZone::MinUtcOffsetSecs) * MSECS_PER_SEC;
3222 qint64 gap = 0;
3223 return qSubOverflow(leftMillis, rightMillis, &gap) || QtPrivate::qUnsignedAbs(gap) > UtcOffsetMillisRange;
3224}
3225
3226// Refresh the LocalTime or TimeZone validity and offset
3227static void refreshZonedDateTime(QDateTimeData &d, const QTimeZone &zone,
3228 QDateTimePrivate::TransitionOptions resolve)
3229{
3230 Q_ASSERT(zone.timeSpec() == Qt::TimeZone || zone.timeSpec() == Qt::LocalTime);
3231 auto status = getStatus(d);
3232 Q_ASSERT(extractSpec(status) == zone.timeSpec());
3233 int offsetFromUtc = 0;
3234 /* Callers are:
3235 * QDTP::create(), where d is too new to be shared yet
3236 * reviseTimeZone(), which detach()es if not short before calling this
3237 * checkValidDateTime(), always follows a setDateTime() that detach()ed if not short
3238
3239 So we can assume d is not shared. We only need to detach() if we convert
3240 from short to pimpled to accommodate an oversize msecs, which can only be
3241 needed in the unlikely event we revise it.
3242 */
3243
3244 // If not valid date and time then is invalid
3245 if (!status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime)) {
3246 status.setFlag(QDateTimePrivate::ValidDateTime, false);
3247 } else {
3248 // We have a valid date and time and a Qt::LocalTime or Qt::TimeZone
3249 // that might fall into a "missing" DST transition hour.
3250 qint64 msecs = getMSecs(d);
3251 QDateTimePrivate::ZoneState state = stateAtMillis(zone, msecs, resolve);
3252 Q_ASSERT(!state.valid || (state.offset >= -SECS_PER_DAY && state.offset <= SECS_PER_DAY));
3253 if (state.dst == QDateTimePrivate::UnknownDaylightTime) { // Overflow
3254 status.setFlag(QDateTimePrivate::ValidDateTime, false);
3255 } else if (state.valid) {
3256 status = mergeDaylightStatus(status, state.dst);
3257 offsetFromUtc = state.offset;
3258 status.setFlag(QDateTimePrivate::ValidDateTime, true);
3259 if (Q_UNLIKELY(msecs != state.when)) {
3260 // Update msecs to the resolution:
3261 if (status.testFlag(QDateTimePrivate::ShortData)) {
3262 if (msecsCanBeSmall(state.when)) {
3263 d.data.msecs = qintptr(state.when);
3264 } else {
3265 // Convert to long-form so we can hold the revised msecs:
3266 status.setFlag(QDateTimePrivate::ShortData, false);
3267 d.detach();
3268 }
3269 }
3270 if (!status.testFlag(QDateTimePrivate::ShortData))
3271 d->m_msecs = state.when;
3272 }
3273 } else {
3274 status.setFlag(QDateTimePrivate::ValidDateTime, false);
3275 }
3276 }
3277
3278 if (status.testFlag(QDateTimePrivate::ShortData)) {
3279 d.data.status = status.toInt();
3280 } else {
3281 d->m_status = status;
3282 d->m_offsetFromUtc = offsetFromUtc;
3283 }
3284}
3285
3286// Check the UTC / offsetFromUTC validity
3288{
3289 auto status = getStatus(d);
3290 Q_ASSERT(QTimeZone::isUtcOrFixedOffset(extractSpec(status)));
3291 status.setFlag(QDateTimePrivate::ValidDateTime,
3292 status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime));
3293
3294 if (status.testFlag(QDateTimePrivate::ShortData))
3295 d.data.status = status.toInt();
3296 else
3297 d->m_status = status;
3298}
3299
3300// Clean up and set status after assorted set-up or reworking:
3301static void checkValidDateTime(QDateTimeData &d, QDateTime::TransitionResolution resolve)
3302{
3303 auto spec = extractSpec(getStatus(d));
3304 switch (spec) {
3305 case Qt::OffsetFromUTC:
3306 case Qt::UTC:
3307 // for these, a valid date and a valid time imply a valid QDateTime
3309 break;
3310 case Qt::TimeZone:
3311 case Qt::LocalTime:
3312 // For these, we need to check whether (the zone is valid and) the time
3313 // is valid for the zone. Expensive, but we have no other option.
3314 refreshZonedDateTime(d, d.timeZone(), toTransitionOptions(resolve));
3315 break;
3316 }
3317}
3318
3319static void reviseTimeZone(QDateTimeData &d, const QTimeZone &zone,
3320 QDateTime::TransitionResolution resolve)
3321{
3322 Qt::TimeSpec spec = zone.timeSpec();
3323 auto status = mergeSpec(getStatus(d), spec);
3324 bool reuse = d.isShort();
3325 int offset = 0;
3326
3327 switch (spec) {
3328 case Qt::UTC:
3329 Q_ASSERT(zone.fixedSecondsAheadOfUtc() == 0);
3330 break;
3331 case Qt::OffsetFromUTC:
3332 reuse = false;
3333 offset = zone.fixedSecondsAheadOfUtc();
3334 Q_ASSERT(offset);
3335 break;
3336 case Qt::TimeZone:
3337 reuse = false;
3338 break;
3339 case Qt::LocalTime:
3340 break;
3341 }
3342
3343 status &= ~(QDateTimePrivate::ValidDateTime | QDateTimePrivate::DaylightMask);
3344 if (reuse) {
3345 d.data.status = status.toInt();
3346 } else {
3347 d.detach();
3348 d->m_status = status & ~QDateTimePrivate::ShortData;
3349 d->m_offsetFromUtc = offset;
3350#if QT_CONFIG(timezone)
3351 if (spec == Qt::TimeZone)
3352 d->m_timeZone = zone;
3353#endif // timezone
3354 }
3355
3356 if (QTimeZone::isUtcOrFixedOffset(spec))
3358 else
3359 refreshZonedDateTime(d, zone, toTransitionOptions(resolve));
3360}
3361
3362static void setDateTime(QDateTimeData &d, QDate date, QTime time)
3363{
3364 // If the date is valid and the time is not we set time to 00:00:00
3365 if (!time.isValid() && date.isValid())
3366 time = QTime::fromMSecsSinceStartOfDay(0);
3367
3368 QDateTimePrivate::StatusFlags newStatus = { };
3369
3370 // Set date value and status
3371 qint64 days = 0;
3372 if (date.isValid()) {
3373 days = date.toJulianDay() - JULIAN_DAY_FOR_EPOCH;
3374 newStatus = QDateTimePrivate::ValidDate;
3375 }
3376
3377 // Set time value and status
3378 int ds = 0;
3379 if (time.isValid()) {
3380 ds = time.msecsSinceStartOfDay();
3381 newStatus |= QDateTimePrivate::ValidTime;
3382 }
3383 Q_ASSERT(ds < MSECS_PER_DAY);
3384 // Only the later parts of the very first day are representable - its start
3385 // would overflow - so get ds the same side of 0 as days:
3386 if (days < 0 && ds > 0) {
3387 days++;
3388 ds -= MSECS_PER_DAY;
3389 }
3390
3391 // Check in representable range:
3392 qint64 msecs = 0;
3393 if (daysAndMillisOverflow(days, qint64(ds), &msecs)) {
3394 newStatus = QDateTimePrivate::StatusFlags{};
3395 msecs = 0;
3396 }
3397 if (d.isShort()) {
3398 // let's see if we can keep this short
3399 if (msecsCanBeSmall(msecs)) {
3400 // yes, we can
3401 d.data.msecs = qintptr(msecs);
3402 d.data.status &= ~(QDateTimePrivate::ValidityMask | QDateTimePrivate::DaylightMask).toInt();
3403 d.data.status |= newStatus.toInt();
3404 } else {
3405 // nope...
3406 d.detach();
3407 }
3408 }
3409 if (!d.isShort()) {
3410 d.detach();
3411 d->m_msecs = msecs;
3412 d->m_status &= ~(QDateTimePrivate::ValidityMask | QDateTimePrivate::DaylightMask);
3413 d->m_status |= newStatus;
3414 }
3415}
3416
3417static std::pair<QDate, QTime> getDateTime(const QDateTimeData &d)
3418{
3419 auto status = getStatus(d);
3420 const qint64 msecs = getMSecs(d);
3421 const auto dayMilli = QRoundingDown::qDivMod<MSECS_PER_DAY>(msecs);
3422 return { status.testFlag(QDateTimePrivate::ValidDate)
3423 ? QDate::fromJulianDay(JULIAN_DAY_FOR_EPOCH + dayMilli.quotient)
3424 : QDate(),
3425 status.testFlag(QDateTimePrivate::ValidTime)
3426 ? QTime::fromMSecsSinceStartOfDay(dayMilli.remainder)
3427 : QTime() };
3428}
3429
3430/*****************************************************************************
3431 QDateTime::Data member functions
3432 *****************************************************************************/
3433
3434inline QDateTime::Data::Data() noexcept
3435{
3436 // default-constructed data has a special exception:
3437 // it can be small even if CanBeSmall == false
3438 // (optimization so we don't allocate memory in the default constructor)
3439 quintptr value = mergeSpec(QDateTimePrivate::ShortData, Qt::LocalTime).toInt();
3440 d = reinterpret_cast<QDateTimePrivate *>(value);
3441}
3442
3443inline QDateTime::Data::Data(const QTimeZone &zone)
3444{
3445 Qt::TimeSpec spec = zone.timeSpec();
3446 if (CanBeSmall && Q_LIKELY(specCanBeSmall(spec))) {
3447 quintptr value = mergeSpec(QDateTimePrivate::ShortData, spec).toInt();
3448 d = reinterpret_cast<QDateTimePrivate *>(value);
3449 Q_ASSERT(isShort());
3450 } else {
3451 // the structure is too small, we need to detach
3452 d = new QDateTimePrivate;
3453 d->ref.ref();
3454 d->m_status = mergeSpec({}, spec);
3455 if (spec == Qt::OffsetFromUTC)
3456 d->m_offsetFromUtc = zone.fixedSecondsAheadOfUtc();
3457 else if (spec == Qt::TimeZone)
3458 d->m_timeZone = zone;
3459 Q_ASSERT(!isShort());
3460 }
3461}
3462
3463inline QDateTime::Data::Data(const Data &other) noexcept
3464 : data(other.data)
3465{
3466 if (!isShort()) {
3467 // check if we could shrink
3468 if (specCanBeSmall(extractSpec(d->m_status)) && msecsCanBeSmall(d->m_msecs)) {
3469 ShortData sd;
3470 sd.msecs = qintptr(d->m_msecs);
3471 sd.status = (d->m_status | QDateTimePrivate::ShortData).toInt();
3472 data = sd;
3473 } else {
3474 // no, have to keep it big
3475 d->ref.ref();
3476 }
3477 }
3478}
3479
3480inline QDateTime::Data::Data(Data &&other) noexcept
3481 : data(other.data)
3482{
3483 // reset the other to a short state
3484 Data dummy;
3485 Q_ASSERT(dummy.isShort());
3486 other.data = dummy.data;
3487}
3488
3489inline QDateTime::Data &QDateTime::Data::operator=(const Data &other) noexcept
3490{
3491 if (isShort() ? data == other.data : d == other.d)
3492 return *this;
3493
3494 auto x = d;
3495 d = other.d;
3496 if (!other.isShort()) {
3497 // check if we could shrink
3498 if (specCanBeSmall(extractSpec(other.d->m_status)) && msecsCanBeSmall(other.d->m_msecs)) {
3499 ShortData sd;
3500 sd.msecs = qintptr(other.d->m_msecs);
3501 sd.status = (other.d->m_status | QDateTimePrivate::ShortData).toInt();
3502 data = sd;
3503 } else {
3504 // no, have to keep it big
3505 other.d->ref.ref();
3506 }
3507 }
3508
3509 if (!(quintptr(x) & QDateTimePrivate::ShortData) && !x->ref.deref())
3510 delete x;
3511 return *this;
3512}
3513
3514inline QDateTime::Data::~Data()
3515{
3516 if (!isShort() && !d->ref.deref())
3517 delete d;
3518}
3519
3520inline bool QDateTime::Data::isShort() const
3521{
3522 bool b = quintptr(d) & QDateTimePrivate::ShortData;
3523
3524 // sanity check:
3525 Q_ASSERT(b || !d->m_status.testFlag(QDateTimePrivate::ShortData));
3526
3527 // even if CanBeSmall = false, we have short data for a default-constructed
3528 // QDateTime object. But it's unlikely.
3529 if constexpr (CanBeSmall)
3530 return Q_LIKELY(b);
3531 return Q_UNLIKELY(b);
3532}
3533
3534inline void QDateTime::Data::detach()
3535{
3536 QDateTimePrivate *x;
3537 bool wasShort = isShort();
3538 if (wasShort) {
3539 // force enlarging
3540 x = new QDateTimePrivate;
3541 x->m_status = QDateTimePrivate::StatusFlags::fromInt(data.status) & ~QDateTimePrivate::ShortData;
3542 x->m_msecs = data.msecs;
3543 } else {
3544 if (d->ref.loadRelaxed() == 1)
3545 return;
3546
3547 x = new QDateTimePrivate(*d);
3548 }
3549
3550 x->ref.storeRelaxed(1);
3551 if (!wasShort && !d->ref.deref())
3552 delete d;
3553 d = x;
3554}
3555
3556void QDateTime::Data::invalidate()
3557{
3558 if (isShort()) {
3559 data.status &= ~int(QDateTimePrivate::ValidityMask);
3560 } else {
3561 detach();
3562 d->m_status &= ~QDateTimePrivate::ValidityMask;
3563 }
3564}
3565
3566QTimeZone QDateTime::Data::timeZone() const
3567{
3568 switch (getSpec(*this)) {
3569 case Qt::UTC:
3570 return QTimeZone::UTC;
3571 case Qt::OffsetFromUTC:
3572 return QTimeZone::fromSecondsAheadOfUtc(d->m_offsetFromUtc);
3573 case Qt::TimeZone:
3574#if QT_CONFIG(timezone)
3575 if (d->m_timeZone.isValid())
3576 return d->m_timeZone;
3577#endif
3578 break;
3579 case Qt::LocalTime:
3580 return QTimeZone::LocalTime;
3581 }
3582 return QTimeZone();
3583}
3584
3585inline const QDateTimePrivate *QDateTime::Data::operator->() const
3586{
3587 Q_ASSERT(!isShort());
3588 return d;
3589}
3590
3591inline QDateTimePrivate *QDateTime::Data::operator->()
3592{
3593 // should we attempt to detach here?
3594 Q_ASSERT(!isShort());
3595 Q_ASSERT(d->ref.loadRelaxed() == 1);
3596 return d;
3597}
3598
3599/*****************************************************************************
3600 QDateTimePrivate member functions
3601 *****************************************************************************/
3602
3603Q_NEVER_INLINE
3604QDateTime::Data QDateTimePrivate::create(QDate toDate, QTime toTime, const QTimeZone &zone,
3605 QDateTime::TransitionResolution resolve)
3606{
3607 QDateTime::Data result(zone);
3608 setDateTime(result, toDate, toTime);
3609 if (zone.isUtcOrFixedOffset())
3610 refreshSimpleDateTime(result);
3611 else
3612 refreshZonedDateTime(result, zone, toTransitionOptions(resolve));
3613 return result;
3614}
3615
3616/*****************************************************************************
3617 QDateTime member functions
3618 *****************************************************************************/
3619
3620/*!
3621 \class QDateTime
3622 \inmodule QtCore
3623 \ingroup shared
3624 \reentrant
3625 \brief The QDateTime class provides date and time functions.
3626
3627 \compares weak
3628
3629 A QDateTime object encodes a calendar date and a clock time (a "datetime")
3630 in accordance with a time representation. It combines features of the QDate
3631 and QTime classes. It can read the current datetime from the system
3632 clock. It provides functions for comparing datetimes and for manipulating a
3633 datetime by adding a number of seconds, days, months, or years.
3634
3635 QDateTime can describe datetimes with respect to \l{Qt::LocalTime}{local
3636 time}, to \l{Qt::UTC}{UTC}, to a specified \l{Qt::OffsetFromUTC}{offset from
3637 UTC} or to a specified \l{Qt::TimeZone}{time zone}. Each of these time
3638 representations can be encapsulated in a suitable instance of the QTimeZone
3639 class. For example, a time zone of "Europe/Berlin" will apply the
3640 daylight-saving rules as used in Germany. In contrast, a fixed offset from
3641 UTC of +3600 seconds is one hour ahead of UTC (usually written in ISO
3642 standard notation as "UTC+01:00"), with no daylight-saving
3643 complications. When using either local time or a specified time zone,
3644 time-zone transitions (see \l {Timezone transitions}{below}) are taken into
3645 account. A QDateTime's timeSpec() will tell you which of the four types of
3646 time representation is in use; its timeRepresentation() provides a full
3647 description of that time representation, as a QTimeZone.
3648
3649 A QDateTime object is typically created either by giving a date and time
3650 explicitly in the constructor, or by using a static function such as
3651 currentDateTime() or fromMSecsSinceEpoch(). The date and time can be changed
3652 with setDate() and setTime(). A datetime can also be set using the
3653 setMSecsSinceEpoch() function that takes the time, in milliseconds, since
3654 the start, in UTC, of the year 1970. The fromString() function returns a
3655 QDateTime, given a string and a date format used to interpret the date
3656 within the string.
3657
3658 QDateTime::currentDateTime() returns a QDateTime that expresses the current
3659 date and time with respect to a specific time representation, such as local
3660 time (its default). QDateTime::currentDateTimeUtc() returns a QDateTime that
3661 expresses the current date and time with respect to UTC; it is equivalent to
3662 \c {QDateTime::currentDateTime(QTimeZone::UTC)}.
3663
3664 The date() and time() functions provide access to the date and
3665 time parts of the datetime. The same information is provided in
3666 textual format by the toString() function.
3667
3668 QDateTime provides a full set of operators to compare two
3669 QDateTime objects, where smaller means earlier and larger means
3670 later.
3671
3672 You can increment (or decrement) a datetime by a given number of
3673 milliseconds using addMSecs(), seconds using addSecs(), or days using
3674 addDays(). Similarly, you can use addMonths() and addYears(). The daysTo()
3675 function returns the number of days between two datetimes, secsTo() returns
3676 the number of seconds between two datetimes, and msecsTo() returns the
3677 number of milliseconds between two datetimes. These operations are aware of
3678 daylight-saving time (DST) and other time-zone transitions, where
3679 applicable.
3680
3681 Use toTimeZone() to re-express a datetime in terms of a different time
3682 representation. By passing a lightweight QTimeZone that represents local
3683 time, UTC or a fixed offset from UTC, you can convert the datetime to use
3684 the corresponding time representation; or you can pass a full time zone
3685 (whose \l {QTimeZone::timeSpec()}{timeSpec()} is \c {Qt::TimeZone}) to use
3686 that instead.
3687
3688 \section1 Remarks
3689
3690 QDateTime does not account for leap seconds.
3691
3692 All conversions to and from string formats are done using the C locale.
3693 For localized conversions, see QLocale.
3694
3695 There is no year 0 in the Gregorian calendar. Dates in that year are
3696 considered invalid. The year -1 is the year "1 before Christ" or "1 before
3697 common era." The day before 1 January 1 CE is 31 December 1 BCE.
3698
3699 Using local time (the default) or a specified time zone implies a need
3700 to resolve any issues around \l {Timezone transitions}{transitions}. As a
3701 result, operations on such QDateTime instances (notably including
3702 constructing them) may be more expensive than the equivalent when using UTC
3703 or a fixed offset from it.
3704
3705 \section2 Range of Valid Dates
3706
3707 The range of values that QDateTime can represent is dependent on the
3708 internal storage implementation. QDateTime is currently stored in a qint64
3709 as a serial msecs value encoding the date and time. This restricts the date
3710 range to about ±292 million years, compared to the QDate range of ±2 billion
3711 years. Care must be taken when creating a QDateTime with extreme values that
3712 you do not overflow the storage. The exact range of supported values varies
3713 depending on the time representation used.
3714
3715 \section2 Use of Timezones
3716
3717 QDateTime uses the system's time zone information to determine the current
3718 local time zone and its offset from UTC. If the system is not configured
3719 correctly or not up-to-date, QDateTime will give wrong results.
3720
3721 QDateTime likewise uses system-provided information to determine the offsets
3722 of other timezones from UTC. If this information is incomplete or out of
3723 date, QDateTime will give wrong results. See the QTimeZone documentation for
3724 more details.
3725
3726 On modern Unix systems, this means QDateTime usually has accurate
3727 information about historical transitions (including DST, see below) whenever
3728 possible. On Windows, where the system doesn't support historical timezone
3729 data, historical accuracy is not maintained with respect to timezone
3730 transitions, notably including DST. However, building Qt with the ICU
3731 library will equip QTimeZone with the same timezone database as is used on
3732 Unix.
3733
3734 \section2 Timezone transitions
3735
3736 QDateTime takes into account timezone transitions, both the transitions
3737 between Standard Time and Daylight-Saving Time (DST) and the transitions
3738 that arise when a zone changes its standard offset. For example, if the
3739 transition is at 2am and the clock goes forward to 3am, then there is a
3740 "missing" hour from 02:00:00 to 02:59:59.999. Such a transition is known as
3741 a "spring forward" and the times skipped over have no meaning. When a
3742 transition goes the other way, known as a "fall back", a time interval is
3743 repeated, first in the old zone (usually DST), then in the new zone (usually
3744 Standard Time), so times in this interval are ambiguous.
3745
3746 Some zones use "reversed" DST, using standard time in summer and
3747 daylight-saving time (with a lowered offset) in winter. For such zones, the
3748 spring forward still happens in spring and skips an hour, but is a
3749 transition \e{out of} daylight-saving time, while the fall back still
3750 repeats an autumn hour but is a transition \e to daylight-saving time.
3751
3752 When converting from a UTC time (or a time at fixed offset from UTC), there
3753 is always an unambiguous valid result in any timezone. However, when
3754 combining a date and time to make a datetime, expressed with respect to
3755 local time or a specific time-zone, the nominal result may fall in a
3756 transition, making it either invalid or ambiguous. Methods where this
3757 situation may arise take a \c resolve parameter: this is always ignored if
3758 the requested datetime is valid and unambiguous. See \l TransitionResolution
3759 for the options it lets you control. Prior to Qt 6.7, the equivalent of its
3760 \l LegacyBehavior was selected.
3761
3762 For a spring forward's skipped interval, interpreting the requested time
3763 with either offset yields an actual time at which the other offset was in
3764 use; so passing \c TransitionResolution::RelativeToBefore for \c resolve
3765 will actually result in a time after the transition, that would have had the
3766 requested representation had the transition not happened. Likewise, \c
3767 TransitionResolution::RelativeToAfter for \c resolve results in a time
3768 before the transition, that would have had the requested representation, had
3769 the transition happened earlier.
3770
3771 When QDateTime performs arithmetic, as with addDay() or addSecs(), it takes
3772 care to produce a valid result. For example, on a day when there is a spring
3773 forward from 02:00 to 03:00, adding one second to 01:59:59 will get
3774 03:00:00. Adding one day to 02:30 on the preceding day will get 03:30 on the
3775 day of the transition, while subtracting one day, by calling \c{addDay(-1)},
3776 to 02:30 on the following day will get 01:30 on the day of the transition.
3777 While addSecs() will deliver a time offset by the given number of seconds,
3778 addDays() adjusts the date and only adjusts time if it would otherwise get
3779 an invalid result. Applying \c{addDays(1)} to 03:00 on the day before the
3780 spring-forward will simply get 03:00 on the day of the transition, even
3781 though the latter is only 23 hours after the former; but \c{addSecs(24 * 60
3782 * 60)} will get 04:00 on the day of the transition, since that's 24 hours
3783 later. Typical transitions make some days 23 or 25 hours long.
3784
3785 For datetimes that the system \c time_t can represent (from 1901-12-14 to
3786 2038-01-18 on systems with 32-bit \c time_t; for the full range QDateTime
3787 can represent if the type is 64-bit), the standard system APIs are used to
3788 determine local time's offset from UTC. For datetimes not handled by these
3789 system APIs (potentially including some within the \c time_t range),
3790 QTimeZone::systemTimeZone() is used, if available, or a best effort is made
3791 to estimate. In any case, the offset information used depends on the system
3792 and may be incomplete or, for past times, historically
3793 inaccurate. Furthermore, for future dates, the local time zone's offsets and
3794 DST rules may change before that date comes around.
3795
3796 \section3 Whole day transitions
3797
3798 A small number of zones have skipped or repeated entire days as part of
3799 moving The International Date Line across themselves. For these, daysTo()
3800 will be unaware of the duplication or gap, simply using the difference in
3801 calendar date; in contrast, msecsTo() and secsTo() know the true time
3802 interval. Likewise, addMSecs() and addSecs() correspond directly to elapsed
3803 time, where addDays(), addMonths() and addYears() follow the nominal
3804 calendar, aside from where landing in a gap or duplication requires
3805 resolving an ambiguity or invalidity due to a duplication or omission.
3806
3807 \note Days "lost" during a change of calendar, such as from Julian to
3808 Gregorian, do not affect QDateTime. Although the two calendars describe
3809 dates differently, the successive days across the change are described by
3810 consecutive QDate instances, each one day later than the previous, as
3811 described by either calendar or by their toJulianDay() values. In contrast,
3812 a zone skipping or duplicating a day is changing its description of \e time,
3813 not date, for all that it does so by a whole 24 hours.
3814
3815 \section2 Offsets From UTC
3816
3817 Offsets from UTC are measured in seconds east of Greenwich. The moment
3818 described by a particular date and time, such as noon on a particular day,
3819 depends on the time representation used. Those with a higher offset from UTC
3820 describe an earlier moment, and those with a lower offset a later moment, by
3821 any given combination of date and time.
3822
3823 There is no explicit size restriction on an offset from UTC, but there is an
3824 implicit limit imposed when using the toString() and fromString() methods
3825 which use a ±hh:mm format, effectively limiting the range to ± 99 hours and
3826 59 minutes and whole minutes only. Note that currently no time zone has an
3827 offset outside the range of ±14 hours and all known offsets are multiples of
3828 five minutes. Historical time zones have a wider range and may have offsets
3829 including seconds; these last cannot be faithfully represented in strings.
3830
3831 \sa QDate, QTime, QDateTimeEdit, QTimeZone
3832*/
3833
3834/*!
3835 \since 5.14
3836 \enum QDateTime::YearRange
3837
3838 This enumerated type describes the range of years (in the Gregorian
3839 calendar) representable by QDateTime:
3840
3841 \value First The later parts of this year are representable
3842 \value Last The earlier parts of this year are representable
3843
3844 All dates strictly between these two years are also representable.
3845 Note, however, that the Gregorian Calendar has no year zero.
3846
3847 \note QDate can describe dates in a wider range of years. For most
3848 purposes, this makes little difference, as the range of years that QDateTime
3849 can support reaches 292 million years either side of 1970.
3850
3851 \sa isValid(), QDate
3852*/
3853
3854/*!
3855 \since 6.7
3856 \enum QDateTime::TransitionResolution
3857
3858 This enumeration is used to resolve datetime combinations which fall in \l
3859 {Timezone transitions}.
3860
3861 When constructing a datetime, specified in terms of local time or a
3862 time-zone that has daylight-saving time, or revising one with setDate(),
3863 setTime() or setTimeZone(), the given parameters may imply a time
3864 representation that either has no meaning or has two meanings in the
3865 zone. Such time representations are described as being in the transition. In
3866 either case, we can simply return an invalid datetime, to indicate that the
3867 operation is ill-defined. In the ambiguous case, we can alternatively select
3868 one of the two times that could be meant. When there is no meaning, we can
3869 select a time either side of it that might plausibly have been meant. For
3870 example, when advancing from an earlier time, we can select the time after
3871 the transition that is actually the specified amount of time after the
3872 earlier time in question. The options specified here configure how such
3873 selection is performed.
3874
3875 \value Reject
3876 Treat any time in a transition as invalid. Either it really is, or it
3877 is ambiguous.
3878 \value RelativeToBefore
3879 Selects a time as if stepping forward from a time before the
3880 transition. This interprets the requested time using the offset in
3881 effect before the transition and, if necessary, converts the result
3882 to the offset in effect at the resulting time.
3883 \value RelativeToAfter
3884 Select a time as if stepping backward from a time after the
3885 transition. This interprets the requested time using the offset in
3886 effect after the transition and, if necessary, converts the result to
3887 the offset in effect at the resulting time.
3888 \value PreferBefore
3889 Selects a time before the transition,
3890 \value PreferAfter
3891 Selects a time after the transition.
3892 \value PreferStandard
3893 Selects a time on the standard time side of the transition.
3894 \value PreferDaylightSaving
3895 Selects a time on the daylight-saving-time side of the transition.
3896 \omitvalue LegacyBehavior
3897
3898 An additional constant, \c LegacyBehavior, is used as a default value for
3899 TransitionResolution parameters in some constructors and setter functions.
3900 This is an alias for \c RelativeToBefore, which implements behavior that
3901 most closely matches the behavior of QDateTime prior to Qt 6.7.
3902
3903 For \l addDays(), \l addMonths() or \l addYears(), the behavior is and
3904 (mostly) was to use \c RelativeToBefore if adding a positive adjustment and \c
3905 RelativeToAfter if adding a negative adjustment.
3906
3907 \note In time zones where daylight-saving increases the offset from UTC in
3908 summer (known as "positive DST"), PreferStandard is an alias for
3909 RelativeToAfter and PreferDaylightSaving for RelativeToBefore. In time zones
3910 where the daylight-saving mechanism is a decrease in offset from UTC in
3911 winter (known as "negative DST"), the reverse applies, provided the
3912 operating system reports - as it does on most platforms - whether a datetime
3913 is in DST or standard time. For some platforms, where transition details are
3914 unavailable even for Qt::TimeZone datetimes, QTimeZone is obliged to presume
3915 that the side with lower offset from UTC is standard time, effectively
3916 assuming positive DST.
3917
3918 The following tables illustrate how a QDateTime constructor resolves a
3919 request for 02:30 on a day when local time has a transition between 02:00
3920 and 03:00, with a nominal standard time LST and daylight-saving time LDT on
3921 the two sides, in the various possible cases. The transition type may be to
3922 skip an hour or repeat it. The type of transition and value of a parameter
3923 \c resolve determine which actual time on the given date is selected. First,
3924 the common case of positive daylight-saving, where:
3925
3926 \table
3927 \header \li Before \li 02:00--03:00 \li After \li \c resolve \li selected
3928 \row \li LST \li skip \li LDT \li RelativeToBefore \li 03:30 LDT
3929 \row \li LST \li skip \li LDT \li RelativeToAfter \li 01:30 LST
3930 \row \li LST \li skip \li LDT \li PreferBefore \li 01:30 LST
3931 \row \li LST \li skip \li LDT \li PreferAfter \li 03:30 LDT
3932 \row \li LST \li skip \li LDT \li PreferStandard \li 01:30 LST
3933 \row \li LST \li skip \li LDT \li PreferDaylightSaving \li 03:30 LDT
3934 \row \li LDT \li repeat \li LST \li RelativeToBefore \li 02:30 LDT
3935 \row \li LDT \li repeat \li LST \li RelativeToAfter \li 02:30 LST
3936 \row \li LDT \li repeat \li LST \li PreferBefore \li 02:30 LDT
3937 \row \li LDT \li repeat \li LST \li PreferAfter \li 02:30 LST
3938 \row \li LDT \li repeat \li LST \li PreferStandard \li 02:30 LST
3939 \row \li LDT \li repeat \li LST \li PreferDaylightSaving \li 02:30 LDT
3940 \endtable
3941
3942 Second, the case for negative daylight-saving, using LDT in winter and
3943 skipping an hour to transition to LST in summer, then repeating an hour at
3944 the transition back to winter:
3945
3946 \table
3947 \row \li LDT \li skip \li LST \li RelativeToBefore \li 03:30 LST
3948 \row \li LDT \li skip \li LST \li RelativeToAfter \li 01:30 LDT
3949 \row \li LDT \li skip \li LST \li PreferBefore \li 01:30 LDT
3950 \row \li LDT \li skip \li LST \li PreferAfter \li 03:30 LST
3951 \row \li LDT \li skip \li LST \li PreferStandard \li 03:30 LST
3952 \row \li LDT \li skip \li LST \li PreferDaylightSaving \li 01:30 LDT
3953 \row \li LST \li repeat \li LDT \li RelativeToBefore \li 02:30 LST
3954 \row \li LST \li repeat \li LDT \li RelativeToAfter \li 02:30 LDT
3955 \row \li LST \li repeat \li LDT \li PreferBefore \li 02:30 LST
3956 \row \li LST \li repeat \li LDT \li PreferAfter \li 02:30 LDT
3957 \row \li LST \li repeat \li LDT \li PreferStandard \li 02:30 LST
3958 \row \li LST \li repeat \li LDT \li PreferDaylightSaving \li 02:30 LDT
3959 \endtable
3960
3961 Reject can be used to prompt relevant QDateTime APIs to return an invalid
3962 datetime object so that your code can deal with transitions for itself, for
3963 example by alerting a user to the fact that the datetime they have selected
3964 is in a transition interval, to offer them the opportunity to resolve a
3965 conflict or ambiguity. Code using this may well find the other options above
3966 useful to determine relevant information to use in its own (or the user's)
3967 resolution. If the start or end of the transition, or the moment of the
3968 transition itself, is the right resolution, QTimeZone's transition APIs can
3969 be used to obtain that information. You can determine whether the transition
3970 is a repeated or skipped interval by using \l secsTo() to measure the actual
3971 time between noon on the previous and following days. The result will be
3972 less than 48 hours for a skipped interval (such as a spring-forward) and
3973 more than 48 hours for a repeated interval (such as a fall-back).
3974
3975 \note When a resolution other than Reject is specified, a valid QDateTime
3976 object is returned, if possible. If the requested date-time falls in a gap,
3977 the returned date-time will not have the time() requested - or, in some
3978 cases, the date(), if a whole day was skipped. You can thus detect when a
3979 gap is hit by comparing date() and time() to what was requested.
3980
3981 \section2 Relation to other datetime software
3982
3983 The Python programming language's datetime APIs have a \c fold parameter
3984 that corresponds to \c RelativeToBefore (\c{fold = True}) and \c
3985 RelativeToAfter (\c{fold = False}).
3986
3987 The \c Temporal proposal to replace JavaScript's \c Date offers four options
3988 for how to resolve a transition, as value for a \c disambiguation
3989 parameter. Its \c{'reject'} raises an exception, which roughly corresponds
3990 to \c Reject producing an invalid result. Its \c{'earlier'} and \c{'later'}
3991 options correspond to \c PreferBefore and \c PreferAfter. Its
3992 \c{'compatible'} option corresponds to \c RelativeToBefore (and Python's
3993 \c{fold = True}).
3994
3995 \sa {Timezone transitions}
3996*/
3997
3998/*!
3999 Constructs a null datetime, nominally using local time.
4000
4001 A null datetime is invalid, since its date and time are invalid.
4002
4003 \sa isValid(), setMSecsSinceEpoch(), setDate(), setTime(), setTimeZone()
4004*/
4005QDateTime::QDateTime() noexcept
4006{
4007#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) || QT_POINTER_SIZE == 8
4008 static_assert(sizeof(ShortData) == sizeof(qint64));
4009 static_assert(sizeof(Data) == sizeof(qint64));
4010#endif
4011 static_assert(sizeof(ShortData) >= sizeof(void*), "oops, Data::swap() is broken!");
4012}
4013
4014#if QT_DEPRECATED_SINCE(6, 9)
4015/*!
4016 \deprecated [6.9] Use \c{QDateTime(date, time)} or \c{QDateTime(date, time, QTimeZone::fromSecondsAheadOfUtc(offsetSeconds))}.
4017
4018 Constructs a datetime with the given \a date and \a time, using the time
4019 representation implied by \a spec and \a offsetSeconds seconds.
4020
4021 If \a date is valid and \a time is not, the time will be set to midnight.
4022
4023 If \a spec is not Qt::OffsetFromUTC then \a offsetSeconds will be
4024 ignored. If \a spec is Qt::OffsetFromUTC and \a offsetSeconds is 0 then the
4025 timeSpec() will be set to Qt::UTC, i.e. an offset of 0 seconds.
4026
4027 If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
4028 i.e. the current system time zone. To create a Qt::TimeZone datetime
4029 use the correct constructor.
4030
4031 If \a date lies outside the range of dates representable by QDateTime, the
4032 result is invalid. If \a spec is Qt::LocalTime and the system's time-zone
4033 skipped over the given date and time, the result is invalid.
4034*/
4035QDateTime::QDateTime(QDate date, QTime time, Qt::TimeSpec spec, int offsetSeconds)
4036 : d(QDateTimePrivate::create(date, time, asTimeZone(spec, offsetSeconds, "QDateTime"),
4037 TransitionResolution::LegacyBehavior))
4038{
4039}
4040#endif // 6.9 deprecation
4041
4042/*!
4043 \since 5.2
4044 \overload primary
4045
4046 Constructs a datetime with the given \a date and \a time, using the time
4047 representation described by \a timeZone.
4048
4049 If \a date is valid and \a time is not, the time will be set to midnight.
4050 If \a timeZone is invalid then the datetime will be invalid. If \a date and
4051 \a time describe a moment close to a transition for \a timeZone, \a resolve
4052 controls how that situation is resolved.
4053
4054//! [pre-resolve-note]
4055 \note Prior to Qt 6.7, the version of this function lacked the \a resolve
4056 parameter so had no way to resolve the ambiguities related to transitions.
4057//! [pre-resolve-note]
4058*/
4059
4060QDateTime::QDateTime(QDate date, QTime time, const QTimeZone &timeZone, TransitionResolution resolve)
4061 : d(QDateTimePrivate::create(date, time, timeZone, resolve))
4062{
4063}
4064
4065/*!
4066 \since 6.5
4067 \overload
4068
4069 Constructs a datetime with the given \a date and \a time, using local time.
4070
4071 If \a date is valid and \a time is not, midnight will be used as the
4072 time. If \a date and \a time describe a moment close to a transition for
4073 local time, \a resolve controls how that situation is resolved.
4074
4075 \include qdatetime.cpp pre-resolve-note
4076*/
4077
4078QDateTime::QDateTime(QDate date, QTime time, TransitionResolution resolve)
4079 : d(QDateTimePrivate::create(date, time, QTimeZone::LocalTime, resolve))
4080{
4081}
4082
4083/*!
4084 Constructs a copy of the \a other datetime.
4085*/
4086QDateTime::QDateTime(const QDateTime &other) noexcept
4087 : d(other.d)
4088{
4089}
4090
4091/*!
4092 \since 5.8
4093 Moves the content of the temporary \a other datetime to this object and
4094 leaves \a other in an unspecified (but proper) state.
4095*/
4096QDateTime::QDateTime(QDateTime &&other) noexcept
4097 : d(std::move(other.d))
4098{
4099}
4100
4101/*!
4102 Destroys the datetime.
4103*/
4104QDateTime::~QDateTime()
4105{
4106}
4107
4108/*!
4109 Copies the \a other datetime into this and returns this copy.
4110*/
4111
4112QDateTime &QDateTime::operator=(const QDateTime &other) noexcept
4113{
4114 d = other.d;
4115 return *this;
4116}
4117/*!
4118 \fn void QDateTime::swap(QDateTime &other)
4119 \since 5.0
4120 \memberswap{datetime}
4121*/
4122
4123/*!
4124 Returns \c true if both the date and the time are null; otherwise
4125 returns \c false. A null datetime is invalid.
4126
4127 \sa QDate::isNull(), QTime::isNull(), isValid()
4128*/
4129
4130bool QDateTime::isNull() const
4131{
4132 // If date or time is invalid, we don't set datetime valid.
4133 return !getStatus(d).testAnyFlag(QDateTimePrivate::ValidityMask);
4134}
4135
4136/*!
4137 Returns \c true if this datetime represents a definite moment, otherwise \c false.
4138
4139 A datetime is valid if both its date and its time are valid and the time
4140 representation used gives a valid meaning to their combination. When the
4141 time representation is a specific time-zone or local time, there may be
4142 times on some dates that the zone skips in its representation, as when a
4143 daylight-saving transition skips an hour (typically during a night in
4144 spring). For example, if DST ends at 2am with the clock advancing to 3am,
4145 then datetimes from 02:00:00 to 02:59:59.999 on that day are invalid.
4146
4147 \sa QDateTime::YearRange, QDate::isValid(), QTime::isValid()
4148*/
4149
4150bool QDateTime::isValid() const
4151{
4152 return getStatus(d).testFlag(QDateTimePrivate::ValidDateTime);
4153}
4154
4155/*!
4156 Returns the date part of the datetime.
4157
4158 \sa setDate(), time(), timeRepresentation()
4159*/
4160
4161QDate QDateTime::date() const
4162{
4163 return getStatus(d).testFlag(QDateTimePrivate::ValidDate) ? msecsToDate(getMSecs(d)) : QDate();
4164}
4165
4166/*!
4167 Returns the time part of the datetime.
4168
4169 \sa setTime(), date(), timeRepresentation()
4170*/
4171
4172QTime QDateTime::time() const
4173{
4174 return getStatus(d).testFlag(QDateTimePrivate::ValidTime) ? msecsToTime(getMSecs(d)) : QTime();
4175}
4176
4177/*!
4178 Returns the time specification of the datetime.
4179
4180 This classifies its time representation as local time, UTC, a fixed offset
4181 from UTC (without indicating the offset) or a time zone (without giving the
4182 details of that time zone). Equivalent to
4183 \c{timeRepresentation().timeSpec()}.
4184
4185 \sa setTimeZone(), timeRepresentation(), date(), time()
4186*/
4187
4188Qt::TimeSpec QDateTime::timeSpec() const
4189{
4190 return getSpec(d);
4191}
4192
4193/*!
4194 \since 6.5
4195 Returns a QTimeZone identifying how this datetime represents time.
4196
4197 The timeSpec() of the returned QTimeZone will coincide with that of this
4198 datetime; if it is not Qt::TimeZone then the returned QTimeZone is a time
4199 representation. When their timeSpec() is Qt::OffsetFromUTC, the returned
4200 QTimeZone's fixedSecondsAheadOfUtc() supplies the offset. When timeSpec()
4201 is Qt::TimeZone, the QTimeZone object itself is the full representation of
4202 that time zone.
4203
4204 \sa timeZone(), setTimeZone(), QTimeZone::asBackendZone()
4205*/
4206
4207QTimeZone QDateTime::timeRepresentation() const
4208{
4209 return d.timeZone();
4210}
4211
4212#if QT_CONFIG(timezone)
4213/*!
4214 \since 5.2
4215
4216 Returns the time zone of the datetime.
4217
4218 The result is the same as \c{timeRepresentation().asBackendZone()}. In all
4219 cases, the result's \l {QTimeZone::timeSpec()}{timeSpec()} is Qt::TimeZone.
4220
4221 When timeSpec() is Qt::LocalTime, the result will describe local time at the
4222 time this method was called. It will not reflect subsequent changes to the
4223 system time zone, even when the QDateTime from which it was obtained does.
4224
4225 \sa timeRepresentation(), setTimeZone(), Qt::TimeSpec, QTimeZone::asBackendZone()
4226*/
4227
4228QTimeZone QDateTime::timeZone() const
4229{
4230 return d.timeZone().asBackendZone();
4231}
4232#endif // timezone
4233
4234/*!
4235 \since 5.2
4236
4237 Returns this datetime's Offset From UTC in seconds.
4238
4239 The result depends on timeSpec():
4240 \list
4241 \li \c Qt::UTC The offset is 0.
4242 \li \c Qt::OffsetFromUTC The offset is the value originally set.
4243 \li \c Qt::LocalTime The local time's offset from UTC is returned.
4244 \li \c Qt::TimeZone The offset used by the time-zone is returned.
4245 \endlist
4246
4247 For the last two, the offset at this date and time will be returned, taking
4248 account of Daylight-Saving Offset. The offset is the difference between the
4249 local time or time in the given time-zone and UTC time; it is positive in
4250 time-zones ahead of UTC (East of The Prime Meridian), negative for those
4251 behind UTC (West of The Prime Meridian).
4252
4253 \sa setTimeZone()
4254*/
4255
4256int QDateTime::offsetFromUtc() const
4257{
4258 const auto status = getStatus(d);
4259 if (!status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime))
4260 return 0;
4261 // But allow invalid date-time (e.g. gap's resolution) to report its offset.
4262 if (!d.isShort())
4263 return d->m_offsetFromUtc;
4264
4265 auto spec = extractSpec(status);
4266 if (spec == Qt::LocalTime) {
4267 // We didn't cache the value, so we need to calculate it:
4268 const auto resolve = toTransitionOptions(extractDaylightStatus(status));
4269 return QDateTimePrivate::localStateAtMillis(getMSecs(d), resolve).offset;
4270 }
4271
4272 Q_ASSERT(spec == Qt::UTC);
4273 return 0;
4274}
4275
4276/*!
4277 \since 5.2
4278
4279 Returns the Time Zone Abbreviation for this datetime.
4280
4281 The returned string depends on timeSpec():
4282
4283 \list
4284 \li For Qt::UTC it is "UTC".
4285 \li For Qt::OffsetFromUTC it will be in the format "UTC±00:00".
4286 \li For Qt::LocalTime, the host system is queried.
4287 \li For Qt::TimeZone, the associated QTimeZone object is queried.
4288 \endlist
4289
4290 \note The abbreviation is not guaranteed to be unique, i.e. different time
4291 zones may have the same abbreviation. For Qt::LocalTime and Qt::TimeZone,
4292 when returned by the host system, the abbreviation may be localized.
4293
4294 \sa timeSpec(), QTimeZone::abbreviation()
4295*/
4296
4297QString QDateTime::timeZoneAbbreviation() const
4298{
4299 if (!isValid())
4300 return QString();
4301
4302 switch (getSpec(d)) {
4303 case Qt::UTC:
4304 return "UTC"_L1;
4305 case Qt::OffsetFromUTC:
4306 return "UTC"_L1 + toOffsetString(Qt::ISODate, d->m_offsetFromUtc);
4307 case Qt::TimeZone:
4308#if !QT_CONFIG(timezone)
4309 break;
4310#else
4311 Q_ASSERT(d->m_timeZone.isValid());
4312 return d->m_timeZone.abbreviation(*this);
4313#endif // timezone
4314 case Qt::LocalTime:
4315#if defined(Q_OS_WIN) && QT_CONFIG(timezone)
4316 // MS's tzname is a full MS-name, not an abbreviation:
4317 if (QString sys = QTimeZone::systemTimeZone().abbreviation(*this); !sys.isEmpty())
4318 return sys;
4319 // ... but, even so, a full name isn't as bad as empty.
4320#endif
4321 return QDateTimePrivate::localNameAtMillis(getMSecs(d),
4322 extractDaylightStatus(getStatus(d)));
4323 }
4324 return QString();
4325}
4326
4327/*!
4328 \since 5.2
4329
4330 Returns if this datetime falls in Daylight-Saving Time.
4331
4332 If the Qt::TimeSpec is not Qt::LocalTime or Qt::TimeZone then will always
4333 return false.
4334
4335 \sa timeSpec()
4336*/
4337
4338bool QDateTime::isDaylightTime() const
4339{
4340 if (!isValid())
4341 return false;
4342
4343 switch (getSpec(d)) {
4344 case Qt::UTC:
4345 case Qt::OffsetFromUTC:
4346 return false;
4347 case Qt::TimeZone:
4348#if !QT_CONFIG(timezone)
4349 break;
4350#else
4351 Q_ASSERT(d->m_timeZone.isValid());
4352 if (auto dst = extractDaylightStatus(getStatus(d));
4353 dst != QDateTimePrivate::UnknownDaylightTime) {
4354 return dst == QDateTimePrivate::DaylightTime;
4355 }
4356 return d->m_timeZone.d->isDaylightTime(toMSecsSinceEpoch());
4357#endif // timezone
4358 case Qt::LocalTime: {
4359 auto dst = extractDaylightStatus(getStatus(d));
4360 if (dst == QDateTimePrivate::UnknownDaylightTime) {
4361 dst = QDateTimePrivate::localStateAtMillis(
4362 getMSecs(d), toTransitionOptions(TransitionResolution::LegacyBehavior)).dst;
4363 }
4364 return dst == QDateTimePrivate::DaylightTime;
4365 }
4366 }
4367 return false;
4368}
4369
4370/*!
4371 Sets the date part of this datetime to \a date.
4372
4373 If no time is set yet, it is set to midnight. If \a date is invalid, this
4374 QDateTime becomes invalid.
4375
4376 If \a date and time() describe a moment close to a transition for this
4377 datetime's time representation, \a resolve controls how that situation is
4378 resolved.
4379
4380 \include qdatetime.cpp pre-resolve-note
4381
4382 \sa date(), setTime(), setTimeZone()
4383*/
4384
4385void QDateTime::setDate(QDate date, TransitionResolution resolve)
4386{
4387 setDateTime(d, date, time());
4388 checkValidDateTime(d, resolve);
4389}
4390
4391/*!
4392 Sets the time part of this datetime to \a time. If \a time is not valid,
4393 this function sets it to midnight. Therefore, it's possible to clear any
4394 set time in a QDateTime by setting it to a default QTime:
4395
4396 \code
4397 QDateTime dt = QDateTime::currentDateTime();
4398 dt.setTime(QTime());
4399 \endcode
4400
4401 If date() and \a time describe a moment close to a transition for this
4402 datetime's time representation, \a resolve controls how that situation is
4403 resolved.
4404
4405 \include qdatetime.cpp pre-resolve-note
4406
4407 \sa time(), setDate(), setTimeZone()
4408*/
4409
4410void QDateTime::setTime(QTime time, TransitionResolution resolve)
4411{
4412 setDateTime(d, date(), time);
4413 checkValidDateTime(d, resolve);
4414}
4415
4416#if QT_DEPRECATED_SINCE(6, 9)
4417/*!
4418 \deprecated [6.9] Use setTimeZone() instead
4419
4420 Sets the time specification used in this datetime to \a spec.
4421 The datetime may refer to a different point in time.
4422
4423 If \a spec is Qt::OffsetFromUTC then the timeSpec() will be set
4424 to Qt::UTC, i.e. an effective offset of 0.
4425
4426 If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
4427 i.e. the current system time zone.
4428
4429 Example:
4430 \snippet code/src_corelib_time_qdatetime.cpp 19
4431
4432 \sa setTimeZone(), timeSpec(), toTimeSpec(), setDate(), setTime()
4433*/
4434
4435void QDateTime::setTimeSpec(Qt::TimeSpec spec)
4436{
4437 reviseTimeZone(d, asTimeZone(spec, 0, "QDateTime::setTimeSpec"),
4438 TransitionResolution::LegacyBehavior);
4439}
4440
4441/*!
4442 \since 5.2
4443 \deprecated [6.9] Use setTimeZone(QTimeZone::fromSecondsAheadOfUtc(offsetSeconds)) instead
4444
4445 Sets the timeSpec() to Qt::OffsetFromUTC and the offset to \a offsetSeconds.
4446 The datetime may refer to a different point in time.
4447
4448 The maximum and minimum offset is 14 positive or negative hours. If
4449 \a offsetSeconds is larger or smaller than that, then the result is
4450 undefined.
4451
4452 If \a offsetSeconds is 0 then the timeSpec() will be set to Qt::UTC.
4453
4454 \sa setTimeZone(), isValid(), offsetFromUtc(), toOffsetFromUtc()
4455*/
4456
4457void QDateTime::setOffsetFromUtc(int offsetSeconds)
4458{
4459 reviseTimeZone(d, QTimeZone::fromSecondsAheadOfUtc(offsetSeconds),
4460 TransitionResolution::Reject);
4461}
4462#endif // 6.9 deprecations
4463
4464/*!
4465 \since 5.2
4466
4467 Sets the time zone used in this datetime to \a toZone.
4468
4469 The datetime may refer to a different point in time. It uses the time
4470 representation of \a toZone, which may change the meaning of its unchanged
4471 date() and time().
4472
4473 If \a toZone is invalid then the datetime will be invalid. Otherwise, this
4474 datetime's timeSpec() after the call will match \c{toZone.timeSpec()}.
4475
4476 If date() and time() describe a moment close to a transition for \a toZone,
4477 \a resolve controls how that situation is resolved.
4478
4479 \include qdatetime.cpp pre-resolve-note
4480
4481 \sa timeRepresentation(), timeZone(), Qt::TimeSpec
4482*/
4483
4484void QDateTime::setTimeZone(const QTimeZone &toZone, TransitionResolution resolve)
4485{
4486 reviseTimeZone(d, toZone, resolve);
4487}
4488
4489/*!
4490 \since 4.7
4491
4492 Returns the datetime as a number of milliseconds after the start, in UTC, of
4493 the year 1970.
4494
4495 On systems that do not support time zones, this function will
4496 behave as if local time were Qt::UTC.
4497
4498 The behavior for this function is undefined if the datetime stored in
4499 this object is not valid. However, for all valid dates, this function
4500 returns a unique value.
4501
4502 \sa toSecsSinceEpoch(), setMSecsSinceEpoch(), fromMSecsSinceEpoch()
4503*/
4504qint64 QDateTime::toMSecsSinceEpoch() const
4505{
4506 // Note: QDateTimeParser relies on this producing a useful result, even when
4507 // !isValid(), at least when the invalidity is a time in a fall-back (that
4508 // we'll have adjusted to lie outside it, but marked invalid because it's
4509 // not what was asked for). Other things may be doing similar. But that's
4510 // only relevant when we got enough data for resolution to find it invalid.
4511 const auto status = getStatus(d);
4512 if (!status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime))
4513 return 0;
4514
4515 switch (extractSpec(status)) {
4516 case Qt::UTC:
4517 return getMSecs(d);
4518
4519 case Qt::OffsetFromUTC:
4520 Q_ASSERT(!d.isShort());
4521 return d->m_msecs - d->m_offsetFromUtc * MSECS_PER_SEC;
4522
4523 case Qt::LocalTime:
4524 if (status.testFlag(QDateTimePrivate::ShortData)) {
4525 // Short form has nowhere to cache the offset, so recompute.
4526 const auto resolve = toTransitionOptions(extractDaylightStatus(getStatus(d)));
4527 const auto state = QDateTimePrivate::localStateAtMillis(getMSecs(d), resolve);
4528 return state.when - state.offset * MSECS_PER_SEC;
4529 }
4530 // Use the offset saved by refreshZonedDateTime() on creation.
4531 return d->m_msecs - d->m_offsetFromUtc * MSECS_PER_SEC;
4532
4533 case Qt::TimeZone:
4534 Q_ASSERT(!d.isShort());
4535#if QT_CONFIG(timezone)
4536 // Use offset refreshZonedDateTime() saved on creation:
4537 if (d->m_timeZone.isValid())
4538 return d->m_msecs - d->m_offsetFromUtc * MSECS_PER_SEC;
4539#endif
4540 return 0;
4541 }
4542 Q_UNREACHABLE_RETURN(0);
4543}
4544
4545/*!
4546 \since 5.8
4547
4548 Returns the datetime as a number of seconds after the start, in UTC, of the
4549 year 1970.
4550
4551 On systems that do not support time zones, this function will
4552 behave as if local time were Qt::UTC.
4553
4554 The behavior for this function is undefined if the datetime stored in
4555 this object is not valid. However, for all valid dates, this function
4556 returns a unique value.
4557
4558 \sa toMSecsSinceEpoch(), fromSecsSinceEpoch(), setSecsSinceEpoch()
4559*/
4560qint64 QDateTime::toSecsSinceEpoch() const
4561{
4562 return toMSecsSinceEpoch() / MSECS_PER_SEC;
4563}
4564
4565/*!
4566 \since 4.7
4567
4568 Sets the datetime to represent a moment a given number, \a msecs, of
4569 milliseconds after the start, in UTC, of the year 1970.
4570
4571 On systems that do not support time zones, this function will
4572 behave as if local time were Qt::UTC.
4573
4574 Note that passing the minimum of \c qint64
4575 (\c{std::numeric_limits<qint64>::min()}) to \a msecs will result in
4576 undefined behavior.
4577
4578 \sa setSecsSinceEpoch(), toMSecsSinceEpoch(), fromMSecsSinceEpoch()
4579*/
4580void QDateTime::setMSecsSinceEpoch(qint64 msecs)
4581{
4582 auto status = getStatus(d);
4583 const auto spec = extractSpec(status);
4584 Q_ASSERT(specCanBeSmall(spec) || !d.isShort());
4585 QDateTimePrivate::ZoneState state(msecs);
4586
4587 status &= ~QDateTimePrivate::ValidityMask;
4588 if (QTimeZone::isUtcOrFixedOffset(spec)) {
4589 if (spec == Qt::OffsetFromUTC)
4590 state.offset = d->m_offsetFromUtc;
4591 if (!state.offset || !qAddOverflow(msecs, state.offset * MSECS_PER_SEC, &state.when))
4592 status |= QDateTimePrivate::ValidityMask;
4593 } else if (spec == Qt::LocalTime) {
4594 state = QDateTimePrivate::expressUtcAsLocal(msecs);
4595 if (state.valid)
4596 status = mergeDaylightStatus(status | QDateTimePrivate::ValidityMask, state.dst);
4597#if QT_CONFIG(timezone)
4598 } else if (spec == Qt::TimeZone && (d.detach(), d->m_timeZone.isValid())) {
4599 const auto data = d->m_timeZone.d->data(msecs);
4600 if (Q_LIKELY(data.offsetFromUtc != QTimeZonePrivate::invalidSeconds())) {
4601 state.offset = data.offsetFromUtc;
4602 Q_ASSERT(state.offset >= -SECS_PER_DAY && state.offset <= SECS_PER_DAY);
4603 if (!state.offset
4604 || !Q_UNLIKELY(qAddOverflow(msecs, state.offset * MSECS_PER_SEC, &state.when))) {
4605 d->m_status = mergeDaylightStatus(status | QDateTimePrivate::ValidityMask,
4606 data.daylightTimeOffset
4607 ? QDateTimePrivate::DaylightTime
4608 : QDateTimePrivate::StandardTime);
4609 d->m_msecs = state.when;
4610 d->m_offsetFromUtc = state.offset;
4611 return;
4612 } // else: zone can't represent this UTC time
4613 } // else: zone unable to represent given UTC time (should only happen on overflow).
4614#endif // timezone
4615 }
4616 Q_ASSERT(!status.testFlag(QDateTimePrivate::ValidDateTime)
4617 || (state.offset >= -SECS_PER_DAY && state.offset <= SECS_PER_DAY));
4618
4619 if (msecsCanBeSmall(state.when) && d.isShort()) {
4620 // we can keep short
4621 d.data.msecs = qintptr(state.when);
4622 d.data.status = status.toInt();
4623 } else {
4624 d.detach();
4625 d->m_status = status & ~QDateTimePrivate::ShortData;
4626 d->m_msecs = state.when;
4627 d->m_offsetFromUtc = state.offset;
4628 }
4629}
4630
4631/*!
4632 \since 5.8
4633
4634 Sets the datetime to represent a moment a given number, \a secs, of seconds
4635 after the start, in UTC, of the year 1970.
4636
4637 On systems that do not support time zones, this function will
4638 behave as if local time were Qt::UTC.
4639
4640 \sa setMSecsSinceEpoch(), toSecsSinceEpoch(), fromSecsSinceEpoch()
4641*/
4642void QDateTime::setSecsSinceEpoch(qint64 secs)
4643{
4644 qint64 msecs;
4645 if (!qMulOverflow(secs, std::integral_constant<qint64, MSECS_PER_SEC>(), &msecs))
4646 setMSecsSinceEpoch(msecs);
4647 else
4648 d.invalidate();
4649}
4650
4651#if QT_CONFIG(datestring) // depends on, so implies, textdate
4652/*!
4653 \overload toString()
4654
4655 Returns the datetime as a string in the \a format given.
4656
4657 If the \a format is Qt::TextDate, the string is formatted in the default
4658 way. The day and month names will be in English. An example of this
4659 formatting is "Wed May 20 03:40:13 1998". For localized formatting, see
4660 \l{QLocale::toString()}.
4661
4662 If the \a format is Qt::ISODate, the string format corresponds to the ISO
4663 8601 extended specification for representations of dates and times, taking
4664 the form yyyy-MM-ddTHH:mm:ss[Z|±HH:mm], depending on the timeSpec() of the
4665 QDateTime. If the timeSpec() is Qt::UTC, Z will be appended to the string;
4666 if the timeSpec() is Qt::OffsetFromUTC, the offset in hours and minutes from
4667 UTC will be appended to the string. To include milliseconds in the ISO 8601
4668 date, use the \a format Qt::ISODateWithMs, which corresponds to
4669 yyyy-MM-ddTHH:mm:ss.zzz[Z|±HH:mm].
4670
4671 If the \a format is Qt::RFC2822Date, the string is formatted
4672 following \l{RFC 2822}.
4673
4674 If the datetime is invalid, an empty string will be returned.
4675
4676 \warning The Qt::ISODate format is only valid for years in the
4677 range 0 to 9999.
4678
4679 \sa fromString(), QDate::toString(), QTime::toString(),
4680 QLocale::toString()
4681*/
4682QString QDateTime::toString(Qt::DateFormat format) const
4683{
4684 QString buf;
4685 if (!isValid())
4686 return buf;
4687
4688 switch (format) {
4689 case Qt::RFC2822Date:
4690 buf = QLocale::c().toString(*this, u"dd MMM yyyy hh:mm:ss ");
4691 buf += toOffsetString(Qt::TextDate, offsetFromUtc());
4692 return buf;
4693 default:
4694 case Qt::TextDate: {
4695 const std::pair<QDate, QTime> p = getDateTime(d);
4696 buf = toStringTextDate(p.first);
4697 // Insert time between date's day and year:
4698 buf.insert(buf.lastIndexOf(u' '),
4699 u' ' + p.second.toString(Qt::TextDate));
4700 // Append zone/offset indicator, as appropriate:
4701 switch (timeSpec()) {
4702 case Qt::LocalTime:
4703 break;
4704#if QT_CONFIG(timezone)
4705 case Qt::TimeZone:
4706 buf += u' ' + d->m_timeZone.displayName(
4707 *this, QTimeZone::OffsetName, QLocale::c());
4708 break;
4709#endif
4710 default:
4711#if 0 // ### Qt 7 GMT: use UTC instead, see qnamespace.qdoc documentation
4712 buf += " UTC"_L1;
4713#else
4714 buf += " GMT"_L1;
4715#endif
4716 if (getSpec(d) == Qt::OffsetFromUTC)
4717 buf += toOffsetString(Qt::TextDate, offsetFromUtc());
4718 }
4719 return buf;
4720 }
4721 case Qt::ISODate:
4722 case Qt::ISODateWithMs: {
4723 const std::pair<QDate, QTime> p = getDateTime(d);
4724 buf = toStringIsoDate(p.first);
4725 if (buf.isEmpty())
4726 return QString(); // failed to convert
4727 buf += u'T' + p.second.toString(format);
4728 switch (getSpec(d)) {
4729 case Qt::UTC:
4730 buf += u'Z';
4731 break;
4732 case Qt::OffsetFromUTC:
4733 case Qt::TimeZone:
4734 buf += toOffsetString(Qt::ISODate, offsetFromUtc());
4735 break;
4736 default:
4737 break;
4738 }
4739 return buf;
4740 }
4741 }
4742}
4743
4744/*!
4745 \since 5.14
4746 \overload primary
4747 \fn QString QDateTime::toString(const QString &format, QCalendar cal) const
4748 \fn QString QDateTime::toString(QStringView format, QCalendar cal) const
4749
4750 Returns the datetime as a string. The \a format parameter determines the
4751 format of the result string. If \a cal is supplied, it determines the
4752 calendar used to represent the date; it defaults to Gregorian. Prior to Qt
4753 5.14, there was no \a cal parameter and the Gregorian calendar was always
4754 used. See QTime::toString() and QDate::toString() for the supported
4755 specifiers for time and date, respectively, in the \a format parameter.
4756
4757 Any sequence of characters enclosed in single quotes will be included
4758 verbatim in the output string (stripped of the quotes), even if it contains
4759 formatting characters. Two consecutive single quotes ("''") are replaced by
4760 a single quote in the output. All other characters in the format string are
4761 included verbatim in the output string.
4762
4763 Formats without separators (e.g. "ddMM") are supported but must be used with
4764 care, as the resulting strings aren't always reliably readable (e.g. if "dM"
4765 produces "212" it could mean either the 2nd of December or the 21st of
4766 February).
4767
4768 Example format strings (assumed that the QDateTime is 21 May 2001
4769 14:13:09.120):
4770
4771 \table
4772 \header \li Format \li Result
4773 \row \li dd.MM.yyyy \li 21.05.2001
4774 \row \li ddd MMMM d yy \li Tue May 21 01
4775 \row \li hh:mm:ss.zzz \li 14:13:09.120
4776 \row \li hh:mm:ss.z \li 14:13:09.12
4777 \row \li h:m:s ap \li 2:13:9 pm
4778 \endtable
4779
4780 If the datetime is invalid, an empty string will be returned.
4781
4782 \note Day and month names as well as AM/PM indicators are given in English
4783 (C locale). To get localized month and day names and localized forms of
4784 AM/PM, use QLocale::system().toDateTime().
4785
4786 \sa fromString(), QDate::toString(), QTime::toString(), QLocale::toString()
4787*/
4788QString QDateTime::toString(QStringView format, QCalendar cal) const
4789{
4790 return QLocale::c().toString(*this, format, cal);
4791}
4792
4793// Out-of-line no-calendar overloads, since QCalendar is a non-trivial type
4794/*!
4795 \since 5.10
4796 \overload toString()
4797*/
4798QString QDateTime::toString(QStringView format) const
4799{
4800 return QLocale::c().toString(*this, format, QCalendar());
4801}
4802
4803/*!
4804 \since 4.6
4805 \overload toString()
4806*/
4807QString QDateTime::toString(const QString &format) const
4808{
4809 return QLocale::c().toString(*this, qToStringViewIgnoringNull(format), QCalendar());
4810}
4811#endif // datestring
4812
4813static inline void massageAdjustedDateTime(QDateTimeData &d, QDate date, QTime time, bool forward)
4814{
4815 const QDateTimePrivate::TransitionOptions resolve = toTransitionOptions(
4816 forward ? QDateTime::TransitionResolution::RelativeToBefore
4817 : QDateTime::TransitionResolution::RelativeToAfter);
4818 auto status = getStatus(d);
4819 Q_ASSERT(status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime
4820 | QDateTimePrivate::ValidDateTime));
4821 auto spec = extractSpec(status);
4822 if (QTimeZone::isUtcOrFixedOffset(spec)) {
4823 setDateTime(d, date, time);
4825 return;
4826 }
4827 qint64 local = timeToMSecs(date, time);
4828 const QDateTimePrivate::ZoneState state = stateAtMillis(d.timeZone(), local, resolve);
4829 Q_ASSERT(state.valid || state.dst == QDateTimePrivate::UnknownDaylightTime);
4830 if (state.dst == QDateTimePrivate::UnknownDaylightTime)
4831 status.setFlag(QDateTimePrivate::ValidDateTime, false);
4832 else
4833 status = mergeDaylightStatus(status | QDateTimePrivate::ValidDateTime, state.dst);
4834
4835 if (status & QDateTimePrivate::ShortData) {
4836 d.data.msecs = state.when;
4837 d.data.status = status.toInt();
4838 } else {
4839 d.detach();
4840 d->m_status = status;
4841 if (state.valid) {
4842 d->m_msecs = state.when;
4843 d->m_offsetFromUtc = state.offset;
4844 }
4845 }
4846}
4847
4848/*!
4849 Returns a QDateTime object containing a datetime \a ndays days
4850 later than the datetime of this object (or earlier if \a ndays is
4851 negative).
4852
4853 If the timeSpec() is Qt::LocalTime or Qt::TimeZone and the resulting date
4854 and time fall in the Standard Time to Daylight-Saving Time transition hour
4855 then the result will be just beyond this gap, in the direction of change.
4856 If the transition is at 2am and the clock goes forward to 3am, the result of
4857 aiming between 2am and 3am will be adjusted to fall before 2am (if \c{ndays
4858 < 0}) or after 3am (otherwise).
4859
4860 \sa daysTo(), addMonths(), addYears(), addSecs(), {Timezone transitions}
4861*/
4862
4863QDateTime QDateTime::addDays(qint64 ndays) const
4864{
4865 if (isNull())
4866 return QDateTime();
4867
4868 QDateTime dt(*this);
4869 std::pair<QDate, QTime> p = getDateTime(d);
4870 massageAdjustedDateTime(dt.d, p.first.addDays(ndays), p.second, ndays >= 0);
4871 return dt;
4872}
4873
4874/*!
4875 \fn QDate &QDate::operator++(QDate &date)
4876 \since 6.11
4877
4878 The prefix \c{++} operator, adds a day to \a date and returns a reference to
4879 the modified date object.
4880
4881 \sa addDays(), operator--()
4882*/
4883
4884/*!
4885 \fn QDate QDate::operator++(QDate &date, int)
4886 \since 6.11
4887
4888 The postfix \c{++} operator, adds a day to \a date and returns a copy of
4889 \a date with the previous date.
4890
4891 \sa addDays(), operator--()
4892*/
4893
4894/*!
4895 \fn QDate &QDate::operator--(QDate &date)
4896 \since 6.11
4897
4898 The prefix \c{--} operator, subtracts a day from \a date and returns a
4899 reference to the modified date object.
4900
4901 \sa addDays(), operator++()
4902*/
4903
4904/*!
4905 \fn QDate QDate::operator--(QDate &date, int)
4906 \since 6.11
4907
4908 The postfix \c{--} operator, subtracts a day from \a date and returns a
4909 copy of \a date with the next date.
4910
4911 \sa addDays(), operator++()
4912*/
4913
4914/*!
4915 Returns a QDateTime object containing a datetime \a nmonths months
4916 later than the datetime of this object (or earlier if \a nmonths
4917 is negative).
4918
4919 If the timeSpec() is Qt::LocalTime or Qt::TimeZone and the resulting date
4920 and time fall in the Standard Time to Daylight-Saving Time transition hour
4921 then the result will be just beyond this gap, in the direction of change.
4922 If the transition is at 2am and the clock goes forward to 3am, the result of
4923 aiming between 2am and 3am will be adjusted to fall before 2am (if
4924 \c{nmonths < 0}) or after 3am (otherwise).
4925
4926 \sa daysTo(), addDays(), addYears(), addSecs(), {Timezone transitions}
4927*/
4928
4929QDateTime QDateTime::addMonths(int nmonths) const
4930{
4931 if (isNull())
4932 return QDateTime();
4933
4934 QDateTime dt(*this);
4935 std::pair<QDate, QTime> p = getDateTime(d);
4936 massageAdjustedDateTime(dt.d, p.first.addMonths(nmonths), p.second, nmonths >= 0);
4937 return dt;
4938}
4939
4940/*!
4941 Returns a QDateTime object containing a datetime \a nyears years
4942 later than the datetime of this object (or earlier if \a nyears is
4943 negative).
4944
4945 If the timeSpec() is Qt::LocalTime or Qt::TimeZone and the resulting date
4946 and time fall in the Standard Time to Daylight-Saving Time transition hour
4947 then the result will be just beyond this gap, in the direction of change.
4948 If the transition is at 2am and the clock goes forward to 3am, the result of
4949 aiming between 2am and 3am will be adjusted to fall before 2am (if \c{nyears
4950 < 0}) or after 3am (otherwise).
4951
4952 \sa daysTo(), addDays(), addMonths(), addSecs(), {Timezone transitions}
4953*/
4954
4955QDateTime QDateTime::addYears(int nyears) const
4956{
4957 if (isNull())
4958 return QDateTime();
4959
4960 QDateTime dt(*this);
4961 std::pair<QDate, QTime> p = getDateTime(d);
4962 massageAdjustedDateTime(dt.d, p.first.addYears(nyears), p.second, nyears >= 0);
4963 return dt;
4964}
4965
4966/*!
4967 Returns a QDateTime object containing a datetime \a s seconds
4968 later than the datetime of this object (or earlier if \a s is
4969 negative).
4970
4971 If this datetime is invalid, an invalid datetime will be returned.
4972
4973 \sa addMSecs(), secsTo(), addDays(), addMonths(), addYears()
4974*/
4975
4976QDateTime QDateTime::addSecs(qint64 s) const
4977{
4978 qint64 msecs;
4979 if (qMulOverflow(s, std::integral_constant<qint64, MSECS_PER_SEC>(), &msecs))
4980 return QDateTime();
4981 return addMSecs(msecs);
4982}
4983
4984/*!
4985 Returns a QDateTime object containing a datetime \a msecs milliseconds
4986 later than the datetime of this object (or earlier if \a msecs is
4987 negative).
4988
4989 If this datetime is invalid, an invalid datetime will be returned.
4990
4991 \sa addSecs(), msecsTo(), addDays(), addMonths(), addYears()
4992*/
4993QDateTime QDateTime::addMSecs(qint64 msecs) const
4994{
4995 if (!isValid())
4996 return QDateTime();
4997
4998 QDateTime dt(*this);
4999 switch (getSpec(d)) {
5000 case Qt::LocalTime:
5001 case Qt::TimeZone:
5002 // Convert to real UTC first in case this crosses a DST transition:
5003 if (!qAddOverflow(toMSecsSinceEpoch(), msecs, &msecs))
5004 dt.setMSecsSinceEpoch(msecs);
5005 else
5006 dt.d.invalidate();
5007 break;
5008 case Qt::UTC:
5009 case Qt::OffsetFromUTC:
5010 // No need to convert, just add on
5011 if (qAddOverflow(getMSecs(d), msecs, &msecs)) {
5012 dt.d.invalidate();
5013 } else if (d.isShort() && msecsCanBeSmall(msecs)) {
5014 dt.d.data.msecs = qintptr(msecs);
5015 } else {
5016 dt.d.detach();
5017 dt.d->m_msecs = msecs;
5018 }
5019 break;
5020 }
5021 return dt;
5022}
5023
5024/*!
5025 \fn QDateTime QDateTime::addDuration(std::chrono::milliseconds msecs) const
5026
5027 \since 6.4
5028
5029 Returns a QDateTime object containing a datetime \a msecs milliseconds
5030 later than the datetime of this object (or earlier if \a msecs is
5031 negative).
5032
5033 If this datetime is invalid, an invalid datetime will be returned.
5034
5035 \note Adding durations expressed in \c{std::chrono::months} or
5036 \c{std::chrono::years} does not yield the same result obtained by using
5037 addMonths() or addYears(). The former are fixed durations, calculated in
5038 relation to the solar year; the latter use the Gregorian calendar definitions
5039 of months/years.
5040
5041 \sa addMSecs(), msecsTo(), addDays(), addMonths(), addYears()
5042*/
5043
5044/*!
5045 Returns the number of days from this datetime to the \a other
5046 datetime. The number of days is counted as the number of times
5047 midnight is reached between this datetime to the \a other
5048 datetime. This means that a 10 minute difference from 23:55 to
5049 0:05 the next day counts as one day.
5050
5051 If the \a other datetime is earlier than this datetime,
5052 the value returned is negative.
5053
5054 Example:
5055 \snippet code/src_corelib_time_qdatetime.cpp 15
5056
5057 \sa addDays(), secsTo(), msecsTo()
5058*/
5059
5060qint64 QDateTime::daysTo(const QDateTime &other) const
5061{
5062 return date().daysTo(other.date());
5063}
5064
5065/*!
5066 Returns the number of seconds from this datetime to the \a other
5067 datetime. If the \a other datetime is earlier than this datetime,
5068 the value returned is negative.
5069
5070 Before performing the comparison, the two datetimes are converted
5071 to Qt::UTC to ensure that the result is correct if daylight-saving
5072 (DST) applies to one of the two datetimes but not the other.
5073
5074 Returns 0 if either datetime is invalid.
5075
5076 Example:
5077 \snippet code/src_corelib_time_qdatetime.cpp 11
5078
5079 \sa addSecs(), daysTo(), QTime::secsTo()
5080*/
5081
5082qint64 QDateTime::secsTo(const QDateTime &other) const
5083{
5084 return msecsTo(other) / MSECS_PER_SEC;
5085}
5086
5087/*!
5088 Returns the number of milliseconds from this datetime to the \a other
5089 datetime. If the \a other datetime is earlier than this datetime,
5090 the value returned is negative.
5091
5092 Before performing the comparison, the two datetimes are converted
5093 to Qt::UTC to ensure that the result is correct if daylight-saving
5094 (DST) applies to one of the two datetimes and but not the other.
5095
5096 Returns 0 if either datetime is invalid.
5097
5098 \sa addMSecs(), daysTo(), QTime::msecsTo()
5099*/
5100
5101qint64 QDateTime::msecsTo(const QDateTime &other) const
5102{
5103 if (!isValid() || !other.isValid())
5104 return 0;
5105
5106 return other.toMSecsSinceEpoch() - toMSecsSinceEpoch();
5107}
5108
5109/*!
5110 \fn std::chrono::milliseconds QDateTime::operator-(const QDateTime &lhs, const QDateTime &rhs)
5111 \since 6.4
5112
5113 Returns the number of milliseconds between \a lhs and \a rhs.
5114 If \a lhs is earlier than \a rhs, the result will be negative.
5115
5116 Returns 0 if either datetime is invalid.
5117
5118 \sa msecsTo()
5119*/
5120
5121/*!
5122 \fn QDateTime QDateTime::operator+(const QDateTime &dateTime, std::chrono::milliseconds duration)
5123 \fn QDateTime QDateTime::operator+(std::chrono::milliseconds duration, const QDateTime &dateTime)
5124
5125 \since 6.4
5126
5127 Returns a QDateTime object containing a datetime \a duration milliseconds
5128 later than \a dateTime (or earlier if \a duration is negative).
5129
5130 If \a dateTime is invalid, an invalid datetime will be returned.
5131
5132 \sa addMSecs()
5133*/
5134
5135/*!
5136 \fn QDateTime &QDateTime::operator+=(std::chrono::milliseconds duration)
5137 \since 6.4
5138
5139 Modifies this datetime object by adding the given \a duration.
5140 The updated object will be later if \a duration is positive,
5141 or earlier if it is negative.
5142
5143 If this datetime is invalid, this function has no effect.
5144
5145 Returns a reference to this datetime object.
5146
5147 \sa addMSecs()
5148*/
5149
5150/*!
5151 \fn QDateTime QDateTime::operator-(const QDateTime &dateTime, std::chrono::milliseconds duration)
5152
5153 \since 6.4
5154
5155 Returns a QDateTime object containing a datetime \a duration milliseconds
5156 earlier than \a dateTime (or later if \a duration is negative).
5157
5158 If \a dateTime is invalid, an invalid datetime will be returned.
5159
5160 \sa addMSecs()
5161*/
5162
5163/*!
5164 \fn QDateTime &QDateTime::operator-=(std::chrono::milliseconds duration)
5165 \since 6.4
5166
5167 Modifies this datetime object by subtracting the given \a duration.
5168 The updated object will be earlier if \a duration is positive,
5169 or later if it is negative.
5170
5171 If this datetime is invalid, this function has no effect.
5172
5173 Returns a reference to this datetime object.
5174
5175 \sa addMSecs
5176*/
5177
5178#if QT_DEPRECATED_SINCE(6, 9)
5179/*!
5180 \deprecated [6.9] Use \l toTimeZone() instead.
5181
5182 Returns a copy of this datetime converted to the given time \a spec.
5183
5184 The result represents the same moment in time as, and is equal to, this datetime.
5185
5186 If \a spec is Qt::OffsetFromUTC then it is set to Qt::UTC. To set to a fixed
5187 offset from UTC, use toTimeZone() or toOffsetFromUtc().
5188
5189 If \a spec is Qt::TimeZone then it is set to Qt::LocalTime, i.e. the local
5190 Time Zone. To set a specified time-zone, use toTimeZone().
5191
5192 Example:
5193 \snippet code/src_corelib_time_qdatetime.cpp 16
5194
5195 \sa setTimeSpec(), timeSpec(), toTimeZone()
5196*/
5197
5198QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
5199{
5200 return toTimeZone(asTimeZone(spec, 0, "toTimeSpec"));
5201}
5202#endif // 6.9 deprecation
5203
5204/*!
5205 \since 5.2
5206
5207 Returns a copy of this datetime converted to a spec of Qt::OffsetFromUTC
5208 with the given \a offsetSeconds. Equivalent to
5209 \c{toTimeZone(QTimeZone::fromSecondsAheadOfUtc(offsetSeconds))}.
5210
5211 If the \a offsetSeconds equals 0 then a UTC datetime will be returned.
5212
5213 The result represents the same moment in time as, and is equal to, this datetime.
5214
5215 \sa offsetFromUtc(), toTimeZone()
5216*/
5217
5218QDateTime QDateTime::toOffsetFromUtc(int offsetSeconds) const
5219{
5220 return toTimeZone(QTimeZone::fromSecondsAheadOfUtc(offsetSeconds));
5221}
5222
5223/*!
5224 Returns a copy of this datetime converted to local time.
5225
5226 The result represents the same moment in time as, and is equal to, this datetime.
5227
5228 Example:
5229
5230 \snippet code/src_corelib_time_qdatetime.cpp 17
5231
5232 \sa toTimeZone(), toUTC(), toOffsetFromUtc()
5233*/
5234QDateTime QDateTime::toLocalTime() const
5235{
5236 return toTimeZone(QTimeZone::LocalTime);
5237}
5238
5239/*!
5240 Returns a copy of this datetime converted to UTC.
5241
5242 The result represents the same moment in time as, and is equal to, this datetime.
5243
5244 Example:
5245
5246 \snippet code/src_corelib_time_qdatetime.cpp 18
5247
5248 \sa toTimeZone(), toLocalTime(), toOffsetFromUtc()
5249*/
5250QDateTime QDateTime::toUTC() const
5251{
5252 return toTimeZone(QTimeZone::UTC);
5253}
5254
5255/*!
5256 \since 5.2
5257
5258 Returns a copy of this datetime converted to the given \a timeZone.
5259
5260 The result represents the same moment in time as, and is equal to, this datetime.
5261
5262 The result describes the moment in time in terms of \a timeZone's time
5263 representation. For example:
5264
5265 \snippet code/src_corelib_time_qdatetime.cpp 23
5266
5267 If \a timeZone is invalid then the datetime will be invalid. Otherwise the
5268 returned datetime's timeSpec() will match \c{timeZone.timeSpec()}.
5269
5270 \sa timeRepresentation(), toLocalTime(), toUTC(), toOffsetFromUtc()
5271*/
5272
5273QDateTime QDateTime::toTimeZone(const QTimeZone &timeZone) const
5274{
5275 if (timeRepresentation() == timeZone)
5276 return *this;
5277
5278 if (!isValid()) {
5279 QDateTime ret = *this;
5280 ret.setTimeZone(timeZone);
5281 return ret;
5282 }
5283
5284 return fromMSecsSinceEpoch(toMSecsSinceEpoch(), timeZone);
5285}
5286
5287/*!
5288 \internal
5289 Returns \c true if this datetime is equal to the \a other datetime;
5290 otherwise returns \c false.
5291
5292 \sa precedes(), operator==()
5293*/
5294
5295bool QDateTime::equals(const QDateTime &other) const
5296{
5297 if (!isValid())
5298 return !other.isValid();
5299 if (!other.isValid())
5300 return false;
5301
5302 const qint64 thisMs = getMSecs(d);
5303 const qint64 yourMs = getMSecs(other.d);
5304 if (usesSameOffset(d, other.d) || areFarEnoughApart(thisMs, yourMs))
5305 return thisMs == yourMs;
5306
5307 // Convert to UTC and compare
5308 return toMSecsSinceEpoch() == other.toMSecsSinceEpoch();
5309}
5310
5311/*!
5312 \fn bool QDateTime::operator==(const QDateTime &lhs, const QDateTime &rhs)
5313
5314 Returns \c true if \a lhs represents the same moment in time as \a rhs;
5315 otherwise returns \c false.
5316
5317//! [datetime-order-details]
5318 Two datetimes using different time representations can have different
5319 offsets from UTC. In this case, they may compare equivalent even if their \l
5320 date() and \l time() differ, if that difference matches the difference in
5321 UTC offset. If their \c date() and \c time() coincide, the one with higher
5322 offset from UTC is less (earlier) than the one with lower offset. As a
5323 result, datetimes are only weakly ordered.
5324
5325 Since 5.14, all invalid datetimes are equivalent and less than all valid
5326 datetimes.
5327//! [datetime-order-details]
5328
5329 \sa operator!=(), operator<(), operator<=(), operator>(), operator>=()
5330*/
5331
5332/*!
5333 \fn bool QDateTime::operator!=(const QDateTime &lhs, const QDateTime &rhs)
5334
5335 Returns \c true if \a lhs is different from \a rhs; otherwise returns \c
5336 false.
5337
5338 \include qdatetime.cpp datetime-order-details
5339
5340 \sa operator==()
5341*/
5342
5343Qt::weak_ordering compareThreeWay(const QDateTime &lhs, const QDateTime &rhs)
5344{
5345 if (!lhs.isValid())
5346 return rhs.isValid() ? Qt::weak_ordering::less : Qt::weak_ordering::equivalent;
5347
5348 if (!rhs.isValid())
5349 return Qt::weak_ordering::greater; // we know that lhs is valid here
5350
5351 const qint64 lhms = getMSecs(lhs.d), rhms = getMSecs(rhs.d);
5352 if (usesSameOffset(lhs.d, rhs.d) || areFarEnoughApart(lhms, rhms))
5353 return Qt::compareThreeWay(lhms, rhms);
5354
5355 // Convert to UTC and compare
5356 return Qt::compareThreeWay(lhs.toMSecsSinceEpoch(), rhs.toMSecsSinceEpoch());
5357}
5358
5359/*!
5360 \fn bool QDateTime::operator<(const QDateTime &lhs, const QDateTime &rhs)
5361
5362 Returns \c true if \a lhs is earlier than \a rhs;
5363 otherwise returns \c false.
5364
5365 \include qdatetime.cpp datetime-order-details
5366
5367 \sa operator==()
5368*/
5369
5370/*!
5371 \fn bool QDateTime::operator<=(const QDateTime &lhs, const QDateTime &rhs)
5372
5373 Returns \c true if \a lhs is earlier than or equal to \a rhs; otherwise
5374 returns \c false.
5375
5376 \include qdatetime.cpp datetime-order-details
5377
5378 \sa operator==()
5379*/
5380
5381/*!
5382 \fn bool QDateTime::operator>(const QDateTime &lhs, const QDateTime &rhs)
5383
5384 Returns \c true if \a lhs is later than \a rhs; otherwise returns \c false.
5385
5386 \include qdatetime.cpp datetime-order-details
5387
5388 \sa operator==()
5389*/
5390
5391/*!
5392 \fn bool QDateTime::operator>=(const QDateTime &lhs, const QDateTime &rhs)
5393
5394 Returns \c true if \a lhs is later than or equal to \a rhs;
5395 otherwise returns \c false.
5396
5397 \include qdatetime.cpp datetime-order-details
5398
5399 \sa operator==()
5400*/
5401
5402/*!
5403 \since 6.5
5404 \overload primary
5405 \fn QDateTime QDateTime::currentDateTime(const QTimeZone &zone)
5406
5407 Returns the system clock's current datetime, using the time representation
5408 described by \a zone. If \a zone is omitted, local time is used.
5409
5410 \sa currentDateTimeUtc(), QDate::currentDate(), QTime::currentTime(), toTimeZone()
5411*/
5412
5413/*!
5414 \since 0.90
5415 \overload currentDateTime()
5417QDateTime QDateTime::currentDateTime()
5418{
5419 return currentDateTime(QTimeZone::LocalTime);
5420}
5421
5422/*!
5423 \fn QDateTime QDateTime::currentDateTimeUtc()
5424 \since 4.7
5425 Returns the system clock's current datetime, expressed in terms of UTC.
5426
5427 Equivalent to \c{currentDateTime(QTimeZone::UTC)}.
5428
5429 \sa currentDateTime(), QDate::currentDate(), QTime::currentTime(), toTimeZone()
5430*/
5431
5432QDateTime QDateTime::currentDateTimeUtc()
5433{
5434 return currentDateTime(QTimeZone::UTC);
5435}
5436
5437/*!
5438 \fn qint64 QDateTime::currentMSecsSinceEpoch()
5439 \since 4.7
5440
5441 Returns the current number of milliseconds since the start, in UTC, of the year 1970.
5442
5443 This number is like the POSIX time_t variable, but expressed in milliseconds
5444 instead of seconds.
5445
5446 \sa currentDateTime(), currentDateTimeUtc(), toTimeZone()
5447*/
5448
5449/*!
5450 \fn qint64 QDateTime::currentSecsSinceEpoch()
5451 \since 5.8
5452
5453 Returns the number of seconds since the start, in UTC, of the year 1970.
5454
5455 This number is like the POSIX time_t variable.
5456
5457 \sa currentMSecsSinceEpoch()
5458*/
5459
5460/*!
5461 \since 6.4
5462 \overload primary
5463 \fn template <typename Clock, typename Duration> QDateTime QDateTime::fromStdTimePoint(const std::chrono::time_point<Clock, Duration> &time)
5464
5465 Constructs a datetime representing the same point in time as \a time,
5466 using Qt::UTC as its time representation.
5467
5468 The clock of \a time must be compatible with
5469 \c{std::chrono::system_clock}; in particular, a conversion
5470 supported by \c{std::chrono::clock_cast} must exist. After the
5471 conversion, the duration type of the result must be convertible to
5472 \c{std::chrono::milliseconds}.
5473
5474 If this is not the case, the caller must perform the necessary
5475 clock conversion towards \c{std::chrono::system_clock} and the
5476 necessary conversion of the duration type
5477 (cast/round/floor/ceil/...) so that the input to this function
5478 satisfies the constraints above.
5479
5480 \note This function requires C++20.
5481
5482 \sa toStdSysMilliseconds(), fromMSecsSinceEpoch()
5483*/
5484
5485/*!
5486 \since 6.4
5487 \overload fromStdTimePoint()
5489 Constructs a datetime representing the same point in time as \a time,
5490 using Qt::UTC as its time representation.
5491*/
5492QDateTime QDateTime::fromStdTimePoint(
5493 std::chrono::time_point<
5494 std::chrono::system_clock,
5495 std::chrono::milliseconds
5496 > time)
5497{
5498 return fromMSecsSinceEpoch(time.time_since_epoch().count(), QTimeZone::UTC);
5499}
5500
5501/*!
5502 \fn QDateTime QDateTime::fromStdTimePoint(const std::chrono::local_time<std::chrono::milliseconds> &time)
5503 \since 6.4
5504
5505 Constructs a datetime whose date and time are the number of milliseconds
5506 represented by \a time, counted since 1970-01-01T00:00:00.000 in local
5507 time (Qt::LocalTime).
5508
5509 \note This function requires C++20.
5510
5511 \sa toStdSysMilliseconds(), fromMSecsSinceEpoch()
5512*/
5513
5514/*!
5515 \fn QDateTime QDateTime::fromStdLocalTime(const std::chrono::local_time<std::chrono::milliseconds> &time)
5516 \since 6.4
5517
5518 Constructs a datetime whose date and time are the number of milliseconds
5519 represented by \a time, counted since 1970-01-01T00:00:00.000 in local
5520 time (Qt::LocalTime).
5521
5522 \note This function requires C++20.
5523
5524 \sa toStdSysMilliseconds(), fromMSecsSinceEpoch()
5525*/
5526
5527/*!
5528 \fn QDateTime QDateTime::fromStdZonedTime(const std::chrono::zoned_time<std::chrono::milliseconds, const std::chrono::time_zone *> &time);
5529 \since 6.4
5530
5531 Constructs a datetime representing the same point in time as \a time.
5532 The result will be expressed in \a{time}'s time zone.
5533
5534 \note This function requires C++20.
5535
5536 \sa QTimeZone
5537
5538 \sa toStdSysMilliseconds(), fromMSecsSinceEpoch()
5539*/
5540
5541/*!
5542 \fn std::chrono::sys_time<std::chrono::milliseconds> QDateTime::toStdSysMilliseconds() const
5543 \since 6.4
5544
5545 Converts this datetime object to the equivalent time point expressed in
5546 milliseconds, using \c{std::chrono::system_clock} as a clock.
5547
5548 \note This function requires C++20.
5549
5550 \sa fromStdTimePoint(), toMSecsSinceEpoch()
5551*/
5552
5553/*!
5554 \fn std::chrono::sys_seconds QDateTime::toStdSysSeconds() const
5555 \since 6.4
5556
5557 Converts this datetime object to the equivalent time point expressed in
5558 seconds, using \c{std::chrono::system_clock} as a clock.
5559
5560 \note This function requires C++20.
5561
5562 \sa fromStdTimePoint(), toSecsSinceEpoch()
5563*/
5564
5565#if defined(Q_OS_WIN)
5566static inline uint msecsFromDecomposed(int hour, int minute, int sec, int msec = 0)
5567{
5568 return MSECS_PER_HOUR * hour + MSECS_PER_MIN * minute + MSECS_PER_SEC * sec + msec;
5569}
5570
5571QDate QDate::currentDate()
5572{
5573 SYSTEMTIME st = {};
5574 GetLocalTime(&st);
5575 return QDate(st.wYear, st.wMonth, st.wDay);
5576}
5577
5578QTime QTime::currentTime()
5579{
5580 QTime ct;
5581 SYSTEMTIME st = {};
5582 GetLocalTime(&st);
5583 ct.setHMS(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
5584 return ct;
5585}
5586
5587QDateTime QDateTime::currentDateTime(const QTimeZone &zone)
5588{
5589 // We can get local time or "system" time (which is UTC); otherwise, we must
5590 // convert, which is most efficiently done from UTC.
5591 const Qt::TimeSpec spec = zone.timeSpec();
5592 SYSTEMTIME st = {};
5593 // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtime
5594 // We previously used GetLocalTime for spec == LocalTime but it didn't provide enough
5595 // information to differentiate between repeated hours of a tradition and would report the same
5596 // timezone (eg always CEST, never CET) for both. But toTimeZone handles it correctly, given
5597 // the UTC time.
5598 GetSystemTime(&st);
5599 QDate d(st.wYear, st.wMonth, st.wDay);
5600 QTime t(msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds));
5601 QDateTime utc(d, t, QTimeZone::UTC);
5602 return spec == Qt::UTC ? utc : utc.toTimeZone(zone);
5603}
5604
5605qint64 QDateTime::currentMSecsSinceEpoch() noexcept
5606{
5607 SYSTEMTIME st = {};
5608 GetSystemTime(&st);
5609 const qint64 daysAfterEpoch = QDate(1970, 1, 1).daysTo(QDate(st.wYear, st.wMonth, st.wDay));
5610
5611 return msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds) +
5612 daysAfterEpoch * MSECS_PER_DAY;
5613}
5614
5615qint64 QDateTime::currentSecsSinceEpoch() noexcept
5616{
5617 SYSTEMTIME st = {};
5618 GetSystemTime(&st);
5619 const qint64 daysAfterEpoch = QDate(1970, 1, 1).daysTo(QDate(st.wYear, st.wMonth, st.wDay));
5620
5621 return st.wHour * SECS_PER_HOUR + st.wMinute * SECS_PER_MIN + st.wSecond +
5622 daysAfterEpoch * SECS_PER_DAY;
5623}
5624
5625#elif defined(Q_OS_UNIX) // Assume POSIX-compliant
5626QDate QDate::currentDate()
5627{
5628 return QDateTime::currentDateTime().date();
5629}
5630
5631QTime QTime::currentTime()
5632{
5633 return QDateTime::currentDateTime().time();
5634}
5635
5636QDateTime QDateTime::currentDateTime(const QTimeZone &zone)
5637{
5638 return fromMSecsSinceEpoch(currentMSecsSinceEpoch(), zone);
5639}
5640
5641qint64 QDateTime::currentMSecsSinceEpoch() noexcept
5642{
5643 struct timespec when;
5644 if (clock_gettime(CLOCK_REALTIME, &when) == 0) // should always succeed
5645 return when.tv_sec * MSECS_PER_SEC + (when.tv_nsec + 500'000) / 1'000'000;
5646 Q_UNREACHABLE_RETURN(0);
5647}
5648
5649qint64 QDateTime::currentSecsSinceEpoch() noexcept
5650{
5651 struct timespec when;
5652 if (clock_gettime(CLOCK_REALTIME, &when) == 0) // should always succeed
5653 return when.tv_sec;
5654 Q_UNREACHABLE_RETURN(0);
5655}
5656#else
5657#error "What system is this?"
5658#endif
5659
5660#if QT_DEPRECATED_SINCE(6, 9)
5661/*!
5662 \since 5.2
5663 \overload fromMSecsSinceEpoch()
5664 \deprecated [6.9] Pass a \l QTimeZone instead, or omit \a spec and \a offsetSeconds.
5665
5666 Returns a datetime representing a moment the given number \a msecs of
5667 milliseconds after the start, in UTC, of the year 1970, described as
5668 specified by \a spec and \a offsetSeconds.
5669
5670 Note that there are possible values for \a msecs that lie outside the valid
5671 range of QDateTime, both negative and positive. The behavior of this
5672 function is undefined for those values.
5673
5674 If the \a spec is not Qt::OffsetFromUTC then the \a offsetSeconds will be
5675 ignored. If the \a spec is Qt::OffsetFromUTC and the \a offsetSeconds is 0
5676 then Qt::UTC will be used as the \a spec, since UTC has zero offset.
5677
5678 If \a spec is Qt::TimeZone then Qt::LocalTime will be used in its place,
5679 equivalent to using the current system time zone (but differently
5680 represented).
5681
5682 \sa fromSecsSinceEpoch(), toMSecsSinceEpoch(), setMSecsSinceEpoch()
5683*/
5684QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec, int offsetSeconds)
5685{
5686 return fromMSecsSinceEpoch(msecs,
5687 asTimeZone(spec, offsetSeconds, "QDateTime::fromMSecsSinceEpoch"));
5688}
5689
5690/*!
5691 \since 5.8
5692 \overload fromSecsSinceEpoch
5693 \deprecated [6.9] Pass a \l QTimeZone instead, or omit \a spec and \a offsetSeconds.
5694
5695 Returns a datetime representing a moment the given number \a secs of seconds
5696 after the start, in UTC, of the year 1970, described as specified by \a spec
5697 and \a offsetSeconds.
5698
5699 Note that there are possible values for \a secs that lie outside the valid
5700 range of QDateTime, both negative and positive. The behavior of this
5701 function is undefined for those values.
5702
5703 If the \a spec is not Qt::OffsetFromUTC then the \a offsetSeconds will be
5704 ignored. If the \a spec is Qt::OffsetFromUTC and the \a offsetSeconds is 0
5705 then Qt::UTC will be used as the \a spec, since UTC has zero offset.
5706
5707 If \a spec is Qt::TimeZone then Qt::LocalTime will be used in its place,
5708 equivalent to using the current system time zone (but differently
5709 represented).
5710
5711 \sa fromMSecsSinceEpoch(), toSecsSinceEpoch(), setSecsSinceEpoch()
5712*/
5713QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, Qt::TimeSpec spec, int offsetSeconds)
5714{
5715 return fromSecsSinceEpoch(secs,
5716 asTimeZone(spec, offsetSeconds, "QDateTime::fromSecsSinceEpoch"));
5717}
5718#endif // 6.9 deprecations
5719
5720/*!
5721 \since 5.2
5722 \overload primary
5723
5724 Returns a datetime representing a moment the given number \a msecs of
5725 milliseconds after the start, in UTC, of the year 1970, described as
5726 specified by \a timeZone. The default time representation is local time.
5727
5728 Note that there are possible values for \a msecs that lie outside the valid
5729 range of QDateTime, both negative and positive. The behavior of this
5730 function is undefined for those values.
5731
5732 \sa fromSecsSinceEpoch(), toMSecsSinceEpoch(), setMSecsSinceEpoch()
5733*/
5734QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone)
5735{
5736 QDateTime dt;
5737 reviseTimeZone(dt.d, timeZone, TransitionResolution::Reject);
5738 if (timeZone.isValid())
5739 dt.setMSecsSinceEpoch(msecs);
5740 return dt;
5741}
5742
5743/*!
5744 \overload fromMSecsSinceEpoch()
5746QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
5747{
5748 return fromMSecsSinceEpoch(msecs, QTimeZone::LocalTime);
5749}
5750
5751/*!
5752 \since 5.8
5753 \overload primary
5754
5755 Returns a datetime representing a moment the given number \a secs of seconds
5756 after the start, in UTC, of the year 1970, described as specified by \a
5757 timeZone. The default time representation is local time.
5758
5759 Note that there are possible values for \a secs that lie outside the valid
5760 range of QDateTime, both negative and positive. The behavior of this
5761 function is undefined for those values.
5762
5763 \sa fromMSecsSinceEpoch(), toSecsSinceEpoch(), setSecsSinceEpoch()
5764*/
5765QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, const QTimeZone &timeZone)
5766{
5767 QDateTime dt;
5768 reviseTimeZone(dt.d, timeZone, TransitionResolution::Reject);
5769 if (timeZone.isValid())
5770 dt.setSecsSinceEpoch(secs);
5771 return dt;
5772}
5773
5774/*!
5775 \overload fromSecsSinceEpoch()
5777QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs)
5778{
5779 return fromSecsSinceEpoch(secs, QTimeZone::LocalTime);
5780}
5781
5782#if QT_CONFIG(datestring) // depends on, so implies, textdate
5783
5784/*!
5785 \overload
5786 \fn QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
5787
5788 Returns the QDateTime represented by the \a string, using the
5789 \a format given, or an invalid datetime if this is not possible.
5790
5791 Note for Qt::TextDate: only English short month names (e.g. "Jan" in short
5792 form or "January" in long form) are recognized.
5793
5794 \sa toString(), QLocale::toDateTime()
5795*/
5796
5797/*!
5798 \since 6.0
5799 \overload fromString()
5800*/
5801QDateTime QDateTime::fromString(QStringView string, Qt::DateFormat format)
5802{
5803 if (string.isEmpty())
5804 return QDateTime();
5805
5806 switch (format) {
5807 case Qt::RFC2822Date: {
5808 const ParsedRfcDateTime rfc = rfcDateImpl(string);
5809
5810 if (!rfc.date.isValid() || !rfc.time.isValid())
5811 return QDateTime();
5812
5813 QDateTime dateTime(rfc.date, rfc.time, QTimeZone::UTC);
5814 dateTime.setTimeZone(QTimeZone::fromSecondsAheadOfUtc(rfc.utcOffset));
5815 return dateTime;
5816 }
5817 case Qt::ISODate:
5818 case Qt::ISODateWithMs: {
5819 const int size = string.size();
5820 if (size < 10)
5821 return QDateTime();
5822
5823 QDate date = QDate::fromString(string.first(10), Qt::ISODate);
5824 if (!date.isValid())
5825 return QDateTime();
5826 if (size == 10)
5827 return date.startOfDay();
5828
5829 QTimeZone zone = QTimeZone::LocalTime;
5830 QStringView isoString = string.sliced(10); // trim "yyyy-MM-dd"
5831
5832 // Must be left with T (or space) and at least one digit for the hour:
5833 if (isoString.size() < 2
5834 || !(isoString.startsWith(u'T', Qt::CaseInsensitive)
5835 // RFC 3339 (section 5.6) allows a space here. (It actually
5836 // allows any separator one considers more readable, merely
5837 // giving space as an example - but let's not go wild !)
5838 || isoString.startsWith(u' '))) {
5839 return QDateTime();
5840 }
5841 isoString = isoString.sliced(1); // trim 'T' (or space)
5842
5843 // Check end of string for Time Zone definition, either Z for UTC or ±HH:mm for Offset
5844 if (isoString.endsWith(u'Z', Qt::CaseInsensitive)) {
5845 zone = QTimeZone::UTC;
5846 isoString.chop(1); // trim 'Z'
5847 } else {
5848 // the loop below is faster but functionally equal to:
5849 // const int signIndex = isoString.indexOf(QRegulargExpression(QStringLiteral("[+-]")));
5850 int signIndex = isoString.size() - 1;
5851 Q_ASSERT(signIndex >= 0);
5852 bool found = false;
5853 do {
5854 QChar character(isoString[signIndex]);
5855 found = character == u'+' || character == u'-';
5856 } while (!found && --signIndex >= 0);
5857
5858 if (found) {
5859 bool ok;
5860 int offset = fromOffsetString(isoString.sliced(signIndex), &ok);
5861 if (!ok)
5862 return QDateTime();
5863 isoString = isoString.first(signIndex);
5864 zone = QTimeZone::fromSecondsAheadOfUtc(offset);
5865 }
5866 }
5867
5868 // Might be end of day (24:00, including variants), which QTime considers invalid.
5869 // ISO 8601 (section 4.2.3) says that 24:00 is equivalent to 00:00 the next day.
5870 bool isMidnight24 = false;
5871 QTime time = fromIsoTimeString(isoString, format, &isMidnight24);
5872 if (!time.isValid())
5873 return QDateTime();
5874 if (isMidnight24) // time is 0:0, but we want the start of next day:
5875 return date.addDays(1).startOfDay(zone);
5876 return QDateTime(date, time, zone);
5877 }
5878 case Qt::TextDate: {
5879 QVarLengthArray<QStringView, 6> parts;
5880
5881 auto tokens = string.tokenize(u' ', Qt::SkipEmptyParts);
5882 auto it = tokens.begin();
5883 for (int i = 0; i < 6 && it != tokens.end(); ++i, ++it)
5884 parts.emplace_back(*it);
5885
5886 // Documented as "ddd MMM d HH:mm:ss yyyy" with optional offset-suffix;
5887 // and allow time either before or after year.
5888 if (parts.size() < 5 || it != tokens.end())
5889 return QDateTime();
5890
5891 // Year and time can be in either order.
5892 // Guess which by looking for ':' in the time
5893 int yearPart = 3;
5894 int timePart = 3;
5895 if (parts.at(3).contains(u':'))
5896 yearPart = 4;
5897 else if (parts.at(4).contains(u':'))
5898 timePart = 4;
5899 else
5900 return QDateTime();
5901
5902 bool ok = false;
5903 int day = parts.at(2).toInt(&ok);
5904 int year = ok ? parts.at(yearPart).toInt(&ok) : 0;
5905 int month = fromShortMonthName(parts.at(1));
5906 if (!ok || year == 0 || day == 0 || month < 1)
5907 return QDateTime();
5908
5909 const QDate date(year, month, day);
5910 if (!date.isValid())
5911 return QDateTime();
5912
5913 const QTime time = fromIsoTimeString(parts.at(timePart), format, nullptr);
5914 if (!time.isValid())
5915 return QDateTime();
5916
5917 if (parts.size() == 5)
5918 return QDateTime(date, time);
5919
5920 QStringView tz = parts.at(5);
5921 if (tz.startsWith("UTC"_L1)
5922 // GMT has long been deprecated as an alias for UTC.
5923 || tz.startsWith("GMT"_L1, Qt::CaseInsensitive)) {
5924 tz = tz.sliced(3);
5925 if (tz.isEmpty())
5926 return QDateTime(date, time, QTimeZone::UTC);
5927
5928 int offset = fromOffsetString(tz, &ok);
5929 return ok ? QDateTime(date, time, QTimeZone::fromSecondsAheadOfUtc(offset))
5930 : QDateTime();
5931 }
5932 return QDateTime();
5933 }
5934 }
5935
5936 return QDateTime();
5937}
5938
5939/*!
5940 \overload primary
5941 \fn QDateTime QDateTime::fromString(const QString &string, const QString &format, int baseYear, QCalendar cal)
5942
5943 Returns the QDateTime represented by the \a string, using the \a
5944 format given, or an invalid datetime if the string cannot be parsed.
5945
5946 Uses the calendar \a cal if supplied, else Gregorian.
5947
5948 \include qlocale.cpp base-year-for-two-digit
5949
5950 In addition to the expressions, recognized in the format string to represent
5951 parts of the date and time, by QDate::fromString() and QTime::fromString(),
5952 this method supports:
5953
5954 \table
5955 \header \li Expression \li Output
5956 \row \li t
5957 \li the timezone (offset, name, "Z" or offset with "UTC" prefix)
5958 \row \li tt
5959 \li the timezone in offset format with no colon between hours and
5960 minutes (for example "+0200")
5961 \row \li ttt
5962 \li the timezone in offset format with a colon between hours and
5963 minutes (for example "+02:00")
5964 \row \li tttt
5965 \li the timezone name, either what \l QTimeZone::displayName() reports
5966 for \l QTimeZone::LongName or the IANA ID of the zone (for example
5967 "Europe/Berlin"). The names recognized are those known to \l
5968 QTimeZone, which may depend on the operating system in use.
5969 \endtable
5970
5971 If no 't' format specifier is present, the system's local time-zone is used.
5972 For the defaults of all other fields, see QDate::fromString() and QTime::fromString().
5973
5974 For example:
5975
5976 \snippet code/src_corelib_time_qdatetime.cpp 14
5977
5978 All other input characters will be treated as text. Any non-empty sequence
5979 of characters enclosed in single quotes will also be treated (stripped of
5980 the quotes) as text and not be interpreted as expressions.
5981
5982 \snippet code/src_corelib_time_qdatetime.cpp 12
5983
5984 If the format is not satisfied, an invalid QDateTime is returned. If the
5985 format is satisfied but \a string represents an invalid datetime (e.g. in a
5986 gap skipped by a time-zone transition), an valid QDateTime is returned, that
5987 represents a near-by datetime that is valid.
5988
5989 The expressions that don't have leading zeroes (d, M, h, m, s, z) will be
5990 greedy. This means that they will use two digits (or three, for z) even if this will
5991 put them outside the range and/or leave too few digits for other
5992 sections.
5993
5994 \snippet code/src_corelib_time_qdatetime.cpp 13
5995
5996 This could have meant 1 January 00:30.00 but the M will grab
5997 two digits.
5998
5999 Incorrectly specified fields of the \a string will cause an invalid
6000 QDateTime to be returned. Only datetimes between the local time start of
6001 year 100 and end of year 9999 are supported. Note that datetimes near the
6002 ends of this range in other time-zones, notably including UTC, may fall
6003 outside the range (and thus be treated as invalid) depending on local time
6004 zone.
6005
6006 \note Day and month names as well as AM/PM indicators must be given in
6007 English (C locale). If localized month and day names or localized forms of
6008 AM/PM are to be recognized, use QLocale::system().toDateTime().
6009
6010 \note If a format character is repeated more times than the longest
6011 expression in the table above using it, this part of the format will be read
6012 as several expressions with no separator between them; the longest above,
6013 possibly repeated as many times as there are copies of it, ending with a
6014 residue that may be a shorter expression. Thus \c{'tttttt'} would match
6015 \c{"Europe/BerlinEurope/Berlin"} and set the zone to Berlin time; if the
6016 datetime string contained "Europe/BerlinZ" it would "match" but produce an
6017 inconsistent result, leading to an invalid datetime.
6018
6019 \sa toString(), QDate::fromString(), QTime::fromString(),
6020 QLocale::toDateTime()
6021*/
6022
6023/*!
6024 \since 6.0
6025 \overload fromString()
6026 \fn QDateTime QDateTime::fromString(QStringView string, QStringView format, QCalendar cal)
6027*/
6028
6029/*!
6030 \since 6.0
6031 \overload fromString()
6032*/
6033QDateTime QDateTime::fromString(const QString &string, QStringView format, int baseYear,
6034 QCalendar cal)
6035{
6036#if QT_CONFIG(datetimeparser)
6037 QDateTime datetime;
6038
6039 QDateTimeParser dt(QMetaType::QDateTime, QDateTimeParser::FromString, cal);
6040 dt.setDefaultLocale(QLocale::c());
6041 if (dt.parseFormat(format) && (dt.fromString(string, &datetime, baseYear)
6042 || !datetime.isValid())) {
6043 return datetime;
6044 }
6045#else
6046 Q_UNUSED(string);
6047 Q_UNUSED(format);
6048 Q_UNUSED(baseYear);
6049 Q_UNUSED(cal);
6050#endif
6051 return QDateTime();
6052}
6053
6054/*!
6055 \since 5.14
6056 \overload fromString()
6057 \fn QDateTime QDateTime::fromString(const QString &string, const QString &format, QCalendar cal)
6058*/
6059
6060/*!
6061 \since 6.0
6062 \overload fromString()
6063 \fn QDateTime QDateTime::fromString(const QString &string, QStringView format, QCalendar cal)
6064*/
6065
6066/*!
6067 \since 6.7
6068 \overload fromString()
6069 \fn QDateTime QDateTime::fromString(QStringView string, QStringView format, int baseYear, QCalendar cal)
6070*/
6071
6072/*!
6073 \since 6.7
6074 \overload fromString()
6075 \fn QDateTime QDateTime::fromString(QStringView string, QStringView format, int baseYear)
6076
6077 Uses a default-constructed QCalendar.
6078*/
6079
6080/*!
6081 \since 6.7
6082 \overload fromString()
6083
6084 Uses a default-constructed QCalendar.
6085*/
6086QDateTime QDateTime::fromString(const QString &string, QStringView format, int baseYear)
6087{
6088 return fromString(string, format, baseYear, QCalendar());
6089}
6090
6091/*!
6092 \since 6.7
6093 \overload fromString()
6094 \fn QDateTime QDateTime::fromString(const QString &string, const QString &format, int baseYear)
6095
6096 Uses a default-constructed QCalendar.
6097*/
6098#endif // datestring
6099
6100/*****************************************************************************
6101 Date/time stream functions
6102 *****************************************************************************/
6103
6104#ifndef QT_NO_DATASTREAM
6105/*!
6106 \relates QDate
6107
6108 Writes the \a date to stream \a out.
6109
6110 \sa {Serializing Qt Data Types}
6111*/
6112
6113QDataStream &operator<<(QDataStream &out, QDate date)
6114{
6115 if (out.version() < QDataStream::Qt_5_0)
6116 return out << quint32(date.jd);
6117 else
6118 return out << date.jd;
6119}
6120
6121/*!
6122 \relates QDate
6123
6124 Reads a date from stream \a in into the \a date.
6125
6126 \sa {Serializing Qt Data Types}
6127*/
6128
6129QDataStream &operator>>(QDataStream &in, QDate &date)
6130{
6131 if (in.version() < QDataStream::Qt_5_0) {
6132 quint32 jd;
6133 in >> jd;
6134 // Older versions consider 0 an invalid jd.
6135 date.jd = (jd != 0 ? jd : QDate::nullJd());
6136 } else {
6137 in >> date.jd;
6138 }
6139
6140 return in;
6141}
6142
6143/*!
6144 \relates QTime
6145
6146 Writes \a time to stream \a out.
6147
6148 \sa {Serializing Qt Data Types}
6149*/
6150
6151QDataStream &operator<<(QDataStream &out, QTime time)
6152{
6153 if (out.version() >= QDataStream::Qt_4_0) {
6154 return out << quint32(time.mds);
6155 } else {
6156 // Qt3 had no support for reading -1, QTime() was valid and serialized as 0
6157 return out << quint32(time.isNull() ? 0 : time.mds);
6158 }
6159}
6160
6161/*!
6162 \relates QTime
6163
6164 Reads a time from stream \a in into the given \a time.
6165
6166 \sa {Serializing Qt Data Types}
6167*/
6168
6169QDataStream &operator>>(QDataStream &in, QTime &time)
6170{
6171 quint32 ds;
6172 in >> ds;
6173 if (in.version() >= QDataStream::Qt_4_0) {
6174 time.mds = int(ds);
6175 } else {
6176 // Qt3 would write 0 for a null time
6177 time.mds = (ds == 0) ? QTime::NullTime : int(ds);
6178 }
6179 return in;
6180}
6181
6182/*!
6183 \relates QDateTime
6184
6185 Writes \a dateTime to the \a out stream.
6186
6187 \sa {Serializing Qt Data Types}
6188*/
6189QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
6190{
6191 std::pair<QDate, QTime> dateAndTime;
6192
6193 // TODO: new version, route spec and details via QTimeZone
6194 if (out.version() >= QDataStream::Qt_5_2) {
6195
6196 // In 5.2 we switched to using Qt::TimeSpec and added offset and zone support
6197 dateAndTime = getDateTime(dateTime.d);
6198 out << dateAndTime << qint8(dateTime.timeSpec());
6199 if (dateTime.timeSpec() == Qt::OffsetFromUTC)
6200 out << qint32(dateTime.offsetFromUtc());
6201#if QT_CONFIG(timezone)
6202 else if (dateTime.timeSpec() == Qt::TimeZone)
6203 out << dateTime.timeZone();
6204#endif // timezone
6205
6206 } else if (out.version() == QDataStream::Qt_5_0) {
6207
6208 // In Qt 5.0 we incorrectly serialised all datetimes as UTC.
6209 // This approach is wrong and should not be used again; it breaks
6210 // the guarantee that a deserialised local datetime is the same time
6211 // of day, regardless of which timezone it was serialised in.
6212 dateAndTime = getDateTime((dateTime.isValid() ? dateTime.toUTC() : dateTime).d);
6213 out << dateAndTime << qint8(dateTime.timeSpec());
6214
6215 } else if (out.version() >= QDataStream::Qt_4_0) {
6216
6217 // From 4.0 to 5.1 (except 5.0) we used QDateTimePrivate::Spec
6218 dateAndTime = getDateTime(dateTime.d);
6219 out << dateAndTime;
6220 switch (dateTime.timeSpec()) {
6221 case Qt::UTC:
6222 out << (qint8)QDateTimePrivate::UTC;
6223 break;
6224 case Qt::OffsetFromUTC:
6225 out << (qint8)QDateTimePrivate::OffsetFromUTC;
6226 break;
6227 case Qt::TimeZone:
6228 out << (qint8)QDateTimePrivate::TimeZone;
6229 break;
6230 case Qt::LocalTime:
6231 out << (qint8)QDateTimePrivate::LocalUnknown;
6232 break;
6233 }
6234
6235 } else { // version < QDataStream::Qt_4_0
6236
6237 // Before 4.0 there was no TimeSpec, only Qt::LocalTime was supported
6238 dateAndTime = getDateTime(dateTime.d);
6239 out << dateAndTime;
6240
6241 }
6242
6243 return out;
6244}
6245
6246/*!
6247 \relates QDateTime
6248
6249 Reads a datetime from the stream \a in into \a dateTime.
6250
6251 \sa {Serializing Qt Data Types}
6252*/
6253
6254QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
6255{
6256 QDate dt;
6257 QTime tm;
6258 qint8 ts = 0;
6259 QTimeZone zone(QTimeZone::LocalTime);
6260
6261 if (in.version() >= QDataStream::Qt_5_2) {
6262
6263 // In 5.2 we switched to using Qt::TimeSpec and added offset and zone support
6264 in >> dt >> tm >> ts;
6265 switch (static_cast<Qt::TimeSpec>(ts)) {
6266 case Qt::UTC:
6267 zone = QTimeZone::UTC;
6268 break;
6269 case Qt::OffsetFromUTC: {
6270 qint32 offset = 0;
6271 in >> offset;
6272 zone = QTimeZone::fromSecondsAheadOfUtc(offset);
6273 break;
6274 }
6275 case Qt::LocalTime:
6276 break;
6277 case Qt::TimeZone:
6278 in >> zone;
6279 break;
6280 }
6281 // Note: no way to resolve transition ambiguity, when relevant; use default.
6282 dateTime = QDateTime(dt, tm, zone);
6283
6284 } else if (in.version() == QDataStream::Qt_5_0) {
6285
6286 // In Qt 5.0 we incorrectly serialised all datetimes as UTC
6287 in >> dt >> tm >> ts;
6288 dateTime = QDateTime(dt, tm, QTimeZone::UTC);
6289 if (static_cast<Qt::TimeSpec>(ts) == Qt::LocalTime)
6290 dateTime = dateTime.toTimeZone(zone);
6291
6292 } else if (in.version() >= QDataStream::Qt_4_0) {
6293
6294 // From 4.0 to 5.1 (except 5.0) we used QDateTimePrivate::Spec
6295 in >> dt >> tm >> ts;
6296 switch (static_cast<QDateTimePrivate::Spec>(ts)) {
6297 case QDateTimePrivate::OffsetFromUTC: // No offset was stored, so treat as UTC.
6298 case QDateTimePrivate::UTC:
6299 zone = QTimeZone::UTC;
6300 break;
6301 case QDateTimePrivate::TimeZone: // No zone was stored, so treat as LocalTime:
6302 case QDateTimePrivate::LocalUnknown:
6303 case QDateTimePrivate::LocalStandard:
6304 case QDateTimePrivate::LocalDST:
6305 break;
6306 }
6307 dateTime = QDateTime(dt, tm, zone);
6308
6309 } else { // version < QDataStream::Qt_4_0
6310
6311 // Before 4.0 there was no TimeSpec, only Qt::LocalTime was supported
6312 in >> dt >> tm;
6313 dateTime = QDateTime(dt, tm);
6314
6315 }
6316
6317 return in;
6318}
6319#endif // QT_NO_DATASTREAM
6320
6321/*****************************************************************************
6322 Date / Time Debug Streams
6323*****************************************************************************/
6324
6325#if !defined(QT_NO_DEBUG_STREAM) && QT_CONFIG(datestring)
6326QDebug operator<<(QDebug dbg, QDate date)
6327{
6328 QDebugStateSaver saver(dbg);
6329 dbg.nospace() << "QDate(";
6330 if (date.isValid())
6331 // QTBUG-91070, ISODate only supports years in the range 0-9999
6332 if (int y = date.year(); y > 0 && y <= 9999)
6333 dbg.nospace() << date.toString(Qt::ISODate);
6334 else
6335 dbg.nospace() << date.toString(Qt::TextDate);
6336 else
6337 dbg.nospace() << "Invalid";
6338 dbg.nospace() << ')';
6339 return dbg;
6340}
6341
6342QDebug operator<<(QDebug dbg, QTime time)
6343{
6344 QDebugStateSaver saver(dbg);
6345 dbg.nospace() << "QTime(";
6346 if (time.isValid())
6347 dbg.nospace() << time.toString(u"HH:mm:ss.zzz");
6348 else
6349 dbg.nospace() << "Invalid";
6350 dbg.nospace() << ')';
6351 return dbg;
6352}
6353
6354QDebug operator<<(QDebug dbg, const QDateTime &date)
6355{
6356 QDebugStateSaver saver(dbg);
6357 dbg.nospace() << "QDateTime(";
6358 if (date.isValid()) {
6359 const Qt::TimeSpec ts = date.timeSpec();
6360 dbg.noquote() << date.toString(u"yyyy-MM-dd HH:mm:ss.zzz t")
6361 << ' ' << ts;
6362 switch (ts) {
6363 case Qt::UTC:
6364 break;
6365 case Qt::OffsetFromUTC:
6366 dbg.space() << date.offsetFromUtc() << 's';
6367 break;
6368 case Qt::TimeZone:
6369#if QT_CONFIG(timezone)
6370 dbg.space() << date.timeZone().id();
6371#endif // timezone
6372 break;
6373 case Qt::LocalTime:
6374 break;
6375 }
6376 } else {
6377 dbg.nospace() << "Invalid";
6378 }
6379 return dbg.nospace() << ')';
6380}
6381#endif // debug_stream && datestring
6382
6383/*! \fn size_t qHash(const QDateTime &key, size_t seed = 0)
6384 \qhashold{QHash}
6385 \since 5.0
6386*/
6387size_t qHash(const QDateTime &key, size_t seed)
6388{
6389 // Use to toMSecsSinceEpoch instead of individual qHash functions for
6390 // QDate/QTime/spec/offset because QDateTime::operator== converts both arguments
6391 // to the same timezone. If we don't, qHash would return different hashes for
6392 // two QDateTimes that are equivalent once converted to the same timezone.
6393 return key.isValid() ? qHash(key.toMSecsSinceEpoch(), seed) : seed;
6394}
6395
6396/*! \fn size_t qHash(QDate key, size_t seed = 0)
6397 \qhashold{QHash}
6398 \since 5.0
6399*/
6400size_t qHash(QDate key, size_t seed) noexcept
6401{
6402 return qHash(key.toJulianDay(), seed);
6403}
6404
6405/*! \fn size_t qHash(QTime key, size_t seed = 0)
6406 \qhashold{QHash}
6407 \since 5.0
6408*/
6409size_t qHash(QTime key, size_t seed) noexcept
6410{
6411 return qHash(key.msecsSinceStartOfDay(), seed);
6412}
6413
6414QT_END_NAMESPACE
size_t qHash(QTime key, size_t seed) noexcept
\qhashold{QHash}
static QTime msecsToTime(qint64 msecs)
static auto millisToWithinRange(qint64 millis)
static QDateTime toLatest(QDate day, const QTimeZone &zone)
static constexpr QDateTimePrivate::StatusFlags mergeDaylightStatus(QDateTimePrivate::StatusFlags sf, QDateTimePrivate::DaylightStatus status)
static QDate fixedDate(QCalendar::YearMonthDay parts)
Definition qdatetime.cpp:63
static qint64 timeToMSecs(QDate date, QTime time)
static std::pair< QDate, QTime > getDateTime(const QDateTimeData &d)
static constexpr QDateTimePrivate::DaylightStatus extractDaylightStatus(QDateTimePrivate::StatusFlags status)
size_t qHash(const QDateTime &key, size_t seed)
\qhashold{QHash}
static Qt::TimeSpec getSpec(const QDateTimeData &d)
QDateTimePrivate::QDateTimeShortData ShortData
static void reviseTimeZone(QDateTimeData &d, const QTimeZone &zone, QDateTime::TransitionResolution resolve)
static QDateTimePrivate::StatusFlags getStatus(const QDateTimeData &d)
static qint64 getMSecs(const QDateTimeData &d)
static void massageAdjustedDateTime(QDateTimeData &d, QDate date, QTime time, bool forward)
static bool inDateTimeRange(qint64 jd, DaySide side)
QDateTimePrivate::QDateTimeData QDateTimeData
static bool specCanBeSmall(Qt::TimeSpec spec)
static int systemTimeYearMatching(int year)
static constexpr QDateTimePrivate::StatusFlags mergeSpec(QDateTimePrivate::StatusFlags status, Qt::TimeSpec spec)
static QDate msecsToDate(qint64 msecs)
static QString toOffsetString(Qt::DateFormat format, int offset)
size_t qHash(QDate key, size_t seed) noexcept
\qhashold{QHash}
static bool daysAndMillisOverflow(qint64 days, qint64 millisInDay, qint64 *sumMillis)
static QDate fixedDate(QCalendar::YearMonthDay parts, QCalendar cal)
Definition qdatetime.cpp:54
static constexpr QDateTimePrivate::TransitionOptions toTransitionOptions(QDateTime::TransitionResolution res)
static void refreshSimpleDateTime(QDateTimeData &d)
bool areFarEnoughApart(qint64 leftMillis, qint64 rightMillis)
static void setDateTime(QDateTimeData &d, QDate date, QTime time)
static void refreshZonedDateTime(QDateTimeData &d, const QTimeZone &zone, QDateTimePrivate::TransitionOptions resolve)
static bool msecsCanBeSmall(qint64 msecs)
static constexpr Qt::TimeSpec extractSpec(QDateTimePrivate::StatusFlags status)
static bool usesSameOffset(const QDateTimeData &a, const QDateTimeData &b)
static void checkValidDateTime(QDateTimeData &d, QDateTime::TransitionResolution resolve)
Qt::weak_ordering compareThreeWay(const QDateTime &lhs, const QDateTime &rhs)
static QDateTime toEarliest(QDate day, const QTimeZone &zone)
static QDateTimePrivate::ZoneState stateAtMillis(const QTimeZone &zone, qint64 millis, QDateTimePrivate::TransitionOptions resolve)
static bool millisInSystemRange(qint64 millis, qint64 slack=0)
static qint64 msecsToJulianDay(qint64 msecs)
DaySide