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 \endtable
2234
2235 \note To get localized forms of AM or PM (the \c{AP}, \c{ap}, \c{A}, \c{a},
2236 \c{aP} or \c{Ap} formats) or of time zone representations (the \c{t}
2237 formats), use QLocale::system().toString().
2238
2239 Any non-empty sequence of characters enclosed in single quotes will be
2240 included verbatim in the output string (stripped of the quotes), even if it
2241 contains formatting characters. Two consecutive single quotes ("''") are
2242 replaced by a single quote in the output. All other characters in the format
2243 string are included verbatim in the output string.
2244
2245 Formats without separators (e.g. "hhmm") are supported but must be used with
2246 care, as the resulting strings aren't always reliably readable (e.g. if "Hm"
2247 produces "212" it could mean either 02:12 or 21:02).
2248
2249 Example format strings (assuming that the QTime is 14:13:09.042)
2250
2251 \table
2252 \header \li Format \li Result
2253 \row \li hh:mm:ss.zzz \li 14:13:09.042
2254 \row \li h:m:s ap \li 2:13:9 pm
2255 \row \li H:m:s a \li 14:13:9 pm
2256 \endtable
2257
2258 \note If a format character is repeated more times than the longest
2259 expression in the table above using it, this part of the format will be read
2260 as several expressions with no separator between them; the longest above,
2261 possibly repeated as many times as there are copies of it, ending with a
2262 residue that may be a shorter expression. Thus \c{'HHHHH'} for the time
2263 08:00 will contribute \c{"08088"} to the output.
2264
2265 Prior to Qt 6.12 the 't' family of format expressions (see
2266 QDateTime::toString() for details) was supported for QTime, using the
2267 timezone information of QDateTime::currentDateTime(). This is misleading and
2268 does not match the \c fromString() behavior, which only supports timezone
2269 expressions for QDateTime. While Qt 6 does still support this usage for
2270 QTime, a warning is issued if it is exercised and support for it shall be
2271 withdrawn at Qt 7. Where the date is implied by context it is, of course,
2272 possible to format a datetime using a format string that only exercises time
2273 and timezone expressions, but the datetime should use the date implied by
2274 context to ensure that its timezone description is correct for that date.
2275 As a further side-effect, any 't' charaters in a time format that you don't
2276 want interpreted as a zone specifier should be enclosed within single
2277 quotes.
2278
2279 \sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
2280*/
2281QString QTime::toString(QStringView format) const
2282{
2283 return QLocale::c().toString(*this, format);
2284}
2285#endif // datestring
2286
2287/*!
2288 Sets the time to hour \a h, minute \a m, seconds \a s and
2289 milliseconds \a ms.
2290
2291 \a h must be in the range 0 to 23, \a m and \a s must be in the
2292 range 0 to 59, and \a ms must be in the range 0 to 999.
2293 Returns \c true if the set time is valid; otherwise returns \c false.
2294
2295 \sa isValid()
2296*/
2297
2298bool QTime::setHMS(int h, int m, int s, int ms)
2299{
2300 if (!isValid(h,m,s,ms)) {
2301 mds = NullTime; // make this invalid
2302 return false;
2303 }
2304 mds = ((h * MINS_PER_HOUR + m) * SECS_PER_MIN + s) * MSECS_PER_SEC + ms;
2305 Q_ASSERT(mds >= 0 && mds < MSECS_PER_DAY);
2306 return true;
2307}
2308
2309/*!
2310 Returns a QTime object containing a time \a s seconds later
2311 than the time of this object (or earlier if \a s is negative).
2312
2313 Note that the time will wrap if it passes midnight.
2314
2315 Returns a null time if this time is invalid.
2316
2317 Example:
2318
2319 \snippet code/src_corelib_time_qdatetime.cpp 5
2320
2321 \sa addMSecs(), secsTo(), QDateTime::addSecs()
2322*/
2323
2324QTime QTime::addSecs(int s) const
2325{
2326 s %= SECS_PER_DAY;
2327 return addMSecs(s * MSECS_PER_SEC);
2328}
2329
2330/*!
2331 Returns the number of seconds from this time to \a t.
2332 If \a t is earlier than this time, the number of seconds returned
2333 is negative.
2334
2335 Because QTime measures time within a day and there are 86400
2336 seconds in a day, the result is always between -86400 and 86400.
2337
2338 secsTo() does not take into account any milliseconds.
2339
2340 Returns 0 if either time is invalid.
2341
2342 \sa addSecs(), QDateTime::secsTo()
2343*/
2344
2345int QTime::secsTo(QTime t) const
2346{
2347 if (!isValid() || !t.isValid())
2348 return 0;
2349
2350 // Truncate milliseconds as we do not want to consider them.
2351 int ourSeconds = ds() / MSECS_PER_SEC;
2352 int theirSeconds = t.ds() / MSECS_PER_SEC;
2353 return theirSeconds - ourSeconds;
2354}
2355
2356/*!
2357 Returns a QTime object containing a time \a ms milliseconds later
2358 than the time of this object (or earlier if \a ms is negative).
2359
2360 Note that the time will wrap if it passes midnight. See addSecs()
2361 for an example.
2362
2363 Returns a null time if this time is invalid.
2364
2365 \sa addSecs(), msecsTo(), QDateTime::addMSecs()
2366*/
2367
2368QTime QTime::addMSecs(int ms) const
2369{
2370 QTime t;
2371 if (isValid())
2372 t.mds = QRoundingDown::qMod<MSECS_PER_DAY>(ds() + ms);
2373 return t;
2374}
2375
2376/*!
2377 Returns the number of milliseconds from this time to \a t.
2378 If \a t is earlier than this time, the number of milliseconds returned
2379 is negative.
2380
2381 Because QTime measures time within a day and there are 86400
2382 seconds in a day, the result is always between -86400000 and
2383 86400000 ms.
2384
2385 Returns 0 if either time is invalid.
2386
2387 \sa secsTo(), addMSecs(), QDateTime::msecsTo()
2388*/
2389
2390int QTime::msecsTo(QTime t) const
2391{
2392 if (!isValid() || !t.isValid())
2393 return 0;
2394 return t.ds() - ds();
2395}
2396
2397
2398/*!
2399 \fn bool QTime::operator==(const QTime &lhs, const QTime &rhs)
2400
2401 Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false.
2402*/
2403
2404/*!
2405 \fn bool QTime::operator!=(const QTime &lhs, const QTime &rhs)
2406
2407 Returns \c true if \a lhs is different from \a rhs; otherwise returns \c false.
2408*/
2409
2410/*!
2411 \fn bool QTime::operator<(const QTime &lhs, const QTime &rhs)
2412
2413 Returns \c true if \a lhs is earlier than \a rhs; otherwise returns \c false.
2414*/
2415
2416/*!
2417 \fn bool QTime::operator<=(const QTime &lhs, const QTime &rhs)
2418
2419 Returns \c true if \a lhs is earlier than or equal to \a rhs;
2420 otherwise returns \c false.
2421*/
2422
2423/*!
2424 \fn bool QTime::operator>(const QTime &lhs, const QTime &rhs)
2425
2426 Returns \c true if \a lhs is later than \a rhs; otherwise returns \c false.
2427*/
2428
2429/*!
2430 \fn bool QTime::operator>=(const QTime &lhs, const QTime &rhs)
2431
2432 Returns \c true if \a lhs is later than or equal to \a rhs;
2433 otherwise returns \c false.
2434*/
2435
2436/*!
2437 \fn QTime QTime::fromMSecsSinceStartOfDay(int msecs)
2438
2439 Returns a new QTime instance with the time set to the number of \a msecs
2440 since the start of the day, i.e. since 00:00:00.
2441
2442 If \a msecs falls outside the valid range an invalid QTime will be returned.
2443
2444 \sa msecsSinceStartOfDay()
2445*/
2446
2447/*!
2448 \fn int QTime::msecsSinceStartOfDay() const
2449
2450 Returns the number of msecs since the start of the day, i.e. since 00:00:00.
2451
2452 \sa fromMSecsSinceStartOfDay()
2453*/
2454
2455/*!
2456 \fn QTime::currentTime()
2457
2458 Returns the current time as reported by the system clock.
2459
2460 Note that the accuracy depends on the accuracy of the underlying
2461 operating system; not all systems provide 1-millisecond accuracy.
2462
2463 Furthermore, currentTime() only increases within each day; it shall drop by
2464 24 hours each time midnight passes; and, beside this, changes in it may not
2465 correspond to elapsed time, if a daylight-saving transition intervenes.
2466
2467 \sa QDateTime::currentDateTime(), QDateTime::currentDateTimeUtc()
2468*/
2469
2470#if QT_CONFIG(datestring) // depends on, so implies, textdate
2471
2472static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *isMidnight24)
2473{
2474 Q_ASSERT(format == Qt::TextDate || format == Qt::ISODate || format == Qt::ISODateWithMs);
2475 if (isMidnight24)
2476 *isMidnight24 = false;
2477 // Match /\d\d(:\d\d(:\d\d)?)?([,.]\d+)?/ as "HH[:mm[:ss]][.zzz]"
2478 // The fractional part, if present, is in the same units as the field it follows.
2479 // TextDate restricts fractional parts to the seconds field.
2480
2481 QStringView tail;
2482 const qsizetype dot = string.indexOf(u'.'), comma = string.indexOf(u',');
2483 if (dot != -1) {
2484 tail = string.sliced(dot + 1);
2485 if (tail.indexOf(u'.') != -1) // Forbid second dot:
2486 return QTime();
2487 string = string.first(dot);
2488 } else if (comma != -1) {
2489 tail = string.sliced(comma + 1);
2490 string = string.first(comma);
2491 }
2492 if (tail.indexOf(u',') != -1) // Forbid comma after first dot-or-comma:
2493 return QTime();
2494
2495 const ParsedInt frac = readInt(tail);
2496 // There must be *some* digits in a fractional part; and it must be all digits:
2497 if (tail.isEmpty() ? dot != -1 || comma != -1 : !frac.ok())
2498 return QTime();
2499 Q_ASSERT(frac.ok() ^ tail.isEmpty());
2500 double fraction = frac.ok() ? frac.result * std::pow(0.1, tail.size()) : 0.0;
2501
2502 const qsizetype size = string.size();
2503 if (size < 2 || size > 8)
2504 return QTime();
2505
2506 ParsedInt hour = readInt(string.first(2));
2507 if (!hour.ok() || hour.result > (format == Qt::TextDate ? 23 : 24))
2508 return QTime();
2509
2510 ParsedInt minute{};
2511 if (string.size() > 2) {
2512 if (string[2] == u':' && string.size() > 4)
2513 minute = readInt(string.sliced(3, 2));
2514 if (!minute.ok() || minute.result >= MINS_PER_HOUR)
2515 return QTime();
2516 } else if (format == Qt::TextDate) { // Requires minutes
2517 return QTime();
2518 } else if (frac.ok()) {
2519 Q_ASSERT(!(fraction < 0.0) && fraction < 1.0);
2520 fraction *= MINS_PER_HOUR;
2521 minute.result = qulonglong(fraction);
2522 fraction -= minute.result;
2523 }
2524
2525 ParsedInt second{};
2526 if (string.size() > 5) {
2527 if (string[5] == u':' && string.size() == 8)
2528 second = readInt(string.sliced(6, 2));
2529 if (!second.ok() || second.result >= SECS_PER_MIN)
2530 return QTime();
2531 } else if (frac.ok()) {
2532 if (format == Qt::TextDate) // Doesn't allow fraction of minutes
2533 return QTime();
2534 Q_ASSERT(!(fraction < 0.0) && fraction < 1.0);
2535 fraction *= SECS_PER_MIN;
2536 second.result = qulonglong(fraction);
2537 fraction -= second.result;
2538 }
2539
2540 Q_ASSERT(!(fraction < 0.0) && fraction < 1.0);
2541 // Round millis to nearest (unlike minutes and seconds, rounded down):
2542 int msec = frac.ok() ? qRound(MSECS_PER_SEC * fraction) : 0;
2543 // But handle overflow gracefully:
2544 if (msec == MSECS_PER_SEC) {
2545 // If we can (when data were otherwise valid) validly propagate overflow
2546 // into other fields, do so:
2547 if (isMidnight24 || hour.result < 23 || minute.result < 59 || second.result < 59) {
2548 msec = 0;
2549 if (++second.result == SECS_PER_MIN) {
2550 second.result = 0;
2551 if (++minute.result == MINS_PER_HOUR) {
2552 minute.result = 0;
2553 ++hour.result;
2554 // May need to propagate further via isMidnight24, see below
2555 }
2556 }
2557 } else {
2558 // QTime::fromString() or Qt::TextDate: rounding up would cause
2559 // 23:59:59.999... to become invalid; clip to 999 ms instead:
2560 msec = MSECS_PER_SEC - 1;
2561 }
2562 }
2563
2564 // For ISO date format, 24:0:0 means 0:0:0 on the next day:
2565 if (hour.result == 24 && minute.result == 0 && second.result == 0 && msec == 0) {
2566 Q_ASSERT(format != Qt::TextDate); // It clipped hour at 23, above.
2567 if (isMidnight24)
2568 *isMidnight24 = true;
2569 hour.result = 0;
2570 }
2571
2572 return QTime(hour.result, minute.result, second.result, msec);
2573}
2574
2575/*!
2576 \overload
2577 \fn QTime QTime::fromString(const QString &string, Qt::DateFormat format)
2578
2579 Returns the time represented in the \a string as a QTime using the
2580 \a format given, or an invalid time if this is not possible.
2581
2582 \sa toString(), QLocale::toTime()
2583*/
2584
2585/*!
2586 \since 6.0
2587 \overload fromString()
2588*/
2589QTime QTime::fromString(QStringView string, Qt::DateFormat format)
2590{
2591 if (string.isEmpty())
2592 return QTime();
2593
2594 switch (format) {
2595 case Qt::RFC2822Date:
2596 return rfcDateImpl(string).time;
2597 case Qt::ISODate:
2598 case Qt::ISODateWithMs:
2599 case Qt::TextDate:
2600 default:
2601 return fromIsoTimeString(string, format, nullptr);
2602 }
2603}
2604
2605/*!
2606 \overload primary
2607 \fn QTime QTime::fromString(const QString &string, const QString &format)
2608
2609 Returns the QTime represented by the \a string, using the \a
2610 format given, or an invalid time if the string cannot be parsed.
2611
2612 These expressions may be used for the format:
2613
2614 \table
2615 \header \li Expression \li Output
2616 \row \li h
2617 \li The hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
2618 \row \li hh
2619 \li The hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
2620 \row \li H
2621 \li The hour without a leading zero (0 to 23, even with AM/PM display)
2622 \row \li HH
2623 \li The hour with a leading zero (00 to 23, even with AM/PM display)
2624 \row \li m \li The minute without a leading zero (0 to 59)
2625 \row \li mm \li The minute with a leading zero (00 to 59)
2626 \row \li s \li The whole second, without any leading zero (0 to 59)
2627 \row \li ss \li The whole second, with a leading zero where applicable (00 to 59)
2628 \row \li z or zz
2629 \li The fractional part of the second, as would usually follow a
2630 decimal point, without requiring trailing zeroes (0 to 999). Thus
2631 \c{"s.z"} matches the seconds with up to three digits of fractional
2632 part supplying millisecond precision, without needing trailing
2633 zeroes. For example, \c{"s.z"} would recognize either \c{"00.250"}
2634 or \c{"0.25"} as representing a time a quarter second into its
2635 minute.
2636 \row \li zzz
2637 \li Three digit fractional part of the second, to millisecond
2638 precision, including trailing zeroes where applicable (000 to 999).
2639 For example, \c{"ss.zzz"} would reject \c{"0.25"} but recognize
2640 \c{"00.250"} as representing a time a quarter second into its
2641 minute.
2642 \row \li AP, A, ap, a, aP or Ap
2643 \li Either 'AM' indicating a time before 12:00 or 'PM' for later times,
2644 matched case-insensitively.
2645 \endtable
2646
2647 All other input characters will be treated as text. Any non-empty sequence
2648 of characters enclosed in single quotes will also be treated (stripped of
2649 the quotes) as text and not be interpreted as expressions.
2650
2651 \snippet code/src_corelib_time_qdatetime.cpp 6
2652
2653 If the format is not satisfied, an invalid QTime is returned.
2654 Expressions that do not expect leading zeroes to be given (h, m, s
2655 and z) are greedy. This means that they will use two digits (or three, for z) even if
2656 this puts them outside the range of accepted values and leaves too
2657 few digits for other sections. For example, the following string
2658 could have meant 00:07:10, but the m will grab two digits, resulting
2659 in an invalid time:
2660
2661 \snippet code/src_corelib_time_qdatetime.cpp 7
2662
2663 Any field that is not represented in the format will be set to zero.
2664 For example:
2665
2666 \snippet code/src_corelib_time_qdatetime.cpp 8
2667
2668 \note If localized forms of am or pm (the AP, ap, Ap, aP, A or a formats)
2669 are to be recognized, use QLocale::system().toTime().
2670
2671 \note If a format character is repeated more times than the longest
2672 expression in the table above using it, this part of the format will be read
2673 as several expressions with no separator between them; the longest above,
2674 possibly repeated as many times as there are copies of it, ending with a
2675 residue that may be a shorter expression. Thus \c{'HHHHH'} would match
2676 \c{"08088"} or \c{"080808"} and set the hour to 8; if the time string
2677 contained "070809" it would "match" but produce an inconsistent result,
2678 leading to an invalid time.
2679
2680 \sa toString(), QDateTime::fromString(), QDate::fromString(),
2681 QLocale::toTime(), QLocale::toDateTime()
2682*/
2683
2684/*!
2685 \since 6.0
2686 \overload fromString()
2687 \fn QTime QTime::fromString(QStringView string, QStringView format)
2688*/
2689
2690/*!
2691 \since 6.0
2692 \overload fromString()
2693*/
2694QTime QTime::fromString(const QString &string, QStringView format)
2695{
2696 QTime time;
2697#if QT_CONFIG(datetimeparser)
2698 QDateTimeParser dt(QMetaType::QTime, QDateTimeParser::FromString, QCalendar());
2699 dt.setDefaultLocale(QLocale::c());
2700 if (dt.parseFormat(format))
2701 dt.fromString(string, nullptr, &time);
2702#else
2703 Q_UNUSED(string);
2704 Q_UNUSED(format);
2705#endif
2706 return time;
2707}
2708#endif // datestring
2709
2710
2711/*!
2712 \overload isValid()
2713
2714 Returns \c true if the specified time is valid; otherwise returns
2715 false.
2716
2717 The time is valid if \a h is in the range 0 to 23, \a m and
2718 \a s are in the range 0 to 59, and \a ms is in the range 0 to 999.
2719
2720 Example:
2721
2722 \snippet code/src_corelib_time_qdatetime.cpp 9
2723*/
2724
2725bool QTime::isValid(int h, int m, int s, int ms)
2726{
2727 return (uint(h) < 24 && uint(m) < MINS_PER_HOUR && uint(s) < SECS_PER_MIN
2728 && uint(ms) < MSECS_PER_SEC);
2729}
2730
2731/*****************************************************************************
2732 QDateTime static helper functions
2733 *****************************************************************************/
2734
2735// get the types from QDateTime (through QDateTimePrivate)
2738
2739// Converts milliseconds since the start of 1970 into a date and/or time:
2740static qint64 msecsToJulianDay(qint64 msecs)
2741{
2742 return JULIAN_DAY_FOR_EPOCH + QRoundingDown::qDiv<MSECS_PER_DAY>(msecs);
2743}
2744
2745static QDate msecsToDate(qint64 msecs)
2746{
2747 return QDate::fromJulianDay(msecsToJulianDay(msecs));
2748}
2749
2750static QTime msecsToTime(qint64 msecs)
2751{
2752 return QTime::fromMSecsSinceStartOfDay(QRoundingDown::qMod<MSECS_PER_DAY>(msecs));
2753}
2754
2755// True if combining days with millis overflows; otherwise, stores result in *sumMillis
2756// The inputs should not have opposite signs.
2757static inline bool daysAndMillisOverflow(qint64 days, qint64 millisInDay, qint64 *sumMillis)
2758{
2759 return qMulOverflow(days, std::integral_constant<qint64, MSECS_PER_DAY>(), sumMillis)
2760 || qAddOverflow(*sumMillis, millisInDay, sumMillis);
2761}
2762
2763// Converts a date/time value into msecs
2764static qint64 timeToMSecs(QDate date, QTime time)
2765{
2766 qint64 days = date.toJulianDay() - JULIAN_DAY_FOR_EPOCH;
2767 qint64 msecs, dayms = time.msecsSinceStartOfDay();
2768 if (days < 0 && dayms > 0) {
2769 ++days;
2770 dayms -= MSECS_PER_DAY;
2771 }
2772 if (daysAndMillisOverflow(days, dayms, &msecs)) {
2773 using Bound = std::numeric_limits<qint64>;
2774 return days < 0 ? Bound::min() : Bound::max();
2775 }
2776 return msecs;
2777}
2778
2779/*!
2780 \internal
2781 Tests whether system functions can handle a given time.
2782
2783 The range of milliseconds for which the time_t-based functions work depends
2784 somewhat on platform (see computeSystemMillisRange() for details). This
2785 function tests whether the UTC time \a millis milliseconds from the epoch is
2786 in the supported range.
2787
2788 To test a local time, pass an upper bound on the magnitude of time-zone
2789 correction potentially needed as \a slack: in this case the range is
2790 extended by this many milliseconds at each end (where applicable). The
2791 function then returns true precisely if \a millis is within this (possibly)
2792 widened range. This doesn't guarantee that the time_t functions can handle
2793 the time, so check their returns to be sure. Values for which the function
2794 returns false should be assumed unrepresentable.
2795*/
2796static inline bool millisInSystemRange(qint64 millis, qint64 slack = 0)
2797{
2798 static const auto bounds = QLocalTime::computeSystemMillisRange();
2799 return (bounds.minClip || millis >= bounds.min - slack)
2800 && (bounds.maxClip || millis <= bounds.max + slack);
2801}
2802
2803/*!
2804 \internal
2805 Returns a year, in the system range, with the same day-of-week pattern
2806
2807 Returns the number of a year, in the range supported by system time_t
2808 functions, that starts and ends on the same days of the week as \a year.
2809 This implies it is a leap year precisely if \a year is. If year is before
2810 the epoch, a year early in the supported range is used; otherwise, one late
2811 in that range. For a leap year, this may be as much as 26 years years from
2812 the range's relevant end; for normal years at most a decade from the end.
2813
2814 This ensures that any DST rules based on, e.g., the last Sunday in a
2815 particular month will select the same date in the returned year as they
2816 would if applied to \a year. Of course, the zone's rules may be different in
2817 \a year than in the selected year, but it's hard to do better.
2818*/
2819static int systemTimeYearMatching(int year)
2820{
2821#if defined(Q_OS_WIN) || defined(Q_OS_WASM)// They don't support times before the epoch
2822 static constexpr int forLeapEarly[] = { 1984, 1996, 1980, 1992, 1976, 1988, 1972 };
2823 static constexpr int regularEarly[] = { 1978, 1973, 1974, 1975, 1970, 1971, 1977 };
2824#else // First year fully in 32-bit time_t range is 1902
2825 static constexpr int forLeapEarly[] = { 1928, 1912, 1924, 1908, 1920, 1904, 1916 };
2826 static constexpr int regularEarly[] = { 1905, 1906, 1907, 1902, 1903, 1909, 1910 };
2827#endif
2828 static constexpr int forLeapLate[] = { 2012, 2024, 2036, 2020, 2032, 2016, 2028 };
2829 static constexpr int regularLate[] = { 2034, 2035, 2030, 2031, 2037, 2027, 2033 };
2830 const int dow = QGregorianCalendar::yearStartWeekDay(year);
2831 Q_ASSERT(dow == QDate(year, 1, 1).dayOfWeek());
2832 const int res = (QGregorianCalendar::leapTest(year)
2833 ? (year < 1970 ? forLeapEarly : forLeapLate)
2834 : (year < 1970 ? regularEarly : regularLate))[dow == 7 ? 0 : dow];
2835 Q_ASSERT(QDate(res, 1, 1).dayOfWeek() == dow);
2836 Q_ASSERT(QDate(res, 12, 31).dayOfWeek() == QDate(year, 12, 31).dayOfWeek());
2837 return res;
2838}
2839
2840// Sets up d and status to represent local time at the given UTC msecs since epoch:
2841QDateTimePrivate::ZoneState QDateTimePrivate::expressUtcAsLocal(qint64 utcMSecs)
2842{
2843 ZoneState result{utcMSecs};
2844 // Within the time_t supported range, localtime() can handle it:
2845 if (millisInSystemRange(utcMSecs)) {
2846 result = QLocalTime::utcToLocal(utcMSecs);
2847 if (result.valid)
2848 return result;
2849 }
2850
2851 // Docs state any LocalTime after 2038-01-18 *will* have any DST applied.
2852 // When this falls outside the supported range, we need to fake it.
2853#if QT_CONFIG(timezone) // Use the system time-zone.
2854 if (const auto sys = QTimeZone::systemTimeZone(); sys.isValid()) {
2855 result.offset = sys.d->offsetFromUtc(utcMSecs);
2856 if (result.offset != QTimeZonePrivate::invalidSeconds()) {
2857 if (qAddOverflow(utcMSecs, result.offset * MSECS_PER_SEC, &result.when))
2858 return result;
2859 result.dst = sys.d->isDaylightTime(utcMSecs) ? DaylightTime : StandardTime;
2860 result.valid = true;
2861 return result;
2862 }
2863 }
2864#endif // timezone
2865
2866 // Kludge
2867 // Do the conversion in a year with the same days of the week, so DST
2868 // dates might be right, and adjust by the number of days that was off:
2869 const qint64 jd = msecsToJulianDay(utcMSecs);
2870 const auto ymd = QGregorianCalendar::partsFromJulian(jd);
2871 qint64 diffMillis, fakeUtc;
2872 const auto fakeJd = QGregorianCalendar::julianFromParts(systemTimeYearMatching(ymd.year),
2873 ymd.month, ymd.day);
2874 if (Q_UNLIKELY(!fakeJd
2875 || qMulOverflow(jd - *fakeJd, std::integral_constant<qint64, MSECS_PER_DAY>(),
2876 &diffMillis)
2877 || qSubOverflow(utcMSecs, diffMillis, &fakeUtc))) {
2878 return result;
2879 }
2880
2881 result = QLocalTime::utcToLocal(fakeUtc);
2882 // Now correct result.when for the use of the fake date:
2883 if (!result.valid || qAddOverflow(result.when, diffMillis, &result.when)) {
2884 // If utcToLocal() failed, its return has the fake when; restore utcMSecs.
2885 // Fail on overflow, but preserve offset and DST-ness.
2886 result.when = utcMSecs;
2887 result.valid = false;
2888 }
2889 return result;
2890}
2891
2892static auto millisToWithinRange(qint64 millis)
2893{
2894 struct R {
2895 qint64 shifted = 0;
2896 bool good = false;
2897 } result;
2898 qint64 jd = msecsToJulianDay(millis);
2899 auto ymd = QGregorianCalendar::partsFromJulian(jd);
2900 const auto fakeJd = QGregorianCalendar::julianFromParts(systemTimeYearMatching(ymd.year),
2901 ymd.month, ymd.day);
2902 result.good = fakeJd && !daysAndMillisOverflow(*fakeJd - jd, millis, &result.shifted);
2903 return result;
2904}
2905
2906/*!
2907 \internal
2908 \enum QDateTimePrivate::TransitionOption
2909
2910 This enumeration is used to resolve datetime combinations which fall in \l
2911 {Timezone transitions}. The transition is described as a "gap" if there are
2912 time representations skipped over by the zone, as is common in the "spring
2913 forward" transitions in many zones on entering daylight-saving time. The
2914 transition is described as a "fold" if there are time representations
2915 repeated in the zone, as in a "fall back" transition out of daylight-saving
2916 time.
2917
2918 When the options specified do not determine a resolution for a datetime, it
2919 is marked invalid.
2920
2921 The prepared option sets above are in fact composed from low-level atomic
2922 options. For each of gap and fold you can chose between two candidate times,
2923 one before or after the transition, based on the time requested; or you can
2924 pick the moment of transition, or the start or end of the transition
2925 interval. For a gap, the start and end of the interval are the moment of the
2926 transition, but for a repeated interval the start of the first pass is the
2927 start of the transition interval, the end of the second pass is the end of
2928 the transition interval and the moment of the transition itself is both the
2929 end of the first pass and the start of the second.
2930
2931 \value GapUseBefore For a time in a gap, use a time before the transition,
2932 as if stepping back from a later time.
2933 \value GapUseAfter For a time in a gap, use a time after the transition, as
2934 if stepping forward from an earlier time.
2935 \value FoldUseBefore For a repeated time, use the first candidate, which is
2936 before the transition.
2937 \value FoldUseAfter For a repeated time, use the second candidate, which is
2938 after the transition.
2939 \value FlipForReverseDst For "reversed" DST, this reverses the preceding
2940 four options (see below).
2941
2942 The last has no effect unless the "daylight-saving" time side of the
2943 transition is known to have a lower offset from UTC than the standard time
2944 side. (This is the "reversed" DST case of \l {Timezone transitions}.) In
2945 that case, if other options would select a time after the transition, a time
2946 before is used instead, and vice versa. This effectively turns a preference
2947 for the side with lower offset into a preference for the side that is
2948 officially standard time, even if it has higher offset; and conversely a
2949 preference for higher offset into a preference for daylight-saving time,
2950 even if it has a lower offset. This option has no effect on a resolution
2951 that selects the moment of transition or the start or end of the transition
2952 interval.
2953
2954 The result of combining more than one of the \c GapUse* options is
2955 undefined; likewise for the \c FoldUse*. Each of QDateTime's
2956 TransitionResolution values, aside from Reject, maps to a combination that
2957 incorporates one from each of these sets.
2958*/
2959
2960constexpr static QDateTimePrivate::TransitionOptions
2961toTransitionOptions(QDateTime::TransitionResolution res)
2962{
2963 switch (res) {
2964 case QDateTime::TransitionResolution::RelativeToBefore:
2965 return QDateTimePrivate::GapUseAfter | QDateTimePrivate::FoldUseBefore;
2966 case QDateTime::TransitionResolution::RelativeToAfter:
2967 return QDateTimePrivate::GapUseBefore | QDateTimePrivate::FoldUseAfter;
2968 case QDateTime::TransitionResolution::PreferBefore:
2969 return QDateTimePrivate::GapUseBefore | QDateTimePrivate::FoldUseBefore;
2970 case QDateTime::TransitionResolution::PreferAfter:
2971 return QDateTimePrivate::GapUseAfter | QDateTimePrivate::FoldUseAfter;
2972 case QDateTime::TransitionResolution::PreferStandard:
2973 return QDateTimePrivate::GapUseBefore
2974 | QDateTimePrivate::FoldUseAfter
2975 | QDateTimePrivate::FlipForReverseDst;
2976 case QDateTime::TransitionResolution::PreferDaylightSaving:
2977 return QDateTimePrivate::GapUseAfter
2978 | QDateTimePrivate::FoldUseBefore
2979 | QDateTimePrivate::FlipForReverseDst;
2980 case QDateTime::TransitionResolution::Reject: break;
2981 }
2982 return {};
2983}
2984
2985constexpr static QDateTimePrivate::TransitionOptions
2986toTransitionOptions(QDateTimePrivate::DaylightStatus dst)
2987{
2988 return toTransitionOptions(dst == QDateTimePrivate::DaylightTime
2989 ? QDateTime::TransitionResolution::PreferDaylightSaving
2990 : QDateTime::TransitionResolution::PreferStandard);
2991}
2992
2993QString QDateTimePrivate::localNameAtMillis(qint64 millis, DaylightStatus dst)
2994{
2995 const QDateTimePrivate::TransitionOptions resolve = toTransitionOptions(dst);
2996 QString abbreviation;
2997 if (millisInSystemRange(millis, MSECS_PER_DAY)) {
2998 abbreviation = QLocalTime::localTimeAbbbreviationAt(millis, resolve);
2999 if (!abbreviation.isEmpty())
3000 return abbreviation;
3001 }
3002
3003 // Otherwise, outside the system range.
3004#if QT_CONFIG(timezone)
3005 // Use the system zone:
3006 const auto sys = QTimeZone::systemTimeZone();
3007 if (sys.isValid()) {
3008 ZoneState state = zoneStateAtMillis(sys, millis, resolve);
3009 if (state.valid)
3010 return sys.d->abbreviation(state.when - state.offset * MSECS_PER_SEC);
3011 }
3012#endif // timezone
3013
3014 // Kludge
3015 // Use a time in the system range with the same day-of-week pattern to its year:
3016 auto fake = millisToWithinRange(millis);
3017 if (Q_LIKELY(fake.good))
3018 return QLocalTime::localTimeAbbbreviationAt(fake.shifted, resolve);
3019
3020 // Overflow, apparently.
3021 return {};
3022}
3023
3024// Determine the offset from UTC at the given local time as millis.
3025QDateTimePrivate::ZoneState QDateTimePrivate::localStateAtMillis(
3026 qint64 millis, QDateTimePrivate::TransitionOptions resolve)
3027{
3028 // First, if millis is within a day of the viable range, try mktime() in
3029 // case it does fall in the range and gets useful information:
3030 if (millisInSystemRange(millis, MSECS_PER_DAY)) {
3031 auto result = QLocalTime::mapLocalTime(millis, resolve);
3032 if (result.valid)
3033 return result;
3034 }
3035
3036 // Otherwise, outside the system range.
3037#if QT_CONFIG(timezone)
3038 // Use the system zone:
3039 const auto sys = QTimeZone::systemTimeZone();
3040 if (sys.isValid())
3041 return zoneStateAtMillis(sys, millis, resolve);
3042#endif // timezone
3043
3044 // Kludge
3045 // Use a time in the system range with the same day-of-week pattern to its year:
3046 auto fake = millisToWithinRange(millis);
3047 if (Q_LIKELY(fake.good)) {
3048 auto result = QLocalTime::mapLocalTime(fake.shifted, resolve);
3049 if (result.valid) {
3050 qint64 adjusted;
3051 if (Q_UNLIKELY(qAddOverflow(result.when, millis - fake.shifted, &adjusted))) {
3052 using Bound = std::numeric_limits<qint64>;
3053 adjusted = millis < fake.shifted ? Bound::min() : Bound::max();
3054 }
3055 result.when = adjusted;
3056 } else {
3057 result.when = millis;
3058 }
3059 return result;
3060 }
3061 // Overflow, apparently.
3062 return {millis};
3063}
3064
3065#if QT_CONFIG(timezone)
3066// For a TimeZone and a time expressed in zone msecs encoding, compute the
3067// actual DST-ness and offset, adjusting the time if needed to escape a
3068// spring-forward.
3069QDateTimePrivate::ZoneState QDateTimePrivate::zoneStateAtMillis(
3070 const QTimeZone &zone, qint64 millis, QDateTimePrivate::TransitionOptions resolve)
3071{
3072 Q_ASSERT(zone.isValid());
3073 Q_ASSERT(zone.timeSpec() == Qt::TimeZone);
3074 return zone.d->stateAtZoneTime(millis, resolve);
3075}
3076#endif // timezone
3077
3078static inline QDateTimePrivate::ZoneState stateAtMillis(const QTimeZone &zone, qint64 millis,
3079 QDateTimePrivate::TransitionOptions resolve)
3080{
3081 if (zone.timeSpec() == Qt::LocalTime)
3082 return QDateTimePrivate::localStateAtMillis(millis, resolve);
3083#if QT_CONFIG(timezone)
3084 if (zone.timeSpec() == Qt::TimeZone && zone.isValid())
3085 return QDateTimePrivate::zoneStateAtMillis(zone, millis, resolve);
3086#endif
3087 return {millis};
3088}
3089
3090static inline bool specCanBeSmall(Qt::TimeSpec spec)
3091{
3092 return spec == Qt::LocalTime || spec == Qt::UTC;
3093}
3094
3095static inline bool msecsCanBeSmall(qint64 msecs)
3096{
3097 if constexpr (!QDateTimeData::CanBeSmall)
3098 return false;
3099
3100 ShortData sd;
3101 sd.msecs = qintptr(msecs);
3102 return sd.msecs == msecs;
3103}
3104
3105static constexpr inline
3106QDateTimePrivate::StatusFlags mergeSpec(QDateTimePrivate::StatusFlags status, Qt::TimeSpec spec)
3107{
3108 status &= ~QDateTimePrivate::TimeSpecMask;
3109 status |= QDateTimePrivate::StatusFlags::fromInt(int(spec) << QDateTimePrivate::TimeSpecShift);
3110 return status;
3111}
3112
3113static constexpr inline Qt::TimeSpec extractSpec(QDateTimePrivate::StatusFlags status)
3114{
3115 return Qt::TimeSpec((status & QDateTimePrivate::TimeSpecMask).toInt() >> QDateTimePrivate::TimeSpecShift);
3116}
3117
3118// Set the Daylight Status if LocalTime set via msecs
3119static constexpr inline QDateTimePrivate::StatusFlags
3120mergeDaylightStatus(QDateTimePrivate::StatusFlags sf, QDateTimePrivate::DaylightStatus status)
3121{
3122 sf &= ~QDateTimePrivate::DaylightMask;
3123 if (status == QDateTimePrivate::DaylightTime) {
3124 sf |= QDateTimePrivate::SetToDaylightTime;
3125 } else if (status == QDateTimePrivate::StandardTime) {
3126 sf |= QDateTimePrivate::SetToStandardTime;
3127 }
3128 return sf;
3129}
3130
3131// Get the DST Status if LocalTime set via msecs
3132static constexpr inline
3133QDateTimePrivate::DaylightStatus extractDaylightStatus(QDateTimePrivate::StatusFlags status)
3134{
3135 if (status.testFlag(QDateTimePrivate::SetToDaylightTime))
3136 return QDateTimePrivate::DaylightTime;
3137 if (status.testFlag(QDateTimePrivate::SetToStandardTime))
3138 return QDateTimePrivate::StandardTime;
3139 return QDateTimePrivate::UnknownDaylightTime;
3140}
3141
3142static inline qint64 getMSecs(const QDateTimeData &d)
3143{
3144 if (d.isShort()) {
3145 // same as, but producing better code
3146 //return d.data.msecs;
3147 return qintptr(d.d) >> 8;
3148 }
3149 return d->m_msecs;
3150}
3151
3153{
3154 if (d.isShort()) {
3155 // same as, but producing better code
3156 //return StatusFlag(d.data.status);
3157 return QDateTimePrivate::StatusFlag(qintptr(d.d) & 0xFF);
3158 }
3159 return d->m_status;
3160}
3161
3162static inline Qt::TimeSpec getSpec(const QDateTimeData &d)
3163{
3164 return extractSpec(getStatus(d));
3165}
3166
3167/* True if we *can cheaply determine* that a and b use the same offset.
3168 If they use different offsets or it would be expensive to find out, false.
3169 Calls to toMSecsSinceEpoch() are expensive, for these purposes.
3170 See QDateTime's comparison operators and areFarEnoughApart().
3171*/
3172static inline bool usesSameOffset(const QDateTimeData &a, const QDateTimeData &b)
3173{
3174 const auto status = getStatus(a);
3175 if (status != getStatus(b))
3176 return false;
3177 // Status includes DST-ness, so we now know they match in it.
3178
3179 switch (extractSpec(status)) {
3180 case Qt::LocalTime:
3181 case Qt::UTC:
3182 return true;
3183
3184 case Qt::TimeZone:
3185 /* TimeZone always determines its offset during construction of the
3186 private data. Even if we're in different zones, what matters is the
3187 offset actually in effect at the specific time. (DST can cause things
3188 with the same time-zone to use different offsets, but we already
3189 checked their DSTs match.) */
3190 case Qt::OffsetFromUTC: // always knows its offset, which is all that matters.
3191 Q_ASSERT(!a.isShort() && !b.isShort());
3192 return a->m_offsetFromUtc == b->m_offsetFromUtc;
3193 }
3194 Q_UNREACHABLE_RETURN(false);
3195}
3196
3197/* Even datetimes with different offset can be ordered by their getMSecs()
3198 provided the difference is bigger than the largest difference in offset we're
3199 prepared to believe in. Technically, it may be possible to construct a zone
3200 with an offset outside the range and get wrong results - but the answer to
3201 someone doing that is that their contrived timezone and its consequences are
3202 their own responsibility.
3203
3204 If two datetimes' millis lie within the offset range of one another, we can't
3205 take any short-cuts, even if they're in the same zone, because there may be a
3206 zone transition between them. (The full 32-hour difference would only arise
3207 before 1845, for one date-time in The Philippines, the other in Alaska.)
3208*/
3209bool areFarEnoughApart(qint64 leftMillis, qint64 rightMillis)
3210{
3211 constexpr quint64 UtcOffsetMillisRange
3212 = quint64(QTimeZone::MaxUtcOffsetSecs - QTimeZone::MinUtcOffsetSecs) * MSECS_PER_SEC;
3213 qint64 gap = 0;
3214 return qSubOverflow(leftMillis, rightMillis, &gap) || QtPrivate::qUnsignedAbs(gap) > UtcOffsetMillisRange;
3215}
3216
3217// Refresh the LocalTime or TimeZone validity and offset
3218static void refreshZonedDateTime(QDateTimeData &d, const QTimeZone &zone,
3219 QDateTimePrivate::TransitionOptions resolve)
3220{
3221 Q_ASSERT(zone.timeSpec() == Qt::TimeZone || zone.timeSpec() == Qt::LocalTime);
3222 auto status = getStatus(d);
3223 Q_ASSERT(extractSpec(status) == zone.timeSpec());
3224 int offsetFromUtc = 0;
3225 /* Callers are:
3226 * QDTP::create(), where d is too new to be shared yet
3227 * reviseTimeZone(), which detach()es if not short before calling this
3228 * checkValidDateTime(), always follows a setDateTime() that detach()ed if not short
3229
3230 So we can assume d is not shared. We only need to detach() if we convert
3231 from short to pimpled to accommodate an oversize msecs, which can only be
3232 needed in the unlikely event we revise it.
3233 */
3234
3235 // If not valid date and time then is invalid
3236 if (!status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime)) {
3237 status.setFlag(QDateTimePrivate::ValidDateTime, false);
3238 } else {
3239 // We have a valid date and time and a Qt::LocalTime or Qt::TimeZone
3240 // that might fall into a "missing" DST transition hour.
3241 qint64 msecs = getMSecs(d);
3242 QDateTimePrivate::ZoneState state = stateAtMillis(zone, msecs, resolve);
3243 Q_ASSERT(!state.valid || (state.offset >= -SECS_PER_DAY && state.offset <= SECS_PER_DAY));
3244 if (state.dst == QDateTimePrivate::UnknownDaylightTime) { // Overflow
3245 status.setFlag(QDateTimePrivate::ValidDateTime, false);
3246 } else if (state.valid) {
3247 status = mergeDaylightStatus(status, state.dst);
3248 offsetFromUtc = state.offset;
3249 status.setFlag(QDateTimePrivate::ValidDateTime, true);
3250 if (Q_UNLIKELY(msecs != state.when)) {
3251 // Update msecs to the resolution:
3252 if (status.testFlag(QDateTimePrivate::ShortData)) {
3253 if (msecsCanBeSmall(state.when)) {
3254 d.data.msecs = qintptr(state.when);
3255 } else {
3256 // Convert to long-form so we can hold the revised msecs:
3257 status.setFlag(QDateTimePrivate::ShortData, false);
3258 d.detach();
3259 }
3260 }
3261 if (!status.testFlag(QDateTimePrivate::ShortData))
3262 d->m_msecs = state.when;
3263 }
3264 } else {
3265 status.setFlag(QDateTimePrivate::ValidDateTime, false);
3266 }
3267 }
3268
3269 if (status.testFlag(QDateTimePrivate::ShortData)) {
3270 d.data.status = status.toInt();
3271 } else {
3272 d->m_status = status;
3273 d->m_offsetFromUtc = offsetFromUtc;
3274 }
3275}
3276
3277// Check the UTC / offsetFromUTC validity
3279{
3280 auto status = getStatus(d);
3281 Q_ASSERT(QTimeZone::isUtcOrFixedOffset(extractSpec(status)));
3282 status.setFlag(QDateTimePrivate::ValidDateTime,
3283 status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime));
3284
3285 if (status.testFlag(QDateTimePrivate::ShortData))
3286 d.data.status = status.toInt();
3287 else
3288 d->m_status = status;
3289}
3290
3291// Clean up and set status after assorted set-up or reworking:
3292static void checkValidDateTime(QDateTimeData &d, QDateTime::TransitionResolution resolve)
3293{
3294 auto spec = extractSpec(getStatus(d));
3295 switch (spec) {
3296 case Qt::OffsetFromUTC:
3297 case Qt::UTC:
3298 // for these, a valid date and a valid time imply a valid QDateTime
3300 break;
3301 case Qt::TimeZone:
3302 case Qt::LocalTime:
3303 // For these, we need to check whether (the zone is valid and) the time
3304 // is valid for the zone. Expensive, but we have no other option.
3305 refreshZonedDateTime(d, d.timeZone(), toTransitionOptions(resolve));
3306 break;
3307 }
3308}
3309
3310static void reviseTimeZone(QDateTimeData &d, const QTimeZone &zone,
3311 QDateTime::TransitionResolution resolve)
3312{
3313 Qt::TimeSpec spec = zone.timeSpec();
3314 auto status = mergeSpec(getStatus(d), spec);
3315 bool reuse = d.isShort();
3316 int offset = 0;
3317
3318 switch (spec) {
3319 case Qt::UTC:
3320 Q_ASSERT(zone.fixedSecondsAheadOfUtc() == 0);
3321 break;
3322 case Qt::OffsetFromUTC:
3323 reuse = false;
3324 offset = zone.fixedSecondsAheadOfUtc();
3325 Q_ASSERT(offset);
3326 break;
3327 case Qt::TimeZone:
3328 reuse = false;
3329 break;
3330 case Qt::LocalTime:
3331 break;
3332 }
3333
3334 status &= ~(QDateTimePrivate::ValidDateTime | QDateTimePrivate::DaylightMask);
3335 if (reuse) {
3336 d.data.status = status.toInt();
3337 } else {
3338 d.detach();
3339 d->m_status = status & ~QDateTimePrivate::ShortData;
3340 d->m_offsetFromUtc = offset;
3341#if QT_CONFIG(timezone)
3342 if (spec == Qt::TimeZone)
3343 d->m_timeZone = zone;
3344#endif // timezone
3345 }
3346
3347 if (QTimeZone::isUtcOrFixedOffset(spec))
3349 else
3350 refreshZonedDateTime(d, zone, toTransitionOptions(resolve));
3351}
3352
3353static void setDateTime(QDateTimeData &d, QDate date, QTime time)
3354{
3355 // If the date is valid and the time is not we set time to 00:00:00
3356 if (!time.isValid() && date.isValid())
3357 time = QTime::fromMSecsSinceStartOfDay(0);
3358
3359 QDateTimePrivate::StatusFlags newStatus = { };
3360
3361 // Set date value and status
3362 qint64 days = 0;
3363 if (date.isValid()) {
3364 days = date.toJulianDay() - JULIAN_DAY_FOR_EPOCH;
3365 newStatus = QDateTimePrivate::ValidDate;
3366 }
3367
3368 // Set time value and status
3369 int ds = 0;
3370 if (time.isValid()) {
3371 ds = time.msecsSinceStartOfDay();
3372 newStatus |= QDateTimePrivate::ValidTime;
3373 }
3374 Q_ASSERT(ds < MSECS_PER_DAY);
3375 // Only the later parts of the very first day are representable - its start
3376 // would overflow - so get ds the same side of 0 as days:
3377 if (days < 0 && ds > 0) {
3378 days++;
3379 ds -= MSECS_PER_DAY;
3380 }
3381
3382 // Check in representable range:
3383 qint64 msecs = 0;
3384 if (daysAndMillisOverflow(days, qint64(ds), &msecs)) {
3385 newStatus = QDateTimePrivate::StatusFlags{};
3386 msecs = 0;
3387 }
3388 if (d.isShort()) {
3389 // let's see if we can keep this short
3390 if (msecsCanBeSmall(msecs)) {
3391 // yes, we can
3392 d.data.msecs = qintptr(msecs);
3393 d.data.status &= ~(QDateTimePrivate::ValidityMask | QDateTimePrivate::DaylightMask).toInt();
3394 d.data.status |= newStatus.toInt();
3395 } else {
3396 // nope...
3397 d.detach();
3398 }
3399 }
3400 if (!d.isShort()) {
3401 d.detach();
3402 d->m_msecs = msecs;
3403 d->m_status &= ~(QDateTimePrivate::ValidityMask | QDateTimePrivate::DaylightMask);
3404 d->m_status |= newStatus;
3405 }
3406}
3407
3408static std::pair<QDate, QTime> getDateTime(const QDateTimeData &d)
3409{
3410 auto status = getStatus(d);
3411 const qint64 msecs = getMSecs(d);
3412 const auto dayMilli = QRoundingDown::qDivMod<MSECS_PER_DAY>(msecs);
3413 return { status.testFlag(QDateTimePrivate::ValidDate)
3414 ? QDate::fromJulianDay(JULIAN_DAY_FOR_EPOCH + dayMilli.quotient)
3415 : QDate(),
3416 status.testFlag(QDateTimePrivate::ValidTime)
3417 ? QTime::fromMSecsSinceStartOfDay(dayMilli.remainder)
3418 : QTime() };
3419}
3420
3421/*****************************************************************************
3422 QDateTime::Data member functions
3423 *****************************************************************************/
3424
3425inline QDateTime::Data::Data() noexcept
3426{
3427 // default-constructed data has a special exception:
3428 // it can be small even if CanBeSmall == false
3429 // (optimization so we don't allocate memory in the default constructor)
3430 quintptr value = mergeSpec(QDateTimePrivate::ShortData, Qt::LocalTime).toInt();
3431 d = reinterpret_cast<QDateTimePrivate *>(value);
3432}
3433
3434inline QDateTime::Data::Data(const QTimeZone &zone)
3435{
3436 Qt::TimeSpec spec = zone.timeSpec();
3437 if (CanBeSmall && Q_LIKELY(specCanBeSmall(spec))) {
3438 quintptr value = mergeSpec(QDateTimePrivate::ShortData, spec).toInt();
3439 d = reinterpret_cast<QDateTimePrivate *>(value);
3440 Q_ASSERT(isShort());
3441 } else {
3442 // the structure is too small, we need to detach
3443 d = new QDateTimePrivate;
3444 d->ref.ref();
3445 d->m_status = mergeSpec({}, spec);
3446 if (spec == Qt::OffsetFromUTC)
3447 d->m_offsetFromUtc = zone.fixedSecondsAheadOfUtc();
3448 else if (spec == Qt::TimeZone)
3449 d->m_timeZone = zone;
3450 Q_ASSERT(!isShort());
3451 }
3452}
3453
3454inline QDateTime::Data::Data(const Data &other) noexcept
3455 : data(other.data)
3456{
3457 if (!isShort()) {
3458 // check if we could shrink
3459 if (specCanBeSmall(extractSpec(d->m_status)) && msecsCanBeSmall(d->m_msecs)) {
3460 ShortData sd;
3461 sd.msecs = qintptr(d->m_msecs);
3462 sd.status = (d->m_status | QDateTimePrivate::ShortData).toInt();
3463 data = sd;
3464 } else {
3465 // no, have to keep it big
3466 d->ref.ref();
3467 }
3468 }
3469}
3470
3471inline QDateTime::Data::Data(Data &&other) noexcept
3472 : data(other.data)
3473{
3474 // reset the other to a short state
3475 Data dummy;
3476 Q_ASSERT(dummy.isShort());
3477 other.data = dummy.data;
3478}
3479
3480inline QDateTime::Data &QDateTime::Data::operator=(const Data &other) noexcept
3481{
3482 if (isShort() ? data == other.data : d == other.d)
3483 return *this;
3484
3485 auto x = d;
3486 d = other.d;
3487 if (!other.isShort()) {
3488 // check if we could shrink
3489 if (specCanBeSmall(extractSpec(other.d->m_status)) && msecsCanBeSmall(other.d->m_msecs)) {
3490 ShortData sd;
3491 sd.msecs = qintptr(other.d->m_msecs);
3492 sd.status = (other.d->m_status | QDateTimePrivate::ShortData).toInt();
3493 data = sd;
3494 } else {
3495 // no, have to keep it big
3496 other.d->ref.ref();
3497 }
3498 }
3499
3500 if (!(quintptr(x) & QDateTimePrivate::ShortData) && !x->ref.deref())
3501 delete x;
3502 return *this;
3503}
3504
3505inline QDateTime::Data::~Data()
3506{
3507 if (!isShort() && !d->ref.deref())
3508 delete d;
3509}
3510
3511inline bool QDateTime::Data::isShort() const
3512{
3513 bool b = quintptr(d) & QDateTimePrivate::ShortData;
3514
3515 // sanity check:
3516 Q_ASSERT(b || !d->m_status.testFlag(QDateTimePrivate::ShortData));
3517
3518 // even if CanBeSmall = false, we have short data for a default-constructed
3519 // QDateTime object. But it's unlikely.
3520 if constexpr (CanBeSmall)
3521 return Q_LIKELY(b);
3522 return Q_UNLIKELY(b);
3523}
3524
3525inline void QDateTime::Data::detach()
3526{
3527 QDateTimePrivate *x;
3528 bool wasShort = isShort();
3529 if (wasShort) {
3530 // force enlarging
3531 x = new QDateTimePrivate;
3532 x->m_status = QDateTimePrivate::StatusFlags::fromInt(data.status) & ~QDateTimePrivate::ShortData;
3533 x->m_msecs = data.msecs;
3534 } else {
3535 if (d->ref.loadRelaxed() == 1)
3536 return;
3537
3538 x = new QDateTimePrivate(*d);
3539 }
3540
3541 x->ref.storeRelaxed(1);
3542 if (!wasShort && !d->ref.deref())
3543 delete d;
3544 d = x;
3545}
3546
3547void QDateTime::Data::invalidate()
3548{
3549 if (isShort()) {
3550 data.status &= ~int(QDateTimePrivate::ValidityMask);
3551 } else {
3552 detach();
3553 d->m_status &= ~QDateTimePrivate::ValidityMask;
3554 }
3555}
3556
3557QTimeZone QDateTime::Data::timeZone() const
3558{
3559 switch (getSpec(*this)) {
3560 case Qt::UTC:
3561 return QTimeZone::UTC;
3562 case Qt::OffsetFromUTC:
3563 return QTimeZone::fromSecondsAheadOfUtc(d->m_offsetFromUtc);
3564 case Qt::TimeZone:
3565#if QT_CONFIG(timezone)
3566 if (d->m_timeZone.isValid())
3567 return d->m_timeZone;
3568#endif
3569 break;
3570 case Qt::LocalTime:
3571 return QTimeZone::LocalTime;
3572 }
3573 return QTimeZone();
3574}
3575
3576inline const QDateTimePrivate *QDateTime::Data::operator->() const
3577{
3578 Q_ASSERT(!isShort());
3579 return d;
3580}
3581
3582inline QDateTimePrivate *QDateTime::Data::operator->()
3583{
3584 // should we attempt to detach here?
3585 Q_ASSERT(!isShort());
3586 Q_ASSERT(d->ref.loadRelaxed() == 1);
3587 return d;
3588}
3589
3590/*****************************************************************************
3591 QDateTimePrivate member functions
3592 *****************************************************************************/
3593
3594Q_NEVER_INLINE
3595QDateTime::Data QDateTimePrivate::create(QDate toDate, QTime toTime, const QTimeZone &zone,
3596 QDateTime::TransitionResolution resolve)
3597{
3598 QDateTime::Data result(zone);
3599 setDateTime(result, toDate, toTime);
3600 if (zone.isUtcOrFixedOffset())
3601 refreshSimpleDateTime(result);
3602 else
3603 refreshZonedDateTime(result, zone, toTransitionOptions(resolve));
3604 return result;
3605}
3606
3607/*****************************************************************************
3608 QDateTime member functions
3609 *****************************************************************************/
3610
3611/*!
3612 \class QDateTime
3613 \inmodule QtCore
3614 \ingroup shared
3615 \reentrant
3616 \brief The QDateTime class provides date and time functions.
3617
3618 \compares weak
3619
3620 A QDateTime object encodes a calendar date and a clock time (a "datetime")
3621 in accordance with a time representation. It combines features of the QDate
3622 and QTime classes. It can read the current datetime from the system
3623 clock. It provides functions for comparing datetimes and for manipulating a
3624 datetime by adding a number of seconds, days, months, or years.
3625
3626 QDateTime can describe datetimes with respect to \l{Qt::LocalTime}{local
3627 time}, to \l{Qt::UTC}{UTC}, to a specified \l{Qt::OffsetFromUTC}{offset from
3628 UTC} or to a specified \l{Qt::TimeZone}{time zone}. Each of these time
3629 representations can be encapsulated in a suitable instance of the QTimeZone
3630 class. For example, a time zone of "Europe/Berlin" will apply the
3631 daylight-saving rules as used in Germany. In contrast, a fixed offset from
3632 UTC of +3600 seconds is one hour ahead of UTC (usually written in ISO
3633 standard notation as "UTC+01:00"), with no daylight-saving
3634 complications. When using either local time or a specified time zone,
3635 time-zone transitions (see \l {Timezone transitions}{below}) are taken into
3636 account. A QDateTime's timeSpec() will tell you which of the four types of
3637 time representation is in use; its timeRepresentation() provides a full
3638 description of that time representation, as a QTimeZone.
3639
3640 A QDateTime object is typically created either by giving a date and time
3641 explicitly in the constructor, or by using a static function such as
3642 currentDateTime() or fromMSecsSinceEpoch(). The date and time can be changed
3643 with setDate() and setTime(). A datetime can also be set using the
3644 setMSecsSinceEpoch() function that takes the time, in milliseconds, since
3645 the start, in UTC, of the year 1970. The fromString() function returns a
3646 QDateTime, given a string and a date format used to interpret the date
3647 within the string.
3648
3649 QDateTime::currentDateTime() returns a QDateTime that expresses the current
3650 date and time with respect to a specific time representation, such as local
3651 time (its default). QDateTime::currentDateTimeUtc() returns a QDateTime that
3652 expresses the current date and time with respect to UTC; it is equivalent to
3653 \c {QDateTime::currentDateTime(QTimeZone::UTC)}.
3654
3655 The date() and time() functions provide access to the date and
3656 time parts of the datetime. The same information is provided in
3657 textual format by the toString() function.
3658
3659 QDateTime provides a full set of operators to compare two
3660 QDateTime objects, where smaller means earlier and larger means
3661 later.
3662
3663 You can increment (or decrement) a datetime by a given number of
3664 milliseconds using addMSecs(), seconds using addSecs(), or days using
3665 addDays(). Similarly, you can use addMonths() and addYears(). The daysTo()
3666 function returns the number of days between two datetimes, secsTo() returns
3667 the number of seconds between two datetimes, and msecsTo() returns the
3668 number of milliseconds between two datetimes. These operations are aware of
3669 daylight-saving time (DST) and other time-zone transitions, where
3670 applicable.
3671
3672 Use toTimeZone() to re-express a datetime in terms of a different time
3673 representation. By passing a lightweight QTimeZone that represents local
3674 time, UTC or a fixed offset from UTC, you can convert the datetime to use
3675 the corresponding time representation; or you can pass a full time zone
3676 (whose \l {QTimeZone::timeSpec()}{timeSpec()} is \c {Qt::TimeZone}) to use
3677 that instead.
3678
3679 \section1 Remarks
3680
3681 QDateTime does not account for leap seconds.
3682
3683 All conversions to and from string formats are done using the C locale.
3684 For localized conversions, see QLocale.
3685
3686 There is no year 0 in the Gregorian calendar. Dates in that year are
3687 considered invalid. The year -1 is the year "1 before Christ" or "1 before
3688 common era." The day before 1 January 1 CE is 31 December 1 BCE.
3689
3690 Using local time (the default) or a specified time zone implies a need
3691 to resolve any issues around \l {Timezone transitions}{transitions}. As a
3692 result, operations on such QDateTime instances (notably including
3693 constructing them) may be more expensive than the equivalent when using UTC
3694 or a fixed offset from it.
3695
3696 \section2 Range of Valid Dates
3697
3698 The range of values that QDateTime can represent is dependent on the
3699 internal storage implementation. QDateTime is currently stored in a qint64
3700 as a serial msecs value encoding the date and time. This restricts the date
3701 range to about ±292 million years, compared to the QDate range of ±2 billion
3702 years. Care must be taken when creating a QDateTime with extreme values that
3703 you do not overflow the storage. The exact range of supported values varies
3704 depending on the time representation used.
3705
3706 \section2 Use of Timezones
3707
3708 QDateTime uses the system's time zone information to determine the current
3709 local time zone and its offset from UTC. If the system is not configured
3710 correctly or not up-to-date, QDateTime will give wrong results.
3711
3712 QDateTime likewise uses system-provided information to determine the offsets
3713 of other timezones from UTC. If this information is incomplete or out of
3714 date, QDateTime will give wrong results. See the QTimeZone documentation for
3715 more details.
3716
3717 On modern Unix systems, this means QDateTime usually has accurate
3718 information about historical transitions (including DST, see below) whenever
3719 possible. On Windows, where the system doesn't support historical timezone
3720 data, historical accuracy is not maintained with respect to timezone
3721 transitions, notably including DST. However, building Qt with the ICU
3722 library will equip QTimeZone with the same timezone database as is used on
3723 Unix.
3724
3725 \section2 Timezone transitions
3726
3727 QDateTime takes into account timezone transitions, both the transitions
3728 between Standard Time and Daylight-Saving Time (DST) and the transitions
3729 that arise when a zone changes its standard offset. For example, if the
3730 transition is at 2am and the clock goes forward to 3am, then there is a
3731 "missing" hour from 02:00:00 to 02:59:59.999. Such a transition is known as
3732 a "spring forward" and the times skipped over have no meaning. When a
3733 transition goes the other way, known as a "fall back", a time interval is
3734 repeated, first in the old zone (usually DST), then in the new zone (usually
3735 Standard Time), so times in this interval are ambiguous.
3736
3737 Some zones use "reversed" DST, using standard time in summer and
3738 daylight-saving time (with a lowered offset) in winter. For such zones, the
3739 spring forward still happens in spring and skips an hour, but is a
3740 transition \e{out of} daylight-saving time, while the fall back still
3741 repeats an autumn hour but is a transition \e to daylight-saving time.
3742
3743 When converting from a UTC time (or a time at fixed offset from UTC), there
3744 is always an unambiguous valid result in any timezone. However, when
3745 combining a date and time to make a datetime, expressed with respect to
3746 local time or a specific time-zone, the nominal result may fall in a
3747 transition, making it either invalid or ambiguous. Methods where this
3748 situation may arise take a \c resolve parameter: this is always ignored if
3749 the requested datetime is valid and unambiguous. See \l TransitionResolution
3750 for the options it lets you control. Prior to Qt 6.7, the equivalent of its
3751 \l LegacyBehavior was selected.
3752
3753 For a spring forward's skipped interval, interpreting the requested time
3754 with either offset yields an actual time at which the other offset was in
3755 use; so passing \c TransitionResolution::RelativeToBefore for \c resolve
3756 will actually result in a time after the transition, that would have had the
3757 requested representation had the transition not happened. Likewise, \c
3758 TransitionResolution::RelativeToAfter for \c resolve results in a time
3759 before the transition, that would have had the requested representation, had
3760 the transition happened earlier.
3761
3762 When QDateTime performs arithmetic, as with addDay() or addSecs(), it takes
3763 care to produce a valid result. For example, on a day when there is a spring
3764 forward from 02:00 to 03:00, adding one second to 01:59:59 will get
3765 03:00:00. Adding one day to 02:30 on the preceding day will get 03:30 on the
3766 day of the transition, while subtracting one day, by calling \c{addDay(-1)},
3767 to 02:30 on the following day will get 01:30 on the day of the transition.
3768 While addSecs() will deliver a time offset by the given number of seconds,
3769 addDays() adjusts the date and only adjusts time if it would otherwise get
3770 an invalid result. Applying \c{addDays(1)} to 03:00 on the day before the
3771 spring-forward will simply get 03:00 on the day of the transition, even
3772 though the latter is only 23 hours after the former; but \c{addSecs(24 * 60
3773 * 60)} will get 04:00 on the day of the transition, since that's 24 hours
3774 later. Typical transitions make some days 23 or 25 hours long.
3775
3776 For datetimes that the system \c time_t can represent (from 1901-12-14 to
3777 2038-01-18 on systems with 32-bit \c time_t; for the full range QDateTime
3778 can represent if the type is 64-bit), the standard system APIs are used to
3779 determine local time's offset from UTC. For datetimes not handled by these
3780 system APIs (potentially including some within the \c time_t range),
3781 QTimeZone::systemTimeZone() is used, if available, or a best effort is made
3782 to estimate. In any case, the offset information used depends on the system
3783 and may be incomplete or, for past times, historically
3784 inaccurate. Furthermore, for future dates, the local time zone's offsets and
3785 DST rules may change before that date comes around.
3786
3787 \section3 Whole day transitions
3788
3789 A small number of zones have skipped or repeated entire days as part of
3790 moving The International Date Line across themselves. For these, daysTo()
3791 will be unaware of the duplication or gap, simply using the difference in
3792 calendar date; in contrast, msecsTo() and secsTo() know the true time
3793 interval. Likewise, addMSecs() and addSecs() correspond directly to elapsed
3794 time, where addDays(), addMonths() and addYears() follow the nominal
3795 calendar, aside from where landing in a gap or duplication requires
3796 resolving an ambiguity or invalidity due to a duplication or omission.
3797
3798 \note Days "lost" during a change of calendar, such as from Julian to
3799 Gregorian, do not affect QDateTime. Although the two calendars describe
3800 dates differently, the successive days across the change are described by
3801 consecutive QDate instances, each one day later than the previous, as
3802 described by either calendar or by their toJulianDay() values. In contrast,
3803 a zone skipping or duplicating a day is changing its description of \e time,
3804 not date, for all that it does so by a whole 24 hours.
3805
3806 \section2 Offsets From UTC
3807
3808 Offsets from UTC are measured in seconds east of Greenwich. The moment
3809 described by a particular date and time, such as noon on a particular day,
3810 depends on the time representation used. Those with a higher offset from UTC
3811 describe an earlier moment, and those with a lower offset a later moment, by
3812 any given combination of date and time.
3813
3814 There is no explicit size restriction on an offset from UTC, but there is an
3815 implicit limit imposed when using the toString() and fromString() methods
3816 which use a ±hh:mm format, effectively limiting the range to ± 99 hours and
3817 59 minutes and whole minutes only. Note that currently no time zone has an
3818 offset outside the range of ±14 hours and all known offsets are multiples of
3819 five minutes. Historical time zones have a wider range and may have offsets
3820 including seconds; these last cannot be faithfully represented in strings.
3821
3822 \sa QDate, QTime, QDateTimeEdit, QTimeZone
3823*/
3824
3825/*!
3826 \since 5.14
3827 \enum QDateTime::YearRange
3828
3829 This enumerated type describes the range of years (in the Gregorian
3830 calendar) representable by QDateTime:
3831
3832 \value First The later parts of this year are representable
3833 \value Last The earlier parts of this year are representable
3834
3835 All dates strictly between these two years are also representable.
3836 Note, however, that the Gregorian Calendar has no year zero.
3837
3838 \note QDate can describe dates in a wider range of years. For most
3839 purposes, this makes little difference, as the range of years that QDateTime
3840 can support reaches 292 million years either side of 1970.
3841
3842 \sa isValid(), QDate
3843*/
3844
3845/*!
3846 \since 6.7
3847 \enum QDateTime::TransitionResolution
3848
3849 This enumeration is used to resolve datetime combinations which fall in \l
3850 {Timezone transitions}.
3851
3852 When constructing a datetime, specified in terms of local time or a
3853 time-zone that has daylight-saving time, or revising one with setDate(),
3854 setTime() or setTimeZone(), the given parameters may imply a time
3855 representation that either has no meaning or has two meanings in the
3856 zone. Such time representations are described as being in the transition. In
3857 either case, we can simply return an invalid datetime, to indicate that the
3858 operation is ill-defined. In the ambiguous case, we can alternatively select
3859 one of the two times that could be meant. When there is no meaning, we can
3860 select a time either side of it that might plausibly have been meant. For
3861 example, when advancing from an earlier time, we can select the time after
3862 the transition that is actually the specified amount of time after the
3863 earlier time in question. The options specified here configure how such
3864 selection is performed.
3865
3866 \value Reject
3867 Treat any time in a transition as invalid. Either it really is, or it
3868 is ambiguous.
3869 \value RelativeToBefore
3870 Selects a time as if stepping forward from a time before the
3871 transition. This interprets the requested time using the offset in
3872 effect before the transition and, if necessary, converts the result
3873 to the offset in effect at the resulting time.
3874 \value RelativeToAfter
3875 Select a time as if stepping backward from a time after the
3876 transition. This interprets the requested time using the offset in
3877 effect after the transition and, if necessary, converts the result to
3878 the offset in effect at the resulting time.
3879 \value PreferBefore
3880 Selects a time before the transition,
3881 \value PreferAfter
3882 Selects a time after the transition.
3883 \value PreferStandard
3884 Selects a time on the standard time side of the transition.
3885 \value PreferDaylightSaving
3886 Selects a time on the daylight-saving-time side of the transition.
3887 \omitvalue LegacyBehavior
3888
3889 An additional constant, \c LegacyBehavior, is used as a default value for
3890 TransitionResolution parameters in some constructors and setter functions.
3891 This is an alias for \c RelativeToBefore, which implements behavior that
3892 most closely matches the behavior of QDateTime prior to Qt 6.7.
3893
3894 For \l addDays(), \l addMonths() or \l addYears(), the behavior is and
3895 (mostly) was to use \c RelativeToBefore if adding a positive adjustment and \c
3896 RelativeToAfter if adding a negative adjustment.
3897
3898 \note In time zones where daylight-saving increases the offset from UTC in
3899 summer (known as "positive DST"), PreferStandard is an alias for
3900 RelativeToAfter and PreferDaylightSaving for RelativeToBefore. In time zones
3901 where the daylight-saving mechanism is a decrease in offset from UTC in
3902 winter (known as "negative DST"), the reverse applies, provided the
3903 operating system reports - as it does on most platforms - whether a datetime
3904 is in DST or standard time. For some platforms, where transition details are
3905 unavailable even for Qt::TimeZone datetimes, QTimeZone is obliged to presume
3906 that the side with lower offset from UTC is standard time, effectively
3907 assuming positive DST.
3908
3909 The following tables illustrate how a QDateTime constructor resolves a
3910 request for 02:30 on a day when local time has a transition between 02:00
3911 and 03:00, with a nominal standard time LST and daylight-saving time LDT on
3912 the two sides, in the various possible cases. The transition type may be to
3913 skip an hour or repeat it. The type of transition and value of a parameter
3914 \c resolve determine which actual time on the given date is selected. First,
3915 the common case of positive daylight-saving, where:
3916
3917 \table
3918 \header \li Before \li 02:00--03:00 \li After \li \c resolve \li selected
3919 \row \li LST \li skip \li LDT \li RelativeToBefore \li 03:30 LDT
3920 \row \li LST \li skip \li LDT \li RelativeToAfter \li 01:30 LST
3921 \row \li LST \li skip \li LDT \li PreferBefore \li 01:30 LST
3922 \row \li LST \li skip \li LDT \li PreferAfter \li 03:30 LDT
3923 \row \li LST \li skip \li LDT \li PreferStandard \li 01:30 LST
3924 \row \li LST \li skip \li LDT \li PreferDaylightSaving \li 03:30 LDT
3925 \row \li LDT \li repeat \li LST \li RelativeToBefore \li 02:30 LDT
3926 \row \li LDT \li repeat \li LST \li RelativeToAfter \li 02:30 LST
3927 \row \li LDT \li repeat \li LST \li PreferBefore \li 02:30 LDT
3928 \row \li LDT \li repeat \li LST \li PreferAfter \li 02:30 LST
3929 \row \li LDT \li repeat \li LST \li PreferStandard \li 02:30 LST
3930 \row \li LDT \li repeat \li LST \li PreferDaylightSaving \li 02:30 LDT
3931 \endtable
3932
3933 Second, the case for negative daylight-saving, using LDT in winter and
3934 skipping an hour to transition to LST in summer, then repeating an hour at
3935 the transition back to winter:
3936
3937 \table
3938 \row \li LDT \li skip \li LST \li RelativeToBefore \li 03:30 LST
3939 \row \li LDT \li skip \li LST \li RelativeToAfter \li 01:30 LDT
3940 \row \li LDT \li skip \li LST \li PreferBefore \li 01:30 LDT
3941 \row \li LDT \li skip \li LST \li PreferAfter \li 03:30 LST
3942 \row \li LDT \li skip \li LST \li PreferStandard \li 03:30 LST
3943 \row \li LDT \li skip \li LST \li PreferDaylightSaving \li 01:30 LDT
3944 \row \li LST \li repeat \li LDT \li RelativeToBefore \li 02:30 LST
3945 \row \li LST \li repeat \li LDT \li RelativeToAfter \li 02:30 LDT
3946 \row \li LST \li repeat \li LDT \li PreferBefore \li 02:30 LST
3947 \row \li LST \li repeat \li LDT \li PreferAfter \li 02:30 LDT
3948 \row \li LST \li repeat \li LDT \li PreferStandard \li 02:30 LST
3949 \row \li LST \li repeat \li LDT \li PreferDaylightSaving \li 02:30 LDT
3950 \endtable
3951
3952 Reject can be used to prompt relevant QDateTime APIs to return an invalid
3953 datetime object so that your code can deal with transitions for itself, for
3954 example by alerting a user to the fact that the datetime they have selected
3955 is in a transition interval, to offer them the opportunity to resolve a
3956 conflict or ambiguity. Code using this may well find the other options above
3957 useful to determine relevant information to use in its own (or the user's)
3958 resolution. If the start or end of the transition, or the moment of the
3959 transition itself, is the right resolution, QTimeZone's transition APIs can
3960 be used to obtain that information. You can determine whether the transition
3961 is a repeated or skipped interval by using \l secsTo() to measure the actual
3962 time between noon on the previous and following days. The result will be
3963 less than 48 hours for a skipped interval (such as a spring-forward) and
3964 more than 48 hours for a repeated interval (such as a fall-back).
3965
3966 \note When a resolution other than Reject is specified, a valid QDateTime
3967 object is returned, if possible. If the requested date-time falls in a gap,
3968 the returned date-time will not have the time() requested - or, in some
3969 cases, the date(), if a whole day was skipped. You can thus detect when a
3970 gap is hit by comparing date() and time() to what was requested.
3971
3972 \section2 Relation to other datetime software
3973
3974 The Python programming language's datetime APIs have a \c fold parameter
3975 that corresponds to \c RelativeToBefore (\c{fold = True}) and \c
3976 RelativeToAfter (\c{fold = False}).
3977
3978 The \c Temporal proposal to replace JavaScript's \c Date offers four options
3979 for how to resolve a transition, as value for a \c disambiguation
3980 parameter. Its \c{'reject'} raises an exception, which roughly corresponds
3981 to \c Reject producing an invalid result. Its \c{'earlier'} and \c{'later'}
3982 options correspond to \c PreferBefore and \c PreferAfter. Its
3983 \c{'compatible'} option corresponds to \c RelativeToBefore (and Python's
3984 \c{fold = True}).
3985
3986 \sa {Timezone transitions}
3987*/
3988
3989/*!
3990 Constructs a null datetime, nominally using local time.
3991
3992 A null datetime is invalid, since its date and time are invalid.
3993
3994 \sa isValid(), setMSecsSinceEpoch(), setDate(), setTime(), setTimeZone()
3995*/
3996QDateTime::QDateTime() noexcept
3997{
3998#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) || QT_POINTER_SIZE == 8
3999 static_assert(sizeof(ShortData) == sizeof(qint64));
4000 static_assert(sizeof(Data) == sizeof(qint64));
4001#endif
4002 static_assert(sizeof(ShortData) >= sizeof(void*), "oops, Data::swap() is broken!");
4003}
4004
4005#if QT_DEPRECATED_SINCE(6, 9)
4006/*!
4007 \deprecated [6.9] Use \c{QDateTime(date, time)} or \c{QDateTime(date, time, QTimeZone::fromSecondsAheadOfUtc(offsetSeconds))}.
4008
4009 Constructs a datetime with the given \a date and \a time, using the time
4010 representation implied by \a spec and \a offsetSeconds seconds.
4011
4012 If \a date is valid and \a time is not, the time will be set to midnight.
4013
4014 If \a spec is not Qt::OffsetFromUTC then \a offsetSeconds will be
4015 ignored. If \a spec is Qt::OffsetFromUTC and \a offsetSeconds is 0 then the
4016 timeSpec() will be set to Qt::UTC, i.e. an offset of 0 seconds.
4017
4018 If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
4019 i.e. the current system time zone. To create a Qt::TimeZone datetime
4020 use the correct constructor.
4021
4022 If \a date lies outside the range of dates representable by QDateTime, the
4023 result is invalid. If \a spec is Qt::LocalTime and the system's time-zone
4024 skipped over the given date and time, the result is invalid.
4025*/
4026QDateTime::QDateTime(QDate date, QTime time, Qt::TimeSpec spec, int offsetSeconds)
4027 : d(QDateTimePrivate::create(date, time, asTimeZone(spec, offsetSeconds, "QDateTime"),
4028 TransitionResolution::LegacyBehavior))
4029{
4030}
4031#endif // 6.9 deprecation
4032
4033/*!
4034 \since 5.2
4035 \overload primary
4036
4037 Constructs a datetime with the given \a date and \a time, using the time
4038 representation described by \a timeZone.
4039
4040 If \a date is valid and \a time is not, the time will be set to midnight.
4041 If \a timeZone is invalid then the datetime will be invalid. If \a date and
4042 \a time describe a moment close to a transition for \a timeZone, \a resolve
4043 controls how that situation is resolved.
4044
4045//! [pre-resolve-note]
4046 \note Prior to Qt 6.7, the version of this function lacked the \a resolve
4047 parameter so had no way to resolve the ambiguities related to transitions.
4048//! [pre-resolve-note]
4049*/
4050
4051QDateTime::QDateTime(QDate date, QTime time, const QTimeZone &timeZone, TransitionResolution resolve)
4052 : d(QDateTimePrivate::create(date, time, timeZone, resolve))
4053{
4054}
4055
4056/*!
4057 \since 6.5
4058 \overload
4059
4060 Constructs a datetime with the given \a date and \a time, using local time.
4061
4062 If \a date is valid and \a time is not, midnight will be used as the
4063 time. If \a date and \a time describe a moment close to a transition for
4064 local time, \a resolve controls how that situation is resolved.
4065
4066 \include qdatetime.cpp pre-resolve-note
4067*/
4068
4069QDateTime::QDateTime(QDate date, QTime time, TransitionResolution resolve)
4070 : d(QDateTimePrivate::create(date, time, QTimeZone::LocalTime, resolve))
4071{
4072}
4073
4074/*!
4075 Constructs a copy of the \a other datetime.
4076*/
4077QDateTime::QDateTime(const QDateTime &other) noexcept
4078 : d(other.d)
4079{
4080}
4081
4082/*!
4083 \since 5.8
4084 Moves the content of the temporary \a other datetime to this object and
4085 leaves \a other in an unspecified (but proper) state.
4086*/
4087QDateTime::QDateTime(QDateTime &&other) noexcept
4088 : d(std::move(other.d))
4089{
4090}
4091
4092/*!
4093 Destroys the datetime.
4094*/
4095QDateTime::~QDateTime()
4096{
4097}
4098
4099/*!
4100 Copies the \a other datetime into this and returns this copy.
4101*/
4102
4103QDateTime &QDateTime::operator=(const QDateTime &other) noexcept
4104{
4105 d = other.d;
4106 return *this;
4107}
4108/*!
4109 \fn void QDateTime::swap(QDateTime &other)
4110 \since 5.0
4111 \memberswap{datetime}
4112*/
4113
4114/*!
4115 Returns \c true if both the date and the time are null; otherwise
4116 returns \c false. A null datetime is invalid.
4117
4118 \sa QDate::isNull(), QTime::isNull(), isValid()
4119*/
4120
4121bool QDateTime::isNull() const
4122{
4123 // If date or time is invalid, we don't set datetime valid.
4124 return !getStatus(d).testAnyFlag(QDateTimePrivate::ValidityMask);
4125}
4126
4127/*!
4128 Returns \c true if this datetime represents a definite moment, otherwise \c false.
4129
4130 A datetime is valid if both its date and its time are valid and the time
4131 representation used gives a valid meaning to their combination. When the
4132 time representation is a specific time-zone or local time, there may be
4133 times on some dates that the zone skips in its representation, as when a
4134 daylight-saving transition skips an hour (typically during a night in
4135 spring). For example, if DST ends at 2am with the clock advancing to 3am,
4136 then datetimes from 02:00:00 to 02:59:59.999 on that day are invalid.
4137
4138 \sa QDateTime::YearRange, QDate::isValid(), QTime::isValid()
4139*/
4140
4141bool QDateTime::isValid() const
4142{
4143 return getStatus(d).testFlag(QDateTimePrivate::ValidDateTime);
4144}
4145
4146/*!
4147 Returns the date part of the datetime.
4148
4149 \sa setDate(), time(), timeRepresentation()
4150*/
4151
4152QDate QDateTime::date() const
4153{
4154 return getStatus(d).testFlag(QDateTimePrivate::ValidDate) ? msecsToDate(getMSecs(d)) : QDate();
4155}
4156
4157/*!
4158 Returns the time part of the datetime.
4159
4160 \sa setTime(), date(), timeRepresentation()
4161*/
4162
4163QTime QDateTime::time() const
4164{
4165 return getStatus(d).testFlag(QDateTimePrivate::ValidTime) ? msecsToTime(getMSecs(d)) : QTime();
4166}
4167
4168/*!
4169 Returns the time specification of the datetime.
4170
4171 This classifies its time representation as local time, UTC, a fixed offset
4172 from UTC (without indicating the offset) or a time zone (without giving the
4173 details of that time zone). Equivalent to
4174 \c{timeRepresentation().timeSpec()}.
4175
4176 \sa setTimeZone(), timeRepresentation(), date(), time()
4177*/
4178
4179Qt::TimeSpec QDateTime::timeSpec() const
4180{
4181 return getSpec(d);
4182}
4183
4184/*!
4185 \since 6.5
4186 Returns a QTimeZone identifying how this datetime represents time.
4187
4188 The timeSpec() of the returned QTimeZone will coincide with that of this
4189 datetime; if it is not Qt::TimeZone then the returned QTimeZone is a time
4190 representation. When their timeSpec() is Qt::OffsetFromUTC, the returned
4191 QTimeZone's fixedSecondsAheadOfUtc() supplies the offset. When timeSpec()
4192 is Qt::TimeZone, the QTimeZone object itself is the full representation of
4193 that time zone.
4194
4195 \sa timeZone(), setTimeZone(), QTimeZone::asBackendZone()
4196*/
4197
4198QTimeZone QDateTime::timeRepresentation() const
4199{
4200 return d.timeZone();
4201}
4202
4203#if QT_CONFIG(timezone)
4204/*!
4205 \since 5.2
4206
4207 Returns the time zone of the datetime.
4208
4209 The result is the same as \c{timeRepresentation().asBackendZone()}. In all
4210 cases, the result's \l {QTimeZone::timeSpec()}{timeSpec()} is Qt::TimeZone.
4211
4212 When timeSpec() is Qt::LocalTime, the result will describe local time at the
4213 time this method was called. It will not reflect subsequent changes to the
4214 system time zone, even when the QDateTime from which it was obtained does.
4215
4216 \sa timeRepresentation(), setTimeZone(), Qt::TimeSpec, QTimeZone::asBackendZone()
4217*/
4218
4219QTimeZone QDateTime::timeZone() const
4220{
4221 return d.timeZone().asBackendZone();
4222}
4223#endif // timezone
4224
4225/*!
4226 \since 5.2
4227
4228 Returns this datetime's Offset From UTC in seconds.
4229
4230 The result depends on timeSpec():
4231 \list
4232 \li \c Qt::UTC The offset is 0.
4233 \li \c Qt::OffsetFromUTC The offset is the value originally set.
4234 \li \c Qt::LocalTime The local time's offset from UTC is returned.
4235 \li \c Qt::TimeZone The offset used by the time-zone is returned.
4236 \endlist
4237
4238 For the last two, the offset at this date and time will be returned, taking
4239 account of Daylight-Saving Offset. The offset is the difference between the
4240 local time or time in the given time-zone and UTC time; it is positive in
4241 time-zones ahead of UTC (East of The Prime Meridian), negative for those
4242 behind UTC (West of The Prime Meridian).
4243
4244 \sa setTimeZone()
4245*/
4246
4247int QDateTime::offsetFromUtc() const
4248{
4249 const auto status = getStatus(d);
4250 if (!status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime))
4251 return 0;
4252 // But allow invalid date-time (e.g. gap's resolution) to report its offset.
4253 if (!d.isShort())
4254 return d->m_offsetFromUtc;
4255
4256 auto spec = extractSpec(status);
4257 if (spec == Qt::LocalTime) {
4258 // We didn't cache the value, so we need to calculate it:
4259 const auto resolve = toTransitionOptions(extractDaylightStatus(status));
4260 return QDateTimePrivate::localStateAtMillis(getMSecs(d), resolve).offset;
4261 }
4262
4263 Q_ASSERT(spec == Qt::UTC);
4264 return 0;
4265}
4266
4267/*!
4268 \since 5.2
4269
4270 Returns the Time Zone Abbreviation for this datetime.
4271
4272 The returned string depends on timeSpec():
4273
4274 \list
4275 \li For Qt::UTC it is "UTC".
4276 \li For Qt::OffsetFromUTC it will be in the format "UTC±00:00".
4277 \li For Qt::LocalTime, the host system is queried.
4278 \li For Qt::TimeZone, the associated QTimeZone object is queried.
4279 \endlist
4280
4281 \note The abbreviation is not guaranteed to be unique, i.e. different time
4282 zones may have the same abbreviation. For Qt::LocalTime and Qt::TimeZone,
4283 when returned by the host system, the abbreviation may be localized.
4284
4285 \sa timeSpec(), QTimeZone::abbreviation()
4286*/
4287
4288QString QDateTime::timeZoneAbbreviation() const
4289{
4290 if (!isValid())
4291 return QString();
4292
4293 switch (getSpec(d)) {
4294 case Qt::UTC:
4295 return "UTC"_L1;
4296 case Qt::OffsetFromUTC:
4297 return "UTC"_L1 + toOffsetString(Qt::ISODate, d->m_offsetFromUtc);
4298 case Qt::TimeZone:
4299#if !QT_CONFIG(timezone)
4300 break;
4301#else
4302 Q_ASSERT(d->m_timeZone.isValid());
4303 return d->m_timeZone.abbreviation(*this);
4304#endif // timezone
4305 case Qt::LocalTime:
4306#if defined(Q_OS_WIN) && QT_CONFIG(timezone)
4307 // MS's tzname is a full MS-name, not an abbreviation:
4308 if (QString sys = QTimeZone::systemTimeZone().abbreviation(*this); !sys.isEmpty())
4309 return sys;
4310 // ... but, even so, a full name isn't as bad as empty.
4311#endif
4312 return QDateTimePrivate::localNameAtMillis(getMSecs(d),
4313 extractDaylightStatus(getStatus(d)));
4314 }
4315 return QString();
4316}
4317
4318/*!
4319 \since 5.2
4320
4321 Returns if this datetime falls in Daylight-Saving Time.
4322
4323 If the Qt::TimeSpec is not Qt::LocalTime or Qt::TimeZone then will always
4324 return false.
4325
4326 \sa timeSpec()
4327*/
4328
4329bool QDateTime::isDaylightTime() const
4330{
4331 if (!isValid())
4332 return false;
4333
4334 switch (getSpec(d)) {
4335 case Qt::UTC:
4336 case Qt::OffsetFromUTC:
4337 return false;
4338 case Qt::TimeZone:
4339#if !QT_CONFIG(timezone)
4340 break;
4341#else
4342 Q_ASSERT(d->m_timeZone.isValid());
4343 if (auto dst = extractDaylightStatus(getStatus(d));
4344 dst != QDateTimePrivate::UnknownDaylightTime) {
4345 return dst == QDateTimePrivate::DaylightTime;
4346 }
4347 return d->m_timeZone.d->isDaylightTime(toMSecsSinceEpoch());
4348#endif // timezone
4349 case Qt::LocalTime: {
4350 auto dst = extractDaylightStatus(getStatus(d));
4351 if (dst == QDateTimePrivate::UnknownDaylightTime) {
4352 dst = QDateTimePrivate::localStateAtMillis(
4353 getMSecs(d), toTransitionOptions(TransitionResolution::LegacyBehavior)).dst;
4354 }
4355 return dst == QDateTimePrivate::DaylightTime;
4356 }
4357 }
4358 return false;
4359}
4360
4361/*!
4362 Sets the date part of this datetime to \a date.
4363
4364 If no time is set yet, it is set to midnight. If \a date is invalid, this
4365 QDateTime becomes invalid.
4366
4367 If \a date and time() describe a moment close to a transition for this
4368 datetime's time representation, \a resolve controls how that situation is
4369 resolved.
4370
4371 \include qdatetime.cpp pre-resolve-note
4372
4373 \sa date(), setTime(), setTimeZone()
4374*/
4375
4376void QDateTime::setDate(QDate date, TransitionResolution resolve)
4377{
4378 setDateTime(d, date, time());
4379 checkValidDateTime(d, resolve);
4380}
4381
4382/*!
4383 Sets the time part of this datetime to \a time. If \a time is not valid,
4384 this function sets it to midnight. Therefore, it's possible to clear any
4385 set time in a QDateTime by setting it to a default QTime:
4386
4387 \code
4388 QDateTime dt = QDateTime::currentDateTime();
4389 dt.setTime(QTime());
4390 \endcode
4391
4392 If date() and \a time describe a moment close to a transition for this
4393 datetime's time representation, \a resolve controls how that situation is
4394 resolved.
4395
4396 \include qdatetime.cpp pre-resolve-note
4397
4398 \sa time(), setDate(), setTimeZone()
4399*/
4400
4401void QDateTime::setTime(QTime time, TransitionResolution resolve)
4402{
4403 setDateTime(d, date(), time);
4404 checkValidDateTime(d, resolve);
4405}
4406
4407#if QT_DEPRECATED_SINCE(6, 9)
4408/*!
4409 \deprecated [6.9] Use setTimeZone() instead
4410
4411 Sets the time specification used in this datetime to \a spec.
4412 The datetime may refer to a different point in time.
4413
4414 If \a spec is Qt::OffsetFromUTC then the timeSpec() will be set
4415 to Qt::UTC, i.e. an effective offset of 0.
4416
4417 If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
4418 i.e. the current system time zone.
4419
4420 Example:
4421 \snippet code/src_corelib_time_qdatetime.cpp 19
4422
4423 \sa setTimeZone(), timeSpec(), toTimeSpec(), setDate(), setTime()
4424*/
4425
4426void QDateTime::setTimeSpec(Qt::TimeSpec spec)
4427{
4428 reviseTimeZone(d, asTimeZone(spec, 0, "QDateTime::setTimeSpec"),
4429 TransitionResolution::LegacyBehavior);
4430}
4431
4432/*!
4433 \since 5.2
4434 \deprecated [6.9] Use setTimeZone(QTimeZone::fromSecondsAheadOfUtc(offsetSeconds)) instead
4435
4436 Sets the timeSpec() to Qt::OffsetFromUTC and the offset to \a offsetSeconds.
4437 The datetime may refer to a different point in time.
4438
4439 The maximum and minimum offset is 14 positive or negative hours. If
4440 \a offsetSeconds is larger or smaller than that, then the result is
4441 undefined.
4442
4443 If \a offsetSeconds is 0 then the timeSpec() will be set to Qt::UTC.
4444
4445 \sa setTimeZone(), isValid(), offsetFromUtc(), toOffsetFromUtc()
4446*/
4447
4448void QDateTime::setOffsetFromUtc(int offsetSeconds)
4449{
4450 reviseTimeZone(d, QTimeZone::fromSecondsAheadOfUtc(offsetSeconds),
4451 TransitionResolution::Reject);
4452}
4453#endif // 6.9 deprecations
4454
4455/*!
4456 \since 5.2
4457
4458 Sets the time zone used in this datetime to \a toZone.
4459
4460 The datetime may refer to a different point in time. It uses the time
4461 representation of \a toZone, which may change the meaning of its unchanged
4462 date() and time().
4463
4464 If \a toZone is invalid then the datetime will be invalid. Otherwise, this
4465 datetime's timeSpec() after the call will match \c{toZone.timeSpec()}.
4466
4467 If date() and time() describe a moment close to a transition for \a toZone,
4468 \a resolve controls how that situation is resolved.
4469
4470 \include qdatetime.cpp pre-resolve-note
4471
4472 \sa timeRepresentation(), timeZone(), Qt::TimeSpec
4473*/
4474
4475void QDateTime::setTimeZone(const QTimeZone &toZone, TransitionResolution resolve)
4476{
4477 reviseTimeZone(d, toZone, resolve);
4478}
4479
4480/*!
4481 \since 4.7
4482
4483 Returns the datetime as a number of milliseconds after the start, in UTC, of
4484 the year 1970.
4485
4486 On systems that do not support time zones, this function will
4487 behave as if local time were Qt::UTC.
4488
4489 The behavior for this function is undefined if the datetime stored in
4490 this object is not valid. However, for all valid dates, this function
4491 returns a unique value.
4492
4493 \sa toSecsSinceEpoch(), setMSecsSinceEpoch(), fromMSecsSinceEpoch()
4494*/
4495qint64 QDateTime::toMSecsSinceEpoch() const
4496{
4497 // Note: QDateTimeParser relies on this producing a useful result, even when
4498 // !isValid(), at least when the invalidity is a time in a fall-back (that
4499 // we'll have adjusted to lie outside it, but marked invalid because it's
4500 // not what was asked for). Other things may be doing similar. But that's
4501 // only relevant when we got enough data for resolution to find it invalid.
4502 const auto status = getStatus(d);
4503 if (!status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime))
4504 return 0;
4505
4506 switch (extractSpec(status)) {
4507 case Qt::UTC:
4508 return getMSecs(d);
4509
4510 case Qt::OffsetFromUTC:
4511 Q_ASSERT(!d.isShort());
4512 return d->m_msecs - d->m_offsetFromUtc * MSECS_PER_SEC;
4513
4514 case Qt::LocalTime:
4515 if (status.testFlag(QDateTimePrivate::ShortData)) {
4516 // Short form has nowhere to cache the offset, so recompute.
4517 const auto resolve = toTransitionOptions(extractDaylightStatus(getStatus(d)));
4518 const auto state = QDateTimePrivate::localStateAtMillis(getMSecs(d), resolve);
4519 return state.when - state.offset * MSECS_PER_SEC;
4520 }
4521 // Use the offset saved by refreshZonedDateTime() on creation.
4522 return d->m_msecs - d->m_offsetFromUtc * MSECS_PER_SEC;
4523
4524 case Qt::TimeZone:
4525 Q_ASSERT(!d.isShort());
4526#if QT_CONFIG(timezone)
4527 // Use offset refreshZonedDateTime() saved on creation:
4528 if (d->m_timeZone.isValid())
4529 return d->m_msecs - d->m_offsetFromUtc * MSECS_PER_SEC;
4530#endif
4531 return 0;
4532 }
4533 Q_UNREACHABLE_RETURN(0);
4534}
4535
4536/*!
4537 \since 5.8
4538
4539 Returns the datetime as a number of seconds after the start, in UTC, of the
4540 year 1970.
4541
4542 On systems that do not support time zones, this function will
4543 behave as if local time were Qt::UTC.
4544
4545 The behavior for this function is undefined if the datetime stored in
4546 this object is not valid. However, for all valid dates, this function
4547 returns a unique value.
4548
4549 \sa toMSecsSinceEpoch(), fromSecsSinceEpoch(), setSecsSinceEpoch()
4550*/
4551qint64 QDateTime::toSecsSinceEpoch() const
4552{
4553 return toMSecsSinceEpoch() / MSECS_PER_SEC;
4554}
4555
4556/*!
4557 \since 4.7
4558
4559 Sets the datetime to represent a moment a given number, \a msecs, of
4560 milliseconds after the start, in UTC, of the year 1970.
4561
4562 On systems that do not support time zones, this function will
4563 behave as if local time were Qt::UTC.
4564
4565 Note that passing the minimum of \c qint64
4566 (\c{std::numeric_limits<qint64>::min()}) to \a msecs will result in
4567 undefined behavior.
4568
4569 \sa setSecsSinceEpoch(), toMSecsSinceEpoch(), fromMSecsSinceEpoch()
4570*/
4571void QDateTime::setMSecsSinceEpoch(qint64 msecs)
4572{
4573 auto status = getStatus(d);
4574 const auto spec = extractSpec(status);
4575 Q_ASSERT(specCanBeSmall(spec) || !d.isShort());
4576 QDateTimePrivate::ZoneState state(msecs);
4577
4578 status &= ~QDateTimePrivate::ValidityMask;
4579 if (QTimeZone::isUtcOrFixedOffset(spec)) {
4580 if (spec == Qt::OffsetFromUTC)
4581 state.offset = d->m_offsetFromUtc;
4582 if (!state.offset || !qAddOverflow(msecs, state.offset * MSECS_PER_SEC, &state.when))
4583 status |= QDateTimePrivate::ValidityMask;
4584 } else if (spec == Qt::LocalTime) {
4585 state = QDateTimePrivate::expressUtcAsLocal(msecs);
4586 if (state.valid)
4587 status = mergeDaylightStatus(status | QDateTimePrivate::ValidityMask, state.dst);
4588#if QT_CONFIG(timezone)
4589 } else if (spec == Qt::TimeZone && (d.detach(), d->m_timeZone.isValid())) {
4590 const auto data = d->m_timeZone.d->data(msecs);
4591 if (Q_LIKELY(data.offsetFromUtc != QTimeZonePrivate::invalidSeconds())) {
4592 state.offset = data.offsetFromUtc;
4593 Q_ASSERT(state.offset >= -SECS_PER_DAY && state.offset <= SECS_PER_DAY);
4594 if (!state.offset
4595 || !Q_UNLIKELY(qAddOverflow(msecs, state.offset * MSECS_PER_SEC, &state.when))) {
4596 d->m_status = mergeDaylightStatus(status | QDateTimePrivate::ValidityMask,
4597 data.daylightTimeOffset
4598 ? QDateTimePrivate::DaylightTime
4599 : QDateTimePrivate::StandardTime);
4600 d->m_msecs = state.when;
4601 d->m_offsetFromUtc = state.offset;
4602 return;
4603 } // else: zone can't represent this UTC time
4604 } // else: zone unable to represent given UTC time (should only happen on overflow).
4605#endif // timezone
4606 }
4607 Q_ASSERT(!status.testFlag(QDateTimePrivate::ValidDateTime)
4608 || (state.offset >= -SECS_PER_DAY && state.offset <= SECS_PER_DAY));
4609
4610 if (msecsCanBeSmall(state.when) && d.isShort()) {
4611 // we can keep short
4612 d.data.msecs = qintptr(state.when);
4613 d.data.status = status.toInt();
4614 } else {
4615 d.detach();
4616 d->m_status = status & ~QDateTimePrivate::ShortData;
4617 d->m_msecs = state.when;
4618 d->m_offsetFromUtc = state.offset;
4619 }
4620}
4621
4622/*!
4623 \since 5.8
4624
4625 Sets the datetime to represent a moment a given number, \a secs, of seconds
4626 after the start, in UTC, of the year 1970.
4627
4628 On systems that do not support time zones, this function will
4629 behave as if local time were Qt::UTC.
4630
4631 \sa setMSecsSinceEpoch(), toSecsSinceEpoch(), fromSecsSinceEpoch()
4632*/
4633void QDateTime::setSecsSinceEpoch(qint64 secs)
4634{
4635 qint64 msecs;
4636 if (!qMulOverflow(secs, std::integral_constant<qint64, MSECS_PER_SEC>(), &msecs))
4637 setMSecsSinceEpoch(msecs);
4638 else
4639 d.invalidate();
4640}
4641
4642#if QT_CONFIG(datestring) // depends on, so implies, textdate
4643/*!
4644 \overload toString()
4645
4646 Returns the datetime as a string in the \a format given.
4647
4648 If the \a format is Qt::TextDate, the string is formatted in the default
4649 way. The day and month names will be in English. An example of this
4650 formatting is "Wed May 20 03:40:13 1998". For localized formatting, see
4651 \l{QLocale::toString()}.
4652
4653 If the \a format is Qt::ISODate, the string format corresponds to the ISO
4654 8601 extended specification for representations of dates and times, taking
4655 the form yyyy-MM-ddTHH:mm:ss[Z|±HH:mm], depending on the timeSpec() of the
4656 QDateTime. If the timeSpec() is Qt::UTC, Z will be appended to the string;
4657 if the timeSpec() is Qt::OffsetFromUTC, the offset in hours and minutes from
4658 UTC will be appended to the string. To include milliseconds in the ISO 8601
4659 date, use the \a format Qt::ISODateWithMs, which corresponds to
4660 yyyy-MM-ddTHH:mm:ss.zzz[Z|±HH:mm].
4661
4662 If the \a format is Qt::RFC2822Date, the string is formatted
4663 following \l{RFC 2822}.
4664
4665 If the datetime is invalid, an empty string will be returned.
4666
4667 \warning The Qt::ISODate format is only valid for years in the
4668 range 0 to 9999.
4669
4670 \sa fromString(), QDate::toString(), QTime::toString(),
4671 QLocale::toString()
4672*/
4673QString QDateTime::toString(Qt::DateFormat format) const
4674{
4675 QString buf;
4676 if (!isValid())
4677 return buf;
4678
4679 switch (format) {
4680 case Qt::RFC2822Date:
4681 buf = QLocale::c().toString(*this, u"dd MMM yyyy hh:mm:ss ");
4682 buf += toOffsetString(Qt::TextDate, offsetFromUtc());
4683 return buf;
4684 default:
4685 case Qt::TextDate: {
4686 const std::pair<QDate, QTime> p = getDateTime(d);
4687 buf = toStringTextDate(p.first);
4688 // Insert time between date's day and year:
4689 buf.insert(buf.lastIndexOf(u' '),
4690 u' ' + p.second.toString(Qt::TextDate));
4691 // Append zone/offset indicator, as appropriate:
4692 switch (timeSpec()) {
4693 case Qt::LocalTime:
4694 break;
4695#if QT_CONFIG(timezone)
4696 case Qt::TimeZone:
4697 buf += u' ' + d->m_timeZone.displayName(
4698 *this, QTimeZone::OffsetName, QLocale::c());
4699 break;
4700#endif
4701 default:
4702#if 0 // ### Qt 7 GMT: use UTC instead, see qnamespace.qdoc documentation
4703 buf += " UTC"_L1;
4704#else
4705 buf += " GMT"_L1;
4706#endif
4707 if (getSpec(d) == Qt::OffsetFromUTC)
4708 buf += toOffsetString(Qt::TextDate, offsetFromUtc());
4709 }
4710 return buf;
4711 }
4712 case Qt::ISODate:
4713 case Qt::ISODateWithMs: {
4714 const std::pair<QDate, QTime> p = getDateTime(d);
4715 buf = toStringIsoDate(p.first);
4716 if (buf.isEmpty())
4717 return QString(); // failed to convert
4718 buf += u'T' + p.second.toString(format);
4719 switch (getSpec(d)) {
4720 case Qt::UTC:
4721 buf += u'Z';
4722 break;
4723 case Qt::OffsetFromUTC:
4724 case Qt::TimeZone:
4725 buf += toOffsetString(Qt::ISODate, offsetFromUtc());
4726 break;
4727 default:
4728 break;
4729 }
4730 return buf;
4731 }
4732 }
4733}
4734
4735/*!
4736 \since 5.14
4737 \overload primary
4738 \fn QString QDateTime::toString(const QString &format, QCalendar cal) const
4739 \fn QString QDateTime::toString(QStringView format, QCalendar cal) const
4740
4741 Returns the datetime as a string. The \a format parameter determines the
4742 format of the result string. If \a cal is supplied, it determines the
4743 calendar used to represent the date; it defaults to Gregorian. Prior to Qt
4744 5.14, there was no \a cal parameter and the Gregorian calendar was always
4745 used.
4746
4747 In addition to the expressions, recognized in the format string to represent
4748 parts of the date and time, by QDate::toString() and QTime::toString(), this
4749 method supports:
4750
4751 \table
4752 \header \li Expression \li Output
4753 \row \li t
4754 \li The timezone abbreviation (for example "CEST"). Note that time zone
4755 abbreviations are not unique. In particular, \l fromString() cannot
4756 parse this.
4757 \row \li tt
4758 \li The timezone's offset from UTC with no colon between the hours and
4759 minutes (for example "+0200").
4760 \row \li ttt
4761 \li The timezone's offset from UTC with a colon between the hours and
4762 minutes (for example "+02:00").
4763 \row \li tttt
4764 \li The timezone name, as provided by \l QTimeZone::displayName() with
4765 the \l QTimeZone::LongName type. This may depend on the operating
4766 system in use. If no such name is available, the IANA ID of the
4767 zone (such as "Europe/Berlin") may be used. It may give no
4768 indication of whether the datetime was in daylight-saving time or
4769 standard time, which may lead to ambiguity if the datetime falls in
4770 an hour repeated by a transition between the two.
4771 \endtable
4772
4773 When the timezone cannot be determined or no suitable representation of it
4774 is available, these representions of it may be skipped. See \l
4775 QTimeZone::displayName() for details of when it returns an empty string.
4776
4777 Any sequence of characters enclosed in single quotes will be included
4778 verbatim in the output string (stripped of the quotes), even if it contains
4779 formatting characters. Two consecutive single quotes ("''") are replaced by
4780 a single quote in the output. All other characters in the format string are
4781 included verbatim in the output string.
4782
4783 Formats without separators (e.g. "ddMM") are supported but must be used with
4784 care, as the resulting strings aren't always reliably readable (e.g. if "dM"
4785 produces "212" it could mean either the 2nd of December or the 21st of
4786 February).
4787
4788 Example format strings (assumed that the QDateTime is 21 May 2001
4789 14:13:09.120):
4790
4791 \table
4792 \header \li Format \li Result
4793 \row \li dd.MM.yyyy \li 21.05.2001
4794 \row \li ddd MMMM d yy \li Tue May 21 01
4795 \row \li hh:mm:ss.zzz \li 14:13:09.120
4796 \row \li hh:mm:ss.z \li 14:13:09.12
4797 \row \li h:m:s ap \li 2:13:9 pm
4798 \endtable
4799
4800 If the datetime is invalid, an empty string will be returned.
4801
4802 \note Day and month names as well as AM/PM indicators are given in English
4803 (C locale). To get localized month and day names and localized forms of
4804 AM/PM, use QLocale::system().toDateTime().
4805
4806 \sa fromString(), QDate::toString(), QTime::toString(), QLocale::toString()
4807*/
4808QString QDateTime::toString(QStringView format, QCalendar cal) const
4809{
4810 return QLocale::c().toString(*this, format, cal);
4811}
4812
4813// Out-of-line no-calendar overloads, since QCalendar is a non-trivial type
4814/*!
4815 \since 5.10
4816 \overload toString()
4817*/
4818QString QDateTime::toString(QStringView format) const
4819{
4820 return QLocale::c().toString(*this, format, QCalendar());
4821}
4822
4823/*!
4824 \since 4.6
4825 \overload toString()
4826*/
4827QString QDateTime::toString(const QString &format) const
4828{
4829 return QLocale::c().toString(*this, qToStringViewIgnoringNull(format), QCalendar());
4830}
4831#endif // datestring
4832
4833static inline void massageAdjustedDateTime(QDateTimeData &d, QDate date, QTime time, bool forward)
4834{
4835 const QDateTimePrivate::TransitionOptions resolve = toTransitionOptions(
4836 forward ? QDateTime::TransitionResolution::RelativeToBefore
4837 : QDateTime::TransitionResolution::RelativeToAfter);
4838 auto status = getStatus(d);
4839 Q_ASSERT(status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime
4840 | QDateTimePrivate::ValidDateTime));
4841 auto spec = extractSpec(status);
4842 if (QTimeZone::isUtcOrFixedOffset(spec)) {
4843 setDateTime(d, date, time);
4845 return;
4846 }
4847 qint64 local = timeToMSecs(date, time);
4848 const QDateTimePrivate::ZoneState state = stateAtMillis(d.timeZone(), local, resolve);
4849 Q_ASSERT(state.valid || state.dst == QDateTimePrivate::UnknownDaylightTime);
4850 if (state.dst == QDateTimePrivate::UnknownDaylightTime)
4851 status.setFlag(QDateTimePrivate::ValidDateTime, false);
4852 else
4853 status = mergeDaylightStatus(status | QDateTimePrivate::ValidDateTime, state.dst);
4854
4855 if (status & QDateTimePrivate::ShortData) {
4856 d.data.msecs = state.when;
4857 d.data.status = status.toInt();
4858 } else {
4859 d.detach();
4860 d->m_status = status;
4861 if (state.valid) {
4862 d->m_msecs = state.when;
4863 d->m_offsetFromUtc = state.offset;
4864 }
4865 }
4866}
4867
4868/*!
4869 Returns a QDateTime object containing a datetime \a ndays days
4870 later than the datetime of this object (or earlier if \a ndays is
4871 negative).
4872
4873 If the timeSpec() is Qt::LocalTime or Qt::TimeZone and the resulting date
4874 and time fall in the Standard Time to Daylight-Saving Time transition hour
4875 then the result will be just beyond this gap, in the direction of change.
4876 If the transition is at 2am and the clock goes forward to 3am, the result of
4877 aiming between 2am and 3am will be adjusted to fall before 2am (if \c{ndays
4878 < 0}) or after 3am (otherwise).
4879
4880 \sa daysTo(), addMonths(), addYears(), addSecs(), {Timezone transitions}
4881*/
4882
4883QDateTime QDateTime::addDays(qint64 ndays) const
4884{
4885 if (isNull())
4886 return QDateTime();
4887
4888 QDateTime dt(*this);
4889 std::pair<QDate, QTime> p = getDateTime(d);
4890 massageAdjustedDateTime(dt.d, p.first.addDays(ndays), p.second, ndays >= 0);
4891 return dt;
4892}
4893
4894/*!
4895 \fn QDate &QDate::operator++(QDate &date)
4896 \since 6.11
4897
4898 The prefix \c{++} operator, adds a day to \a date and returns a reference to
4899 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, adds a day to \a date and returns a copy of
4909 \a date with the previous date.
4910
4911 \sa addDays(), operator--()
4912*/
4913
4914/*!
4915 \fn QDate &QDate::operator--(QDate &date)
4916 \since 6.11
4917
4918 The prefix \c{--} operator, subtracts a day from \a date and returns a
4919 reference to the modified date object.
4920
4921 \sa addDays(), operator++()
4922*/
4923
4924/*!
4925 \fn QDate QDate::operator--(QDate &date, int)
4926 \since 6.11
4927
4928 The postfix \c{--} operator, subtracts a day from \a date and returns a
4929 copy of \a date with the next date.
4930
4931 \sa addDays(), operator++()
4932*/
4933
4934/*!
4935 Returns a QDateTime object containing a datetime \a nmonths months
4936 later than the datetime of this object (or earlier if \a nmonths
4937 is negative).
4938
4939 If the timeSpec() is Qt::LocalTime or Qt::TimeZone and the resulting date
4940 and time fall in the Standard Time to Daylight-Saving Time transition hour
4941 then the result will be just beyond this gap, in the direction of change.
4942 If the transition is at 2am and the clock goes forward to 3am, the result of
4943 aiming between 2am and 3am will be adjusted to fall before 2am (if
4944 \c{nmonths < 0}) or after 3am (otherwise).
4945
4946 \sa daysTo(), addDays(), addYears(), addSecs(), {Timezone transitions}
4947*/
4948
4949QDateTime QDateTime::addMonths(int nmonths) const
4950{
4951 if (isNull())
4952 return QDateTime();
4953
4954 QDateTime dt(*this);
4955 std::pair<QDate, QTime> p = getDateTime(d);
4956 massageAdjustedDateTime(dt.d, p.first.addMonths(nmonths), p.second, nmonths >= 0);
4957 return dt;
4958}
4959
4960/*!
4961 Returns a QDateTime object containing a datetime \a nyears years
4962 later than the datetime of this object (or earlier if \a nyears is
4963 negative).
4964
4965 If the timeSpec() is Qt::LocalTime or Qt::TimeZone and the resulting date
4966 and time fall in the Standard Time to Daylight-Saving Time transition hour
4967 then the result will be just beyond this gap, in the direction of change.
4968 If the transition is at 2am and the clock goes forward to 3am, the result of
4969 aiming between 2am and 3am will be adjusted to fall before 2am (if \c{nyears
4970 < 0}) or after 3am (otherwise).
4971
4972 \sa daysTo(), addDays(), addMonths(), addSecs(), {Timezone transitions}
4973*/
4974
4975QDateTime QDateTime::addYears(int nyears) const
4976{
4977 if (isNull())
4978 return QDateTime();
4979
4980 QDateTime dt(*this);
4981 std::pair<QDate, QTime> p = getDateTime(d);
4982 massageAdjustedDateTime(dt.d, p.first.addYears(nyears), p.second, nyears >= 0);
4983 return dt;
4984}
4985
4986/*!
4987 Returns a QDateTime object containing a datetime \a s seconds
4988 later than the datetime of this object (or earlier if \a s is
4989 negative).
4990
4991 If this datetime is invalid, an invalid datetime will be returned.
4992
4993 \sa addMSecs(), secsTo(), addDays(), addMonths(), addYears()
4994*/
4995
4996QDateTime QDateTime::addSecs(qint64 s) const
4997{
4998 qint64 msecs;
4999 if (qMulOverflow(s, std::integral_constant<qint64, MSECS_PER_SEC>(), &msecs))
5000 return QDateTime();
5001 return addMSecs(msecs);
5002}
5003
5004/*!
5005 Returns a QDateTime object containing a datetime \a msecs milliseconds
5006 later than the datetime of this object (or earlier if \a msecs is
5007 negative).
5008
5009 If this datetime is invalid, an invalid datetime will be returned.
5010
5011 \sa addSecs(), msecsTo(), addDays(), addMonths(), addYears()
5012*/
5013QDateTime QDateTime::addMSecs(qint64 msecs) const
5014{
5015 if (!isValid())
5016 return QDateTime();
5017
5018 QDateTime dt(*this);
5019 switch (getSpec(d)) {
5020 case Qt::LocalTime:
5021 case Qt::TimeZone:
5022 // Convert to real UTC first in case this crosses a DST transition:
5023 if (!qAddOverflow(toMSecsSinceEpoch(), msecs, &msecs))
5024 dt.setMSecsSinceEpoch(msecs);
5025 else
5026 dt.d.invalidate();
5027 break;
5028 case Qt::UTC:
5029 case Qt::OffsetFromUTC:
5030 // No need to convert, just add on
5031 if (qAddOverflow(getMSecs(d), msecs, &msecs)) {
5032 dt.d.invalidate();
5033 } else if (d.isShort() && msecsCanBeSmall(msecs)) {
5034 dt.d.data.msecs = qintptr(msecs);
5035 } else {
5036 dt.d.detach();
5037 dt.d->m_msecs = msecs;
5038 }
5039 break;
5040 }
5041 return dt;
5042}
5043
5044/*!
5045 \fn QDateTime QDateTime::addDuration(std::chrono::milliseconds msecs) const
5046
5047 \since 6.4
5048
5049 Returns a QDateTime object containing a datetime \a msecs milliseconds
5050 later than the datetime of this object (or earlier if \a msecs is
5051 negative).
5052
5053 If this datetime is invalid, an invalid datetime will be returned.
5054
5055 \note Adding durations expressed in \c{std::chrono::months} or
5056 \c{std::chrono::years} does not yield the same result obtained by using
5057 addMonths() or addYears(). The former are fixed durations, calculated in
5058 relation to the solar year; the latter use the Gregorian calendar definitions
5059 of months/years.
5060
5061 \sa addMSecs(), msecsTo(), addDays(), addMonths(), addYears()
5062*/
5063
5064/*!
5065 Returns the number of days from this datetime to the \a other
5066 datetime. The number of days is counted as the number of times
5067 midnight is reached between this datetime to the \a other
5068 datetime. This means that a 10 minute difference from 23:55 to
5069 0:05 the next day counts as one day.
5070
5071 If the \a other datetime is earlier than this datetime,
5072 the value returned is negative.
5073
5074 Example:
5075 \snippet code/src_corelib_time_qdatetime.cpp 15
5076
5077 \sa addDays(), secsTo(), msecsTo()
5078*/
5079
5080qint64 QDateTime::daysTo(const QDateTime &other) const
5081{
5082 return date().daysTo(other.date());
5083}
5084
5085/*!
5086 Returns the number of seconds from this datetime to the \a other
5087 datetime. If the \a other datetime is earlier than this datetime,
5088 the value returned is negative.
5089
5090 Before performing the comparison, the two datetimes are converted
5091 to Qt::UTC to ensure that the result is correct if daylight-saving
5092 (DST) applies to one of the two datetimes but not the other.
5093
5094 Returns 0 if either datetime is invalid.
5095
5096 Example:
5097 \snippet code/src_corelib_time_qdatetime.cpp 11
5098
5099 \sa addSecs(), daysTo(), QTime::secsTo()
5100*/
5101
5102qint64 QDateTime::secsTo(const QDateTime &other) const
5103{
5104 return msecsTo(other) / MSECS_PER_SEC;
5105}
5106
5107/*!
5108 Returns the number of milliseconds from this datetime to the \a other
5109 datetime. If the \a other datetime is earlier than this datetime,
5110 the value returned is negative.
5111
5112 Before performing the comparison, the two datetimes are converted
5113 to Qt::UTC to ensure that the result is correct if daylight-saving
5114 (DST) applies to one of the two datetimes and but not the other.
5115
5116 Returns 0 if either datetime is invalid.
5117
5118 \sa addMSecs(), daysTo(), QTime::msecsTo()
5119*/
5120
5121qint64 QDateTime::msecsTo(const QDateTime &other) const
5122{
5123 if (!isValid() || !other.isValid())
5124 return 0;
5125
5126 return other.toMSecsSinceEpoch() - toMSecsSinceEpoch();
5127}
5128
5129/*!
5130 \fn std::chrono::milliseconds QDateTime::operator-(const QDateTime &lhs, const QDateTime &rhs)
5131 \since 6.4
5132
5133 Returns the number of milliseconds between \a lhs and \a rhs.
5134 If \a lhs is earlier than \a rhs, the result will be negative.
5135
5136 Returns 0 if either datetime is invalid.
5137
5138 \sa msecsTo()
5139*/
5140
5141/*!
5142 \fn QDateTime QDateTime::operator+(const QDateTime &dateTime, std::chrono::milliseconds duration)
5143 \fn QDateTime QDateTime::operator+(std::chrono::milliseconds duration, const QDateTime &dateTime)
5144
5145 \since 6.4
5146
5147 Returns a QDateTime object containing a datetime \a duration milliseconds
5148 later than \a dateTime (or earlier if \a duration is negative).
5149
5150 If \a dateTime is invalid, an invalid datetime will be returned.
5151
5152 \sa addMSecs()
5153*/
5154
5155/*!
5156 \fn QDateTime &QDateTime::operator+=(std::chrono::milliseconds duration)
5157 \since 6.4
5158
5159 Modifies this datetime object by adding the given \a duration.
5160 The updated object will be later if \a duration is positive,
5161 or earlier if it is negative.
5162
5163 If this datetime is invalid, this function has no effect.
5164
5165 Returns a reference to this datetime object.
5166
5167 \sa addMSecs()
5168*/
5169
5170/*!
5171 \fn QDateTime QDateTime::operator-(const QDateTime &dateTime, std::chrono::milliseconds duration)
5172
5173 \since 6.4
5174
5175 Returns a QDateTime object containing a datetime \a duration milliseconds
5176 earlier than \a dateTime (or later if \a duration is negative).
5177
5178 If \a dateTime is invalid, an invalid datetime will be returned.
5179
5180 \sa addMSecs()
5181*/
5182
5183/*!
5184 \fn QDateTime &QDateTime::operator-=(std::chrono::milliseconds duration)
5185 \since 6.4
5186
5187 Modifies this datetime object by subtracting the given \a duration.
5188 The updated object will be earlier if \a duration is positive,
5189 or later if it is negative.
5190
5191 If this datetime is invalid, this function has no effect.
5192
5193 Returns a reference to this datetime object.
5194
5195 \sa addMSecs
5196*/
5197
5198#if QT_DEPRECATED_SINCE(6, 9)
5199/*!
5200 \deprecated [6.9] Use \l toTimeZone() instead.
5201
5202 Returns a copy of this datetime converted to the given time \a spec.
5203
5204 The result represents the same moment in time as, and is equal to, this datetime.
5205
5206 If \a spec is Qt::OffsetFromUTC then it is set to Qt::UTC. To set to a fixed
5207 offset from UTC, use toTimeZone() or toOffsetFromUtc().
5208
5209 If \a spec is Qt::TimeZone then it is set to Qt::LocalTime, i.e. the local
5210 Time Zone. To set a specified time-zone, use toTimeZone().
5211
5212 Example:
5213 \snippet code/src_corelib_time_qdatetime.cpp 16
5214
5215 \sa setTimeSpec(), timeSpec(), toTimeZone()
5216*/
5217
5218QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
5219{
5220 return toTimeZone(asTimeZone(spec, 0, "toTimeSpec"));
5221}
5222#endif // 6.9 deprecation
5223
5224/*!
5225 \since 5.2
5226
5227 Returns a copy of this datetime converted to a spec of Qt::OffsetFromUTC
5228 with the given \a offsetSeconds. Equivalent to
5229 \c{toTimeZone(QTimeZone::fromSecondsAheadOfUtc(offsetSeconds))}.
5230
5231 If the \a offsetSeconds equals 0 then a UTC datetime will be returned.
5232
5233 The result represents the same moment in time as, and is equal to, this datetime.
5234
5235 \sa offsetFromUtc(), toTimeZone()
5236*/
5237
5238QDateTime QDateTime::toOffsetFromUtc(int offsetSeconds) const
5239{
5240 return toTimeZone(QTimeZone::fromSecondsAheadOfUtc(offsetSeconds));
5241}
5242
5243/*!
5244 Returns a copy of this datetime converted to local time.
5245
5246 The result represents the same moment in time as, and is equal to, this datetime.
5247
5248 Example:
5249
5250 \snippet code/src_corelib_time_qdatetime.cpp 17
5251
5252 \sa toTimeZone(), toUTC(), toOffsetFromUtc()
5253*/
5254QDateTime QDateTime::toLocalTime() const
5255{
5256 return toTimeZone(QTimeZone::LocalTime);
5257}
5258
5259/*!
5260 Returns a copy of this datetime converted to UTC.
5261
5262 The result represents the same moment in time as, and is equal to, this datetime.
5263
5264 Example:
5265
5266 \snippet code/src_corelib_time_qdatetime.cpp 18
5267
5268 \sa toTimeZone(), toLocalTime(), toOffsetFromUtc()
5269*/
5270QDateTime QDateTime::toUTC() const
5271{
5272 return toTimeZone(QTimeZone::UTC);
5273}
5274
5275/*!
5276 \since 5.2
5277
5278 Returns a copy of this datetime converted to the given \a timeZone.
5279
5280 The result represents the same moment in time as, and is equal to, this datetime.
5281
5282 The result describes the moment in time in terms of \a timeZone's time
5283 representation. For example:
5284
5285 \snippet code/src_corelib_time_qdatetime.cpp 23
5286
5287 If \a timeZone is invalid then the datetime will be invalid. Otherwise the
5288 returned datetime's timeSpec() will match \c{timeZone.timeSpec()}.
5289
5290 \sa timeRepresentation(), toLocalTime(), toUTC(), toOffsetFromUtc()
5291*/
5292
5293QDateTime QDateTime::toTimeZone(const QTimeZone &timeZone) const
5294{
5295 if (timeRepresentation() == timeZone)
5296 return *this;
5297
5298 if (!isValid()) {
5299 QDateTime ret = *this;
5300 ret.setTimeZone(timeZone);
5301 return ret;
5302 }
5303
5304 return fromMSecsSinceEpoch(toMSecsSinceEpoch(), timeZone);
5305}
5306
5307/*!
5308 \internal
5309 Returns \c true if this datetime is equal to the \a other datetime;
5310 otherwise returns \c false.
5311
5312 \sa precedes(), operator==()
5313*/
5314
5315bool QDateTime::equals(const QDateTime &other) const
5316{
5317 if (!isValid())
5318 return !other.isValid();
5319 if (!other.isValid())
5320 return false;
5321
5322 const qint64 thisMs = getMSecs(d);
5323 const qint64 yourMs = getMSecs(other.d);
5324 if (usesSameOffset(d, other.d) || areFarEnoughApart(thisMs, yourMs))
5325 return thisMs == yourMs;
5326
5327 // Convert to UTC and compare
5328 return toMSecsSinceEpoch() == other.toMSecsSinceEpoch();
5329}
5330
5331/*!
5332 \fn bool QDateTime::operator==(const QDateTime &lhs, const QDateTime &rhs)
5333
5334 Returns \c true if \a lhs represents the same moment in time as \a rhs;
5335 otherwise returns \c false.
5336
5337//! [datetime-order-details]
5338 Two datetimes using different time representations can have different
5339 offsets from UTC. In this case, they may compare equivalent even if their \l
5340 date() and \l time() differ, if that difference matches the difference in
5341 UTC offset. If their \c date() and \c time() coincide, the one with higher
5342 offset from UTC is less (earlier) than the one with lower offset. As a
5343 result, datetimes are only weakly ordered.
5344
5345 Since 5.14, all invalid datetimes are equivalent and less than all valid
5346 datetimes.
5347//! [datetime-order-details]
5348
5349 \sa operator!=(), operator<(), operator<=(), operator>(), operator>=()
5350*/
5351
5352/*!
5353 \fn bool QDateTime::operator!=(const QDateTime &lhs, const QDateTime &rhs)
5354
5355 Returns \c true if \a lhs is different from \a rhs; otherwise returns \c
5356 false.
5357
5358 \include qdatetime.cpp datetime-order-details
5359
5360 \sa operator==()
5361*/
5362
5363Qt::weak_ordering compareThreeWay(const QDateTime &lhs, const QDateTime &rhs)
5364{
5365 if (!lhs.isValid())
5366 return rhs.isValid() ? Qt::weak_ordering::less : Qt::weak_ordering::equivalent;
5367
5368 if (!rhs.isValid())
5369 return Qt::weak_ordering::greater; // we know that lhs is valid here
5370
5371 const qint64 lhms = getMSecs(lhs.d), rhms = getMSecs(rhs.d);
5372 if (usesSameOffset(lhs.d, rhs.d) || areFarEnoughApart(lhms, rhms))
5373 return Qt::compareThreeWay(lhms, rhms);
5374
5375 // Convert to UTC and compare
5376 return Qt::compareThreeWay(lhs.toMSecsSinceEpoch(), rhs.toMSecsSinceEpoch());
5377}
5378
5379/*!
5380 \fn bool QDateTime::operator<(const QDateTime &lhs, const QDateTime &rhs)
5381
5382 Returns \c true if \a lhs is earlier than \a rhs;
5383 otherwise returns \c false.
5384
5385 \include qdatetime.cpp datetime-order-details
5386
5387 \sa operator==()
5388*/
5389
5390/*!
5391 \fn bool QDateTime::operator<=(const QDateTime &lhs, const QDateTime &rhs)
5392
5393 Returns \c true if \a lhs is earlier than or equal to \a rhs; otherwise
5394 returns \c false.
5395
5396 \include qdatetime.cpp datetime-order-details
5397
5398 \sa operator==()
5399*/
5400
5401/*!
5402 \fn bool QDateTime::operator>(const QDateTime &lhs, const QDateTime &rhs)
5403
5404 Returns \c true if \a lhs is later than \a rhs; otherwise returns \c false.
5405
5406 \include qdatetime.cpp datetime-order-details
5407
5408 \sa operator==()
5409*/
5410
5411/*!
5412 \fn bool QDateTime::operator>=(const QDateTime &lhs, const QDateTime &rhs)
5413
5414 Returns \c true if \a lhs is later than or equal to \a rhs;
5415 otherwise returns \c false.
5416
5417 \include qdatetime.cpp datetime-order-details
5418
5419 \sa operator==()
5420*/
5421
5422/*!
5423 \since 6.5
5424 \overload primary
5425 \fn QDateTime QDateTime::currentDateTime(const QTimeZone &zone)
5426
5427 Returns the system clock's current datetime, using the time representation
5428 described by \a zone. If \a zone is omitted, local time is used.
5429
5430 \sa currentDateTimeUtc(), QDate::currentDate(), QTime::currentTime(), toTimeZone()
5431*/
5432
5433/*!
5434 \since 0.90
5435 \overload currentDateTime()
5437QDateTime QDateTime::currentDateTime()
5438{
5439 return currentDateTime(QTimeZone::LocalTime);
5440}
5441
5442/*!
5443 \fn QDateTime QDateTime::currentDateTimeUtc()
5444 \since 4.7
5445 Returns the system clock's current datetime, expressed in terms of UTC.
5446
5447 Equivalent to \c{currentDateTime(QTimeZone::UTC)}.
5448
5449 \sa currentDateTime(), QDate::currentDate(), QTime::currentTime(), toTimeZone()
5450*/
5451
5452QDateTime QDateTime::currentDateTimeUtc()
5453{
5454 return currentDateTime(QTimeZone::UTC);
5455}
5456
5457/*!
5458 \fn qint64 QDateTime::currentMSecsSinceEpoch()
5459 \since 4.7
5460
5461 Returns the current number of milliseconds since the start, in UTC, of the year 1970.
5462
5463 This number is like the POSIX time_t variable, but expressed in milliseconds
5464 instead of seconds.
5465
5466 \sa currentDateTime(), currentDateTimeUtc(), toTimeZone()
5467*/
5468
5469/*!
5470 \fn qint64 QDateTime::currentSecsSinceEpoch()
5471 \since 5.8
5472
5473 Returns the number of seconds since the start, in UTC, of the year 1970.
5474
5475 This number is like the POSIX time_t variable.
5476
5477 \sa currentMSecsSinceEpoch()
5478*/
5479
5480/*!
5481 \since 6.4
5482 \overload primary
5483 \fn template <typename Clock, typename Duration> QDateTime QDateTime::fromStdTimePoint(const std::chrono::time_point<Clock, Duration> &time)
5484
5485 Constructs a datetime representing the same point in time as \a time,
5486 using Qt::UTC as its time representation.
5487
5488 The clock of \a time must be compatible with
5489 \c{std::chrono::system_clock}; in particular, a conversion
5490 supported by \c{std::chrono::clock_cast} must exist. After the
5491 conversion, the duration type of the result must be convertible to
5492 \c{std::chrono::milliseconds}.
5493
5494 If this is not the case, the caller must perform the necessary
5495 clock conversion towards \c{std::chrono::system_clock} and the
5496 necessary conversion of the duration type
5497 (cast/round/floor/ceil/...) so that the input to this function
5498 satisfies the constraints above.
5499
5500 \note This function requires C++20.
5501
5502 \sa toStdSysMilliseconds(), fromMSecsSinceEpoch()
5503*/
5504
5505/*!
5506 \since 6.4
5507 \overload fromStdTimePoint()
5509 Constructs a datetime representing the same point in time as \a time,
5510 using Qt::UTC as its time representation.
5511*/
5512QDateTime QDateTime::fromStdTimePoint(
5513 std::chrono::time_point<
5514 std::chrono::system_clock,
5515 std::chrono::milliseconds
5516 > time)
5517{
5518 return fromMSecsSinceEpoch(time.time_since_epoch().count(), QTimeZone::UTC);
5519}
5520
5521/*!
5522 \fn QDateTime QDateTime::fromStdTimePoint(const std::chrono::local_time<std::chrono::milliseconds> &time)
5523 \since 6.4
5524
5525 Constructs a datetime whose date and time are the number of milliseconds
5526 represented by \a time, counted since 1970-01-01T00:00:00.000 in local
5527 time (Qt::LocalTime).
5528
5529 \note This function requires C++20.
5530
5531 \sa toStdSysMilliseconds(), fromMSecsSinceEpoch()
5532*/
5533
5534/*!
5535 \fn QDateTime QDateTime::fromStdLocalTime(const std::chrono::local_time<std::chrono::milliseconds> &time)
5536 \since 6.4
5537
5538 Constructs a datetime whose date and time are the number of milliseconds
5539 represented by \a time, counted since 1970-01-01T00:00:00.000 in local
5540 time (Qt::LocalTime).
5541
5542 \note This function requires C++20.
5543
5544 \sa toStdSysMilliseconds(), fromMSecsSinceEpoch()
5545*/
5546
5547/*!
5548 \fn QDateTime QDateTime::fromStdZonedTime(const std::chrono::zoned_time<std::chrono::milliseconds, const std::chrono::time_zone *> &time);
5549 \since 6.4
5550
5551 Constructs a datetime representing the same point in time as \a time.
5552 The result will be expressed in \a{time}'s time zone.
5553
5554 \note This function requires C++20.
5555
5556 \sa QTimeZone
5557
5558 \sa toStdSysMilliseconds(), fromMSecsSinceEpoch()
5559*/
5560
5561/*!
5562 \fn std::chrono::sys_time<std::chrono::milliseconds> QDateTime::toStdSysMilliseconds() const
5563 \since 6.4
5564
5565 Converts this datetime object to the equivalent time point expressed in
5566 milliseconds, using \c{std::chrono::system_clock} as a clock.
5567
5568 \note This function requires C++20.
5569
5570 \sa fromStdTimePoint(), toMSecsSinceEpoch()
5571*/
5572
5573/*!
5574 \fn std::chrono::sys_seconds QDateTime::toStdSysSeconds() const
5575 \since 6.4
5576
5577 Converts this datetime object to the equivalent time point expressed in
5578 seconds, using \c{std::chrono::system_clock} as a clock.
5579
5580 \note This function requires C++20.
5581
5582 \sa fromStdTimePoint(), toSecsSinceEpoch()
5583*/
5584
5585#if defined(Q_OS_WIN)
5586static inline uint msecsFromDecomposed(int hour, int minute, int sec, int msec = 0)
5587{
5588 return MSECS_PER_HOUR * hour + MSECS_PER_MIN * minute + MSECS_PER_SEC * sec + msec;
5589}
5590
5591QDate QDate::currentDate()
5592{
5593 SYSTEMTIME st = {};
5594 GetLocalTime(&st);
5595 return QDate(st.wYear, st.wMonth, st.wDay);
5596}
5597
5598QTime QTime::currentTime()
5599{
5600 QTime ct;
5601 SYSTEMTIME st = {};
5602 GetLocalTime(&st);
5603 ct.setHMS(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
5604 return ct;
5605}
5606
5607QDateTime QDateTime::currentDateTime(const QTimeZone &zone)
5608{
5609 // We can get local time or "system" time (which is UTC); otherwise, we must
5610 // convert, which is most efficiently done from UTC.
5611 const Qt::TimeSpec spec = zone.timeSpec();
5612 SYSTEMTIME st = {};
5613 // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtime
5614 // We previously used GetLocalTime for spec == LocalTime but it didn't provide enough
5615 // information to differentiate between repeated hours of a tradition and would report the same
5616 // timezone (eg always CEST, never CET) for both. But toTimeZone handles it correctly, given
5617 // the UTC time.
5618 GetSystemTime(&st);
5619 QDate d(st.wYear, st.wMonth, st.wDay);
5620 QTime t(msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds));
5621 QDateTime utc(d, t, QTimeZone::UTC);
5622 return spec == Qt::UTC ? utc : utc.toTimeZone(zone);
5623}
5624
5625qint64 QDateTime::currentMSecsSinceEpoch() noexcept
5626{
5627 SYSTEMTIME st = {};
5628 GetSystemTime(&st);
5629 const qint64 daysAfterEpoch = QDate(1970, 1, 1).daysTo(QDate(st.wYear, st.wMonth, st.wDay));
5630
5631 return msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds) +
5632 daysAfterEpoch * MSECS_PER_DAY;
5633}
5634
5635qint64 QDateTime::currentSecsSinceEpoch() noexcept
5636{
5637 SYSTEMTIME st = {};
5638 GetSystemTime(&st);
5639 const qint64 daysAfterEpoch = QDate(1970, 1, 1).daysTo(QDate(st.wYear, st.wMonth, st.wDay));
5640
5641 return st.wHour * SECS_PER_HOUR + st.wMinute * SECS_PER_MIN + st.wSecond +
5642 daysAfterEpoch * SECS_PER_DAY;
5643}
5644
5645#elif defined(Q_OS_UNIX) // Assume POSIX-compliant
5646QDate QDate::currentDate()
5647{
5648 return QDateTime::currentDateTime().date();
5649}
5650
5651QTime QTime::currentTime()
5652{
5653 return QDateTime::currentDateTime().time();
5654}
5655
5656QDateTime QDateTime::currentDateTime(const QTimeZone &zone)
5657{
5658 return fromMSecsSinceEpoch(currentMSecsSinceEpoch(), zone);
5659}
5660
5661qint64 QDateTime::currentMSecsSinceEpoch() noexcept
5662{
5663 struct timespec when;
5664 if (clock_gettime(CLOCK_REALTIME, &when) == 0) // should always succeed
5665 return when.tv_sec * MSECS_PER_SEC + (when.tv_nsec + 500'000) / 1'000'000;
5666 Q_UNREACHABLE_RETURN(0);
5667}
5668
5669qint64 QDateTime::currentSecsSinceEpoch() noexcept
5670{
5671 struct timespec when;
5672 if (clock_gettime(CLOCK_REALTIME, &when) == 0) // should always succeed
5673 return when.tv_sec;
5674 Q_UNREACHABLE_RETURN(0);
5675}
5676#else
5677#error "What system is this?"
5678#endif
5679
5680#if QT_DEPRECATED_SINCE(6, 9)
5681/*!
5682 \since 5.2
5683 \overload fromMSecsSinceEpoch()
5684 \deprecated [6.9] Pass a \l QTimeZone instead, or omit \a spec and \a offsetSeconds.
5685
5686 Returns a datetime representing a moment the given number \a msecs of
5687 milliseconds after the start, in UTC, of the year 1970, described as
5688 specified by \a spec and \a offsetSeconds.
5689
5690 Note that there are possible values for \a msecs that lie outside the valid
5691 range of QDateTime, both negative and positive. The behavior of this
5692 function is undefined for those values.
5693
5694 If the \a spec is not Qt::OffsetFromUTC then the \a offsetSeconds will be
5695 ignored. If the \a spec is Qt::OffsetFromUTC and the \a offsetSeconds is 0
5696 then Qt::UTC will be used as the \a spec, since UTC has zero offset.
5697
5698 If \a spec is Qt::TimeZone then Qt::LocalTime will be used in its place,
5699 equivalent to using the current system time zone (but differently
5700 represented).
5701
5702 \sa fromSecsSinceEpoch(), toMSecsSinceEpoch(), setMSecsSinceEpoch()
5703*/
5704QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec, int offsetSeconds)
5705{
5706 return fromMSecsSinceEpoch(msecs,
5707 asTimeZone(spec, offsetSeconds, "QDateTime::fromMSecsSinceEpoch"));
5708}
5709
5710/*!
5711 \since 5.8
5712 \overload fromSecsSinceEpoch
5713 \deprecated [6.9] Pass a \l QTimeZone instead, or omit \a spec and \a offsetSeconds.
5714
5715 Returns a datetime representing a moment the given number \a secs of seconds
5716 after the start, in UTC, of the year 1970, described as specified by \a spec
5717 and \a offsetSeconds.
5718
5719 Note that there are possible values for \a secs that lie outside the valid
5720 range of QDateTime, both negative and positive. The behavior of this
5721 function is undefined for those values.
5722
5723 If the \a spec is not Qt::OffsetFromUTC then the \a offsetSeconds will be
5724 ignored. If the \a spec is Qt::OffsetFromUTC and the \a offsetSeconds is 0
5725 then Qt::UTC will be used as the \a spec, since UTC has zero offset.
5726
5727 If \a spec is Qt::TimeZone then Qt::LocalTime will be used in its place,
5728 equivalent to using the current system time zone (but differently
5729 represented).
5730
5731 \sa fromMSecsSinceEpoch(), toSecsSinceEpoch(), setSecsSinceEpoch()
5732*/
5733QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, Qt::TimeSpec spec, int offsetSeconds)
5734{
5735 return fromSecsSinceEpoch(secs,
5736 asTimeZone(spec, offsetSeconds, "QDateTime::fromSecsSinceEpoch"));
5737}
5738#endif // 6.9 deprecations
5739
5740/*!
5741 \since 5.2
5742 \overload primary
5743
5744 Returns a datetime representing a moment the given number \a msecs of
5745 milliseconds after the start, in UTC, of the year 1970, described as
5746 specified by \a timeZone. The default time representation is local time.
5747
5748 Note that there are possible values for \a msecs that lie outside the valid
5749 range of QDateTime, both negative and positive. The behavior of this
5750 function is undefined for those values.
5751
5752 \sa fromSecsSinceEpoch(), toMSecsSinceEpoch(), setMSecsSinceEpoch()
5753*/
5754QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone)
5755{
5756 QDateTime dt;
5757 reviseTimeZone(dt.d, timeZone, TransitionResolution::Reject);
5758 if (timeZone.isValid())
5759 dt.setMSecsSinceEpoch(msecs);
5760 return dt;
5761}
5762
5763/*!
5764 \overload fromMSecsSinceEpoch()
5766QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
5767{
5768 return fromMSecsSinceEpoch(msecs, QTimeZone::LocalTime);
5769}
5770
5771/*!
5772 \since 5.8
5773 \overload primary
5774
5775 Returns a datetime representing a moment the given number \a secs of seconds
5776 after the start, in UTC, of the year 1970, described as specified by \a
5777 timeZone. The default time representation is local time.
5778
5779 Note that there are possible values for \a secs that lie outside the valid
5780 range of QDateTime, both negative and positive. The behavior of this
5781 function is undefined for those values.
5782
5783 \sa fromMSecsSinceEpoch(), toSecsSinceEpoch(), setSecsSinceEpoch()
5784*/
5785QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, const QTimeZone &timeZone)
5786{
5787 QDateTime dt;
5788 reviseTimeZone(dt.d, timeZone, TransitionResolution::Reject);
5789 if (timeZone.isValid())
5790 dt.setSecsSinceEpoch(secs);
5791 return dt;
5792}
5793
5794/*!
5795 \overload fromSecsSinceEpoch()
5797QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs)
5798{
5799 return fromSecsSinceEpoch(secs, QTimeZone::LocalTime);
5800}
5801
5802#if QT_CONFIG(datestring) // depends on, so implies, textdate
5803
5804/*!
5805 \overload
5806 \fn QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
5807
5808 Returns the QDateTime represented by the \a string, using the
5809 \a format given, or an invalid datetime if this is not possible.
5810
5811 Note for Qt::TextDate: only English short month names (e.g. "Jan" in short
5812 form or "January" in long form) are recognized.
5813
5814 \sa toString(), QLocale::toDateTime()
5815*/
5816
5817/*!
5818 \since 6.0
5819 \overload fromString()
5820*/
5821QDateTime QDateTime::fromString(QStringView string, Qt::DateFormat format)
5822{
5823 if (string.isEmpty())
5824 return QDateTime();
5825
5826 switch (format) {
5827 case Qt::RFC2822Date: {
5828 const ParsedRfcDateTime rfc = rfcDateImpl(string);
5829
5830 if (!rfc.date.isValid() || !rfc.time.isValid())
5831 return QDateTime();
5832
5833 QDateTime dateTime(rfc.date, rfc.time, QTimeZone::UTC);
5834 dateTime.setTimeZone(QTimeZone::fromSecondsAheadOfUtc(rfc.utcOffset));
5835 return dateTime;
5836 }
5837 case Qt::ISODate:
5838 case Qt::ISODateWithMs: {
5839 const int size = string.size();
5840 if (size < 10)
5841 return QDateTime();
5842
5843 QDate date = QDate::fromString(string.first(10), Qt::ISODate);
5844 if (!date.isValid())
5845 return QDateTime();
5846 if (size == 10)
5847 return date.startOfDay();
5848
5849 QTimeZone zone = QTimeZone::LocalTime;
5850 QStringView isoString = string.sliced(10); // trim "yyyy-MM-dd"
5851
5852 // Must be left with T (or space) and at least one digit for the hour:
5853 if (isoString.size() < 2
5854 || !(isoString.startsWith(u'T', Qt::CaseInsensitive)
5855 // RFC 3339 (section 5.6) allows a space here. (It actually
5856 // allows any separator one considers more readable, merely
5857 // giving space as an example - but let's not go wild !)
5858 || isoString.startsWith(u' '))) {
5859 return QDateTime();
5860 }
5861 isoString = isoString.sliced(1); // trim 'T' (or space)
5862
5863 // Check end of string for Time Zone definition, either Z for UTC or ±HH:mm for Offset
5864 if (isoString.endsWith(u'Z', Qt::CaseInsensitive)) {
5865 zone = QTimeZone::UTC;
5866 isoString.chop(1); // trim 'Z'
5867 } else {
5868 // the loop below is faster but functionally equal to:
5869 // const int signIndex = isoString.indexOf(QRegulargExpression(QStringLiteral("[+-]")));
5870 int signIndex = isoString.size() - 1;
5871 Q_ASSERT(signIndex >= 0);
5872 bool found = false;
5873 do {
5874 QChar character(isoString[signIndex]);
5875 found = character == u'+' || character == u'-';
5876 } while (!found && --signIndex >= 0);
5877
5878 if (found) {
5879 bool ok;
5880 int offset = fromOffsetString(isoString.sliced(signIndex), &ok);
5881 if (!ok)
5882 return QDateTime();
5883 isoString = isoString.first(signIndex);
5884 zone = QTimeZone::fromSecondsAheadOfUtc(offset);
5885 }
5886 }
5887
5888 // Might be end of day (24:00, including variants), which QTime considers invalid.
5889 // ISO 8601 (section 4.2.3) says that 24:00 is equivalent to 00:00 the next day.
5890 bool isMidnight24 = false;
5891 QTime time = fromIsoTimeString(isoString, format, &isMidnight24);
5892 if (!time.isValid())
5893 return QDateTime();
5894 if (isMidnight24) // time is 0:0, but we want the start of next day:
5895 return date.addDays(1).startOfDay(zone);
5896 return QDateTime(date, time, zone);
5897 }
5898 case Qt::TextDate: {
5899 QVarLengthArray<QStringView, 6> parts;
5900
5901 auto tokens = string.tokenize(u' ', Qt::SkipEmptyParts);
5902 auto it = tokens.begin();
5903 for (int i = 0; i < 6 && it != tokens.end(); ++i, ++it)
5904 parts.emplace_back(*it);
5905
5906 // Documented as "ddd MMM d HH:mm:ss yyyy" with optional offset-suffix;
5907 // and allow time either before or after year.
5908 if (parts.size() < 5 || it != tokens.end())
5909 return QDateTime();
5910
5911 // Year and time can be in either order.
5912 // Guess which by looking for ':' in the time
5913 int yearPart = 3;
5914 int timePart = 3;
5915 if (parts.at(3).contains(u':'))
5916 yearPart = 4;
5917 else if (parts.at(4).contains(u':'))
5918 timePart = 4;
5919 else
5920 return QDateTime();
5921
5922 bool ok = false;
5923 int day = parts.at(2).toInt(&ok);
5924 int year = ok ? parts.at(yearPart).toInt(&ok) : 0;
5925 int month = fromShortMonthName(parts.at(1));
5926 if (!ok || year == 0 || day == 0 || month < 1)
5927 return QDateTime();
5928
5929 const QDate date(year, month, day);
5930 if (!date.isValid())
5931 return QDateTime();
5932
5933 const QTime time = fromIsoTimeString(parts.at(timePart), format, nullptr);
5934 if (!time.isValid())
5935 return QDateTime();
5936
5937 if (parts.size() == 5)
5938 return QDateTime(date, time);
5939
5940 QStringView tz = parts.at(5);
5941 if (tz.startsWith("UTC"_L1)
5942 // GMT has long been deprecated as an alias for UTC.
5943 || tz.startsWith("GMT"_L1, Qt::CaseInsensitive)) {
5944 tz = tz.sliced(3);
5945 if (tz.isEmpty())
5946 return QDateTime(date, time, QTimeZone::UTC);
5947
5948 int offset = fromOffsetString(tz, &ok);
5949 return ok ? QDateTime(date, time, QTimeZone::fromSecondsAheadOfUtc(offset))
5950 : QDateTime();
5951 }
5952 return QDateTime();
5953 }
5954 }
5955
5956 return QDateTime();
5957}
5958
5959/*!
5960 \overload primary
5961 \fn QDateTime QDateTime::fromString(const QString &string, const QString &format, int baseYear, QCalendar cal)
5962
5963 Returns the QDateTime represented by the \a string, using the \a
5964 format given, or an invalid datetime if the string cannot be parsed.
5965
5966 Uses the calendar \a cal if supplied, else Gregorian.
5967
5968 \include qlocale.cpp base-year-for-two-digit
5969
5970 In addition to the expressions, recognized in the format string to represent
5971 parts of the date and time, by QDate::fromString() and QTime::fromString(),
5972 this method supports:
5973
5974 \table
5975 \header \li Expression \li Output
5976 \row \li t
5977 \li the timezone (offset, name, "Z" or offset with "UTC" prefix)
5978 \row \li tt
5979 \li the timezone in offset format with no colon between hours and
5980 minutes (for example "+0200")
5981 \row \li ttt
5982 \li the timezone in offset format with a colon between hours and
5983 minutes (for example "+02:00")
5984 \row \li tttt
5985 \li the timezone name, either what \l QTimeZone::displayName() reports
5986 for \l QTimeZone::LongName or the IANA ID of the zone (for example
5987 "Europe/Berlin"). The names recognized are those known to \l
5988 QTimeZone, which may depend on the operating system in use.
5989 \endtable
5990
5991 If no 't' format specifier is present, the system's local time-zone is used.
5992 For the defaults of all other fields, see QDate::fromString() and QTime::fromString().
5993
5994 For example:
5995
5996 \snippet code/src_corelib_time_qdatetime.cpp 14
5997
5998 All other input characters will be treated as text. Any non-empty sequence
5999 of characters enclosed in single quotes will also be treated (stripped of
6000 the quotes) as text and not be interpreted as expressions.
6001
6002 \snippet code/src_corelib_time_qdatetime.cpp 12
6003
6004 If the format is not satisfied, an invalid QDateTime is returned. If the
6005 format is satisfied but \a string represents an invalid datetime (e.g. in a
6006 gap skipped by a time-zone transition), an valid QDateTime is returned, that
6007 represents a near-by datetime that is valid.
6008
6009 The expressions that don't have leading zeroes (d, M, h, m, s, z) will be
6010 greedy. This means that they will use two digits (or three, for z) even if this will
6011 put them outside the range and/or leave too few digits for other
6012 sections.
6013
6014 \snippet code/src_corelib_time_qdatetime.cpp 13
6015
6016 This could have meant 1 January 00:30.00 but the M will grab
6017 two digits.
6018
6019 Incorrectly specified fields of the \a string will cause an invalid
6020 QDateTime to be returned. Only datetimes between the local time start of
6021 year 100 and end of year 9999 are supported. Note that datetimes near the
6022 ends of this range in other time-zones, notably including UTC, may fall
6023 outside the range (and thus be treated as invalid) depending on local time
6024 zone.
6025
6026 \note Day and month names as well as AM/PM indicators must be given in
6027 English (C locale). If localized month and day names or localized forms of
6028 AM/PM are to be recognized, use QLocale::system().toDateTime().
6029
6030 \note If a format character is repeated more times than the longest
6031 expression in the table above using it, this part of the format will be read
6032 as several expressions with no separator between them; the longest above,
6033 possibly repeated as many times as there are copies of it, ending with a
6034 residue that may be a shorter expression. Thus \c{'tttttt'} would match
6035 \c{"Europe/BerlinEurope/Berlin"} and set the zone to Berlin time; if the
6036 datetime string contained "Europe/BerlinZ" it would "match" but produce an
6037 inconsistent result, leading to an invalid datetime.
6038
6039 \sa toString(), QDate::fromString(), QTime::fromString(),
6040 QLocale::toDateTime()
6041*/
6042
6043/*!
6044 \since 6.0
6045 \overload fromString()
6046 \fn QDateTime QDateTime::fromString(QStringView string, QStringView format, QCalendar cal)
6047*/
6048
6049/*!
6050 \since 6.0
6051 \overload fromString()
6052*/
6053QDateTime QDateTime::fromString(const QString &string, QStringView format, int baseYear,
6054 QCalendar cal)
6055{
6056#if QT_CONFIG(datetimeparser)
6057 QDateTime datetime;
6058
6059 QDateTimeParser dt(QMetaType::QDateTime, QDateTimeParser::FromString, cal);
6060 dt.setDefaultLocale(QLocale::c());
6061 if (dt.parseFormat(format) && (dt.fromString(string, &datetime, baseYear)
6062 || !datetime.isValid())) {
6063 return datetime;
6064 }
6065#else
6066 Q_UNUSED(string);
6067 Q_UNUSED(format);
6068 Q_UNUSED(baseYear);
6069 Q_UNUSED(cal);
6070#endif
6071 return QDateTime();
6072}
6073
6074/*!
6075 \since 5.14
6076 \overload fromString()
6077 \fn QDateTime QDateTime::fromString(const QString &string, const QString &format, QCalendar cal)
6078*/
6079
6080/*!
6081 \since 6.0
6082 \overload fromString()
6083 \fn QDateTime QDateTime::fromString(const QString &string, QStringView format, QCalendar cal)
6084*/
6085
6086/*!
6087 \since 6.7
6088 \overload fromString()
6089 \fn QDateTime QDateTime::fromString(QStringView string, QStringView format, int baseYear, QCalendar cal)
6090*/
6091
6092/*!
6093 \since 6.7
6094 \overload fromString()
6095 \fn QDateTime QDateTime::fromString(QStringView string, QStringView format, int baseYear)
6096
6097 Uses a default-constructed QCalendar.
6098*/
6099
6100/*!
6101 \since 6.7
6102 \overload fromString()
6103
6104 Uses a default-constructed QCalendar.
6105*/
6106QDateTime QDateTime::fromString(const QString &string, QStringView format, int baseYear)
6107{
6108 return fromString(string, format, baseYear, QCalendar());
6109}
6110
6111/*!
6112 \since 6.7
6113 \overload fromString()
6114 \fn QDateTime QDateTime::fromString(const QString &string, const QString &format, int baseYear)
6115
6116 Uses a default-constructed QCalendar.
6117*/
6118#endif // datestring
6119
6120/*****************************************************************************
6121 Date/time stream functions
6122 *****************************************************************************/
6123
6124#ifndef QT_NO_DATASTREAM
6125/*!
6126 \relates QDate
6127
6128 Writes the \a date to stream \a out.
6129
6130 \sa {Serializing Qt Data Types}
6131*/
6132
6133QDataStream &operator<<(QDataStream &out, QDate date)
6134{
6135 if (out.version() < QDataStream::Qt_5_0)
6136 return out << quint32(date.jd);
6137 else
6138 return out << date.jd;
6139}
6140
6141/*!
6142 \relates QDate
6143
6144 Reads a date from stream \a in into the \a date.
6145
6146 \sa {Serializing Qt Data Types}
6147*/
6148
6149QDataStream &operator>>(QDataStream &in, QDate &date)
6150{
6151 if (in.version() < QDataStream::Qt_5_0) {
6152 quint32 jd;
6153 in >> jd;
6154 // Older versions consider 0 an invalid jd.
6155 date.jd = (jd != 0 ? jd : QDate::nullJd());
6156 } else {
6157 in >> date.jd;
6158 }
6159
6160 return in;
6161}
6162
6163/*!
6164 \relates QTime
6165
6166 Writes \a time to stream \a out.
6167
6168 \sa {Serializing Qt Data Types}
6169*/
6170
6171QDataStream &operator<<(QDataStream &out, QTime time)
6172{
6173 if (out.version() >= QDataStream::Qt_4_0) {
6174 return out << quint32(time.mds);
6175 } else {
6176 // Qt3 had no support for reading -1, QTime() was valid and serialized as 0
6177 return out << quint32(time.isNull() ? 0 : time.mds);
6178 }
6179}
6180
6181/*!
6182 \relates QTime
6183
6184 Reads a time from stream \a in into the given \a time.
6185
6186 \sa {Serializing Qt Data Types}
6187*/
6188
6189QDataStream &operator>>(QDataStream &in, QTime &time)
6190{
6191 quint32 ds;
6192 in >> ds;
6193 if (in.version() >= QDataStream::Qt_4_0) {
6194 time.mds = int(ds);
6195 } else {
6196 // Qt3 would write 0 for a null time
6197 time.mds = (ds == 0) ? QTime::NullTime : int(ds);
6198 }
6199 return in;
6200}
6201
6202/*!
6203 \relates QDateTime
6204
6205 Writes \a dateTime to the \a out stream.
6206
6207 \sa {Serializing Qt Data Types}
6208*/
6209QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
6210{
6211 std::pair<QDate, QTime> dateAndTime;
6212
6213 // TODO: new version, route spec and details via QTimeZone
6214 if (out.version() >= QDataStream::Qt_5_2) {
6215
6216 // In 5.2 we switched to using Qt::TimeSpec and added offset and zone support
6217 dateAndTime = getDateTime(dateTime.d);
6218 out << dateAndTime << qint8(dateTime.timeSpec());
6219 if (dateTime.timeSpec() == Qt::OffsetFromUTC)
6220 out << qint32(dateTime.offsetFromUtc());
6221#if QT_CONFIG(timezone)
6222 else if (dateTime.timeSpec() == Qt::TimeZone)
6223 out << dateTime.timeZone();
6224#endif // timezone
6225
6226 } else if (out.version() == QDataStream::Qt_5_0) {
6227
6228 // In Qt 5.0 we incorrectly serialised all datetimes as UTC.
6229 // This approach is wrong and should not be used again; it breaks
6230 // the guarantee that a deserialised local datetime is the same time
6231 // of day, regardless of which timezone it was serialised in.
6232 dateAndTime = getDateTime((dateTime.isValid() ? dateTime.toUTC() : dateTime).d);
6233 out << dateAndTime << qint8(dateTime.timeSpec());
6234
6235 } else if (out.version() >= QDataStream::Qt_4_0) {
6236
6237 // From 4.0 to 5.1 (except 5.0) we used QDateTimePrivate::Spec
6238 dateAndTime = getDateTime(dateTime.d);
6239 out << dateAndTime;
6240 switch (dateTime.timeSpec()) {
6241 case Qt::UTC:
6242 out << (qint8)QDateTimePrivate::UTC;
6243 break;
6244 case Qt::OffsetFromUTC:
6245 out << (qint8)QDateTimePrivate::OffsetFromUTC;
6246 break;
6247 case Qt::TimeZone:
6248 out << (qint8)QDateTimePrivate::TimeZone;
6249 break;
6250 case Qt::LocalTime:
6251 out << (qint8)QDateTimePrivate::LocalUnknown;
6252 break;
6253 }
6254
6255 } else { // version < QDataStream::Qt_4_0
6256
6257 // Before 4.0 there was no TimeSpec, only Qt::LocalTime was supported
6258 dateAndTime = getDateTime(dateTime.d);
6259 out << dateAndTime;
6260
6261 }
6262
6263 return out;
6264}
6265
6266/*!
6267 \relates QDateTime
6268
6269 Reads a datetime from the stream \a in into \a dateTime.
6270
6271 \sa {Serializing Qt Data Types}
6272*/
6273
6274QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
6275{
6276 QDate dt;
6277 QTime tm;
6278 qint8 ts = 0;
6279 QTimeZone zone(QTimeZone::LocalTime);
6280
6281 if (in.version() >= QDataStream::Qt_5_2) {
6282
6283 // In 5.2 we switched to using Qt::TimeSpec and added offset and zone support
6284 in >> dt >> tm >> ts;
6285 switch (static_cast<Qt::TimeSpec>(ts)) {
6286 case Qt::UTC:
6287 zone = QTimeZone::UTC;
6288 break;
6289 case Qt::OffsetFromUTC: {
6290 qint32 offset = 0;
6291 in >> offset;
6292 zone = QTimeZone::fromSecondsAheadOfUtc(offset);
6293 break;
6294 }
6295 case Qt::LocalTime:
6296 break;
6297 case Qt::TimeZone:
6298 in >> zone;
6299 break;
6300 }
6301 // Note: no way to resolve transition ambiguity, when relevant; use default.
6302 dateTime = QDateTime(dt, tm, zone);
6303
6304 } else if (in.version() == QDataStream::Qt_5_0) {
6305
6306 // In Qt 5.0 we incorrectly serialised all datetimes as UTC
6307 in >> dt >> tm >> ts;
6308 dateTime = QDateTime(dt, tm, QTimeZone::UTC);
6309 if (static_cast<Qt::TimeSpec>(ts) == Qt::LocalTime)
6310 dateTime = dateTime.toTimeZone(zone);
6311
6312 } else if (in.version() >= QDataStream::Qt_4_0) {
6313
6314 // From 4.0 to 5.1 (except 5.0) we used QDateTimePrivate::Spec
6315 in >> dt >> tm >> ts;
6316 switch (static_cast<QDateTimePrivate::Spec>(ts)) {
6317 case QDateTimePrivate::OffsetFromUTC: // No offset was stored, so treat as UTC.
6318 case QDateTimePrivate::UTC:
6319 zone = QTimeZone::UTC;
6320 break;
6321 case QDateTimePrivate::TimeZone: // No zone was stored, so treat as LocalTime:
6322 case QDateTimePrivate::LocalUnknown:
6323 case QDateTimePrivate::LocalStandard:
6324 case QDateTimePrivate::LocalDST:
6325 break;
6326 }
6327 dateTime = QDateTime(dt, tm, zone);
6328
6329 } else { // version < QDataStream::Qt_4_0
6330
6331 // Before 4.0 there was no TimeSpec, only Qt::LocalTime was supported
6332 in >> dt >> tm;
6333 dateTime = QDateTime(dt, tm);
6334
6335 }
6336
6337 return in;
6338}
6339#endif // QT_NO_DATASTREAM
6340
6341/*****************************************************************************
6342 Date / Time Debug Streams
6343*****************************************************************************/
6344
6345#if !defined(QT_NO_DEBUG_STREAM) && QT_CONFIG(datestring)
6346QDebug operator<<(QDebug dbg, QDate date)
6347{
6348 QDebugStateSaver saver(dbg);
6349 dbg.nospace() << "QDate(";
6350 if (date.isValid())
6351 // QTBUG-91070, ISODate only supports years in the range 0-9999
6352 if (int y = date.year(); y > 0 && y <= 9999)
6353 dbg.nospace() << date.toString(Qt::ISODate);
6354 else
6355 dbg.nospace() << date.toString(Qt::TextDate);
6356 else
6357 dbg.nospace() << "Invalid";
6358 dbg.nospace() << ')';
6359 return dbg;
6360}
6361
6362QDebug operator<<(QDebug dbg, QTime time)
6363{
6364 QDebugStateSaver saver(dbg);
6365 dbg.nospace() << "QTime(";
6366 if (time.isValid())
6367 dbg.nospace() << time.toString(u"HH:mm:ss.zzz");
6368 else
6369 dbg.nospace() << "Invalid";
6370 dbg.nospace() << ')';
6371 return dbg;
6372}
6373
6374QDebug operator<<(QDebug dbg, const QDateTime &date)
6375{
6376 QDebugStateSaver saver(dbg);
6377 dbg.nospace() << "QDateTime(";
6378 if (date.isValid()) {
6379 const Qt::TimeSpec ts = date.timeSpec();
6380 dbg.noquote() << date.toString(u"yyyy-MM-dd HH:mm:ss.zzz t")
6381 << ' ' << ts;
6382 switch (ts) {
6383 case Qt::UTC:
6384 break;
6385 case Qt::OffsetFromUTC:
6386 dbg.space() << date.offsetFromUtc() << 's';
6387 break;
6388 case Qt::TimeZone:
6389#if QT_CONFIG(timezone)
6390 dbg.space() << date.timeZone().id();
6391#endif // timezone
6392 break;
6393 case Qt::LocalTime:
6394 break;
6395 }
6396 } else {
6397 dbg.nospace() << "Invalid";
6398 }
6399 return dbg.nospace() << ')';
6400}
6401#endif // debug_stream && datestring
6402
6403/*! \fn size_t qHash(const QDateTime &key, size_t seed = 0)
6404 \qhashold{QHash}
6405 \since 5.0
6406*/
6407size_t qHash(const QDateTime &key, size_t seed)
6408{
6409 // Use to toMSecsSinceEpoch instead of individual qHash functions for
6410 // QDate/QTime/spec/offset because QDateTime::operator== converts both arguments
6411 // to the same timezone. If we don't, qHash would return different hashes for
6412 // two QDateTimes that are equivalent once converted to the same timezone.
6413 return key.isValid() ? qHash(key.toMSecsSinceEpoch(), seed) : seed;
6414}
6415
6416/*! \fn size_t qHash(QDate key, size_t seed = 0)
6417 \qhashold{QHash}
6418 \since 5.0
6419*/
6420size_t qHash(QDate key, size_t seed) noexcept
6421{
6422 return qHash(key.toJulianDay(), seed);
6423}
6424
6425/*! \fn size_t qHash(QTime key, size_t seed = 0)
6426 \qhashold{QHash}
6427 \since 5.0
6428*/
6429size_t qHash(QTime key, size_t seed) noexcept
6430{
6431 return qHash(key.msecsSinceStartOfDay(), seed);
6432}
6433
6434QT_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