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

source code of qtbase/src/corelib/time/qdatetime.cpp