1/****************************************************************************
2**
3** Copyright (C) 2020 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
79QT_BEGIN_NAMESPACE
80
81/*****************************************************************************
82 Date/Time Constants
83 *****************************************************************************/
84
85enum {
86 SECS_PER_DAY = 86400,
87 MSECS_PER_DAY = 86400000,
88 SECS_PER_HOUR = 3600,
89 MSECS_PER_HOUR = 3600000,
90 SECS_PER_MIN = 60,
91 MSECS_PER_MIN = 60000,
92 TIME_T_MAX = 2145916799, // int maximum 2037-12-31T23:59:59 UTC
93 JULIAN_DAY_FOR_EPOCH = 2440588 // result of julianDayFromDate(1970, 1, 1)
94};
95
96/*****************************************************************************
97 QDate static helper functions
98 *****************************************************************************/
99
100static inline QDate fixedDate(QCalendar::YearMonthDay &&parts, QCalendar cal)
101{
102 if ((parts.year < 0 && !cal.isProleptic()) || (parts.year == 0 && !cal.hasYearZero()))
103 return QDate();
104
105 parts.day = qMin(parts.day, cal.daysInMonth(parts.month, parts.year));
106 return cal.dateFromParts(parts);
107}
108
109static inline QDate fixedDate(QCalendar::YearMonthDay &&parts)
110{
111 if (parts.year) {
112 parts.day = qMin(parts.day, QGregorianCalendar::monthLength(parts.month, parts.year));
113 qint64 jd;
114 if (QGregorianCalendar::julianFromParts(parts.year, parts.month, parts.day, &jd))
115 return QDate::fromJulianDay(jd);
116 }
117 return QDate();
118}
119
120/*****************************************************************************
121 Date/Time formatting helper functions
122 *****************************************************************************/
123
124#if QT_CONFIG(textdate)
125static const char qt_shortMonthNames[][4] = {
126 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
127 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
128};
129
130static int qt_monthNumberFromShortName(QStringView shortName)
131{
132 for (unsigned int i = 0; i < sizeof(qt_shortMonthNames) / sizeof(qt_shortMonthNames[0]); ++i) {
133 if (shortName == QLatin1String(qt_shortMonthNames[i], 3))
134 return i + 1;
135 }
136 return -1;
137}
138static int qt_monthNumberFromShortName(const QString &shortName)
139{ return qt_monthNumberFromShortName(QStringView(shortName)); }
140
141static int fromShortMonthName(QStringView monthName, int year)
142{
143 // Assume that English monthnames are the default
144 int month = qt_monthNumberFromShortName(monthName);
145 if (month != -1)
146 return month;
147 // If English names can't be found, search the localized ones
148 for (int i = 1; i <= 12; ++i) {
149 if (monthName == QCalendar().monthName(QLocale::system(), i, year, QLocale::ShortFormat))
150 return i;
151 }
152 return -1;
153}
154#endif // textdate
155
156#if QT_CONFIG(datestring)
157struct ParsedRfcDateTime {
158 QDate date;
159 QTime time;
160 int utcOffset;
161};
162
163static ParsedRfcDateTime rfcDateImpl(const QString &s)
164{
165 ParsedRfcDateTime result;
166
167 // Matches "[ddd,] dd MMM yyyy[ hh:mm[:ss]] [±hhmm]" - correct RFC 822, 2822, 5322 format
168 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))?"));
169 if (s.indexOf(rex) == 0) {
170 const QStringList cap = rex.capturedTexts();
171 result.date = QDate(cap[3].toInt(), qt_monthNumberFromShortName(cap[2]), cap[1].toInt());
172 if (!cap[4].isEmpty())
173 result.time = QTime(cap[4].toInt(), cap[5].toInt(), cap[6].toInt());
174 const bool positiveOffset = (cap[7] == QLatin1String("+"));
175 const int hourOffset = cap[8].toInt();
176 const int minOffset = cap[9].toInt();
177 result.utcOffset = ((hourOffset * 60 + minOffset) * (positiveOffset ? 60 : -60));
178 } else {
179 // Matches "ddd MMM dd[ hh:mm:ss] yyyy [±hhmm]" - permissive RFC 850, 1036 (read only)
180 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))?"));
181 if (s.indexOf(rex) == 0) {
182 const QStringList cap = rex.capturedTexts();
183 result.date = QDate(cap[6].toInt(), qt_monthNumberFromShortName(cap[1]), cap[2].toInt());
184 if (!cap[3].isEmpty())
185 result.time = QTime(cap[3].toInt(), cap[4].toInt(), cap[5].toInt());
186 const bool positiveOffset = (cap[7] == QLatin1String("+"));
187 const int hourOffset = cap[8].toInt();
188 const int minOffset = cap[9].toInt();
189 result.utcOffset = ((hourOffset * 60 + minOffset) * (positiveOffset ? 60 : -60));
190 }
191 }
192
193 return result;
194}
195#endif // datestring
196
197// Return offset in [+-]HH:mm format
198static QString toOffsetString(Qt::DateFormat format, int offset)
199{
200 return QString::asprintf("%c%02d%s%02d",
201 offset >= 0 ? '+' : '-',
202 qAbs(offset) / SECS_PER_HOUR,
203 // Qt::ISODate puts : between the hours and minutes, but Qt:TextDate does not:
204 format == Qt::TextDate ? "" : ":",
205 (qAbs(offset) / 60) % 60);
206}
207
208#if QT_CONFIG(datestring)
209// Parse offset in [+-]HH[[:]mm] format
210static int fromOffsetString(QStringView offsetString, bool *valid) noexcept
211{
212 *valid = false;
213
214 const int size = offsetString.size();
215 if (size < 2 || size > 6)
216 return 0;
217
218 // sign will be +1 for a positive and -1 for a negative offset
219 int sign;
220
221 // First char must be + or -
222 const QChar signChar = offsetString.at(0);
223 if (signChar == QLatin1Char('+'))
224 sign = 1;
225 else if (signChar == QLatin1Char('-'))
226 sign = -1;
227 else
228 return 0;
229
230 // Split the hour and minute parts
231 const QStringView time = offsetString.mid(1);
232 qsizetype hhLen = time.indexOf(QLatin1Char(':'));
233 qsizetype mmIndex;
234 if (hhLen == -1)
235 mmIndex = hhLen = 2; // [+-]HHmm or [+-]HH format
236 else
237 mmIndex = hhLen + 1;
238
239 const QLocale C = QLocale::c();
240 const QStringView hhRef = time.left(qMin(hhLen, time.size()));
241 bool ok = false;
242 const int hour = C.toInt(hhRef, &ok);
243 if (!ok)
244 return 0;
245
246 const QStringView mmRef = time.mid(qMin(mmIndex, time.size()));
247 const int minute = mmRef.isEmpty() ? 0 : C.toInt(mmRef, &ok);
248 if (!ok || minute < 0 || minute > 59)
249 return 0;
250
251 *valid = true;
252 return sign * ((hour * 60) + minute) * 60;
253}
254#endif // datestring
255
256/*****************************************************************************
257 QDate member functions
258 *****************************************************************************/
259
260/*!
261 \since 4.5
262
263 \enum QDate::MonthNameType
264
265 This enum describes the types of the string representation used
266 for the month name.
267
268 \value DateFormat This type of name can be used for date-to-string formatting.
269 \value StandaloneFormat This type is used when you need to enumerate months or weekdays.
270 Usually standalone names are represented in singular forms with
271 capitalized first letter.
272*/
273
274/*!
275 \class QDate
276 \inmodule QtCore
277 \reentrant
278 \brief The QDate class provides date functions.
279
280 A QDate object represents a particular day, regardless of calendar,
281 locale or other settings used when creating it or supplied by the system.
282 It can report the year, month and day of the month that represent the
283 day with respect to the proleptic Gregorian calendar or any calendar supplied
284 as a QCalendar object.
285
286 A QDate object is typically created by giving the year, month, and day
287 numbers explicitly. Note that QDate interprets year numbers less than 100 as
288 presented, i.e., as years 1 through 99, without adding any offset. The
289 static function currentDate() creates a QDate object containing the date
290 read from the system clock. An explicit date can also be set using
291 setDate(). The fromString() function returns a QDate given a string and a
292 date format which is used to interpret the date within the string.
293
294 The year(), month(), and day() functions provide access to the year, month,
295 and day numbers. When more than one of these values is needed, it is more
296 efficient to call QCalendar::partsFromDate(), to save repeating (potentially
297 expensive) calendrical calculations.
298
299 Also, dayOfWeek() and dayOfYear() functions are provided. The same
300 information is provided in textual format by toString(). QLocale can map the
301 day numbers to names, QCalendar can map month numbers to names.
302
303 QDate provides a full set of operators to compare two QDate
304 objects where smaller means earlier, and larger means later.
305
306 You can increment (or decrement) a date by a given number of days
307 using addDays(). Similarly you can use addMonths() and addYears().
308 The daysTo() function returns the number of days between two
309 dates.
310
311 The daysInMonth() and daysInYear() functions return how many days there are
312 in this date's month and year, respectively. The isLeapYear() function
313 indicates whether a date is in a leap year. QCalendar can also supply this
314 information, in some cases more conveniently.
315
316 \section1 Remarks
317
318 \section2 No Year 0
319
320 In the Gregorian calendar, there is no year 0. Dates in that year are
321 considered invalid. The year -1 is the year "1 before Christ" or "1 before
322 common era." The day before 1 January 1 CE, QDate(1, 1, 1), is 31 December
323 1 BCE, QDate(-1, 12, 31). Various other calendars behave similarly; see
324 QCalendar::hasYearZero().
325
326 \section2 Range of Valid Dates
327
328 Dates are stored internally as a Julian Day number, an integer count of
329 every day in a contiguous range, with 24 November 4714 BCE in the Gregorian
330 calendar being Julian Day 0 (1 January 4713 BCE in the Julian calendar).
331 As well as being an efficient and accurate way of storing an absolute date,
332 it is suitable for converting a date into other calendar systems such as
333 Hebrew, Islamic or Chinese. The Julian Day number can be obtained using
334 QDate::toJulianDay() and can be set using QDate::fromJulianDay().
335
336 The range of Julian Day numbers that QDate can represent is, for technical
337 reasons, limited to between -784350574879 and 784354017364, which means from
338 before 2 billion BCE to after 2 billion CE. This is more than seven times as
339 wide as the range of dates a QDateTime can represent.
340
341 \sa QTime, QDateTime, QCalendar, QDateTime::YearRange, QDateEdit, QDateTimeEdit, QCalendarWidget
342*/
343
344/*!
345 \fn QDate::QDate()
346
347 Constructs a null date. Null dates are invalid.
348
349 \sa isNull(), isValid()
350*/
351
352/*!
353 Constructs a date with year \a y, month \a m and day \a d.
354
355 The date is understood in terms of the Gregorian calendar. If the specified
356 date is invalid, the date is not set and isValid() returns \c false.
357
358 \warning Years 1 to 99 are interpreted as is. Year 0 is invalid.
359
360 \sa isValid(), QCalendar::dateFromParts()
361*/
362
363QDate::QDate(int y, int m, int d)
364{
365 if (!QGregorianCalendar::julianFromParts(y, m, d, &jd))
366 jd = nullJd();
367}
368
369QDate::QDate(int y, int m, int d, QCalendar cal)
370{
371 *this = cal.dateFromParts(y, m, d);
372}
373
374/*!
375 \fn bool QDate::isNull() const
376
377 Returns \c true if the date is null; otherwise returns \c false. A null
378 date is invalid.
379
380 \note The behavior of this function is equivalent to isValid().
381
382 \sa isValid()
383*/
384
385/*!
386 \fn bool QDate::isValid() const
387
388 Returns \c true if this date is valid; otherwise returns \c false.
389
390 \sa isNull(), QCalendar::isDateValid()
391*/
392
393/*!
394 Returns the year of this date.
395
396 Uses \a cal as calendar, if supplied, else the Gregorian calendar.
397
398 Returns 0 if the date is invalid. For some calendars, dates before their
399 first year may all be invalid.
400
401 If using a calendar which has a year 0, check using isValid() if the return
402 is 0. Such calendars use negative year numbers in the obvious way, with
403 year 1 preceded by year 0, in turn preceded by year -1 and so on.
404
405 Some calendars, despite having no year 0, have a conventional numbering of
406 the years before their first year, counting backwards from 1. For example,
407 in the proleptic Gregorian calendar, successive years before 1 CE (the first
408 year) are identified as 1 BCE, 2 BCE, 3 BCE and so on. For such calendars,
409 negative year numbers are used to indicate these years before year 1, with
410 -1 indicating the year before 1.
411
412 \sa month(), day(), QCalendar::hasYearZero(), QCalendar::isProleptic(), QCalendar::partsFromDate()
413*/
414
415int QDate::year(QCalendar cal) const
416{
417 if (isValid()) {
418 const auto parts = cal.partsFromDate(*this);
419 if (parts.isValid())
420 return parts.year;
421 }
422 return 0;
423}
424
425/*!
426 \overload
427 */
428
429int QDate::year() const
430{
431 if (isValid()) {
432 const auto parts = QGregorianCalendar::partsFromJulian(jd);
433 if (parts.isValid())
434 return parts.year;
435 }
436 return 0;
437}
438
439/*!
440 Returns the month-number for the date.
441
442 Numbers the months of the year starting with 1 for the first. Uses \a cal
443 as calendar if supplied, else the Gregorian calendar, for which the month
444 numbering is as follows:
445
446 \list
447 \li 1 = "January"
448 \li 2 = "February"
449 \li 3 = "March"
450 \li 4 = "April"
451 \li 5 = "May"
452 \li 6 = "June"
453 \li 7 = "July"
454 \li 8 = "August"
455 \li 9 = "September"
456 \li 10 = "October"
457 \li 11 = "November"
458 \li 12 = "December"
459 \endlist
460
461 Returns 0 if the date is invalid. Note that some calendars may have more
462 than 12 months in some years.
463
464 \sa year(), day(), QCalendar::partsFromDate()
465*/
466
467int QDate::month(QCalendar cal) const
468{
469 if (isValid()) {
470 const auto parts = cal.partsFromDate(*this);
471 if (parts.isValid())
472 return parts.month;
473 }
474 return 0;
475}
476
477/*!
478 \overload
479 */
480
481int QDate::month() const
482{
483 if (isValid()) {
484 const auto parts = QGregorianCalendar::partsFromJulian(jd);
485 if (parts.isValid())
486 return parts.month;
487 }
488 return 0;
489}
490
491/*!
492 Returns the day of the month for this date.
493
494 Uses \a cal as calendar if supplied, else the Gregorian calendar (for which
495 the return ranges from 1 to 31). Returns 0 if the date is invalid.
496
497 \sa year(), month(), dayOfWeek(), QCalendar::partsFromDate()
498*/
499
500int QDate::day(QCalendar cal) const
501{
502 if (isValid()) {
503 const auto parts = cal.partsFromDate(*this);
504 if (parts.isValid())
505 return parts.day;
506 }
507 return 0;
508}
509
510/*!
511 \overload
512 */
513
514int QDate::day() const
515{
516 if (isValid()) {
517 const auto parts = QGregorianCalendar::partsFromJulian(jd);
518 if (parts.isValid())
519 return parts.day;
520 }
521 return 0;
522}
523
524/*!
525 Returns the weekday (1 = Monday to 7 = Sunday) for this date.
526
527 Uses \a cal as calendar if supplied, else the Gregorian calendar. Returns 0
528 if the date is invalid. Some calendars may give special meaning
529 (e.g. intercallary days) to values greater than 7.
530
531 \sa day(), dayOfYear(), QCalendar::dayOfWeek(), Qt::DayOfWeek
532*/
533
534int QDate::dayOfWeek(QCalendar cal) const
535{
536 if (isNull())
537 return 0;
538
539 return cal.dayOfWeek(*this);
540}
541
542/*!
543 \overload
544 */
545
546int QDate::dayOfWeek() const
547{
548 return isValid() ? QGregorianCalendar::weekDayOfJulian(jd) : 0;
549}
550
551/*!
552 Returns the day of the year (1 for the first day) for this date.
553
554 Uses \a cal as calendar if supplied, else the Gregorian calendar.
555 Returns 0 if either the date or the first day of its year is invalid.
556
557 \sa day(), dayOfWeek(), QCalendar::daysInYear()
558*/
559
560int QDate::dayOfYear(QCalendar cal) const
561{
562 if (isValid()) {
563 QDate firstDay = cal.dateFromParts(year(cal), 1, 1);
564 if (firstDay.isValid())
565 return firstDay.daysTo(*this) + 1;
566 }
567 return 0;
568}
569
570/*!
571 \overload
572 */
573
574int QDate::dayOfYear() const
575{
576 if (isValid()) {
577 qint64 first;
578 if (QGregorianCalendar::julianFromParts(year(), 1, 1, &first))
579 return jd - first + 1;
580 }
581 return 0;
582}
583
584/*!
585 Returns the number of days in the month for this date.
586
587 Uses \a cal as calendar if supplied, else the Gregorian calendar (for which
588 the result ranges from 28 to 31). Returns 0 if the date is invalid.
589
590 \sa day(), daysInYear(), QCalendar::daysInMonth(),
591 QCalendar::maximumDaysInMonth(), QCalendar::minimumDaysInMonth()
592*/
593
594int QDate::daysInMonth(QCalendar cal) const
595{
596 if (isValid()) {
597 const auto parts = cal.partsFromDate(*this);
598 if (parts.isValid())
599 return cal.daysInMonth(parts.month, parts.year);
600 }
601 return 0;
602}
603
604/*!
605 \overload
606 */
607
608int QDate::daysInMonth() const
609{
610 if (isValid()) {
611 const auto parts = QGregorianCalendar::partsFromJulian(jd);
612 if (parts.isValid())
613 return QGregorianCalendar::monthLength(parts.month, parts.year);
614 }
615 return 0;
616}
617
618/*!
619 Returns the number of days in the year for this date.
620
621 Uses \a cal as calendar if supplied, else the Gregorian calendar (for which
622 the result is 365 or 366). Returns 0 if the date is invalid.
623
624 \sa day(), daysInMonth(), QCalendar::daysInYear(), QCalendar::maximumMonthsInYear()
625*/
626
627int QDate::daysInYear(QCalendar cal) const
628{
629 if (isNull())
630 return 0;
631
632 return cal.daysInYear(year(cal));
633}
634
635/*!
636 \overload
637 */
638
639int QDate::daysInYear() const
640{
641 return isValid() ? QGregorianCalendar::leapTest(year()) ? 366 : 365 : 0;
642}
643
644/*!
645 Returns the ISO 8601 week number (1 to 53).
646
647 Returns 0 if the date is invalid. Otherwise, returns the week number for the
648 date. If \a yearNumber is not \nullptr (its default), stores the year as
649 *\a{yearNumber}.
650
651 In accordance with ISO 8601, each week falls in the year to which most of
652 its days belong, in the Gregorian calendar. As ISO 8601's week starts on
653 Monday, this is the year in which the week's Thursday falls. Most years have
654 52 weeks, but some have 53.
655
656 \note *\a{yearNumber} is not always the same as year(). For example, 1
657 January 2000 has week number 52 in the year 1999, and 31 December
658 2002 has week number 1 in the year 2003.
659
660 \sa isValid()
661*/
662
663int QDate::weekNumber(int *yearNumber) const
664{
665 if (!isValid())
666 return 0;
667
668 // This could be replaced by use of QIso8601Calendar, once we implement it.
669 // The Thursday of the same week determines our answer:
670 QDate thursday(addDays(4 - dayOfWeek()));
671 int year = thursday.year();
672 // Week n's Thurs's DOY has 1 <= DOY - 7*(n-1) < 8, so 0 <= DOY + 6 - 7*n < 7:
673 int week = (thursday.dayOfYear() + 6) / 7;
674
675 if (yearNumber)
676 *yearNumber = year;
677 return week;
678}
679
680static bool inDateTimeRange(qint64 jd, bool start)
681{
682 using Bounds = std::numeric_limits<qint64>;
683 if (jd < Bounds::min() + JULIAN_DAY_FOR_EPOCH)
684 return false;
685 jd -= JULIAN_DAY_FOR_EPOCH;
686 const qint64 maxDay = Bounds::max() / MSECS_PER_DAY;
687 const qint64 minDay = Bounds::min() / MSECS_PER_DAY - 1;
688 // (Divisions rounded towards zero, as MSECS_PER_DAY has factors other than two.)
689 // Range includes start of last day and end of first:
690 if (start)
691 return jd > minDay && jd <= maxDay;
692 return jd >= minDay && jd < maxDay;
693}
694
695static QDateTime toEarliest(QDate day, const QDateTime &form)
696{
697 const Qt::TimeSpec spec = form.timeSpec();
698 const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0;
699#if QT_CONFIG(timezone)
700 QTimeZone zone;
701 if (spec == Qt::TimeZone)
702 zone = form.timeZone();
703#endif
704 auto moment = [=](QTime time) {
705 switch (spec) {
706 case Qt::OffsetFromUTC: return QDateTime(day, time, spec, offset);
707#if QT_CONFIG(timezone)
708 case Qt::TimeZone: return QDateTime(day, time, zone);
709#endif
710 default: return QDateTime(day, time, spec);
711 }
712 };
713 // Longest routine time-zone transition is 2 hours:
714 QDateTime when = moment(QTime(2, 0));
715 if (!when.isValid()) {
716 // Noon should be safe ...
717 when = moment(QTime(12, 0));
718 if (!when.isValid()) {
719 // ... unless it's a 24-hour jump (moving the date-line)
720 when = moment(QTime(23, 59, 59, 999));
721 if (!when.isValid())
722 return QDateTime();
723 }
724 }
725 int high = when.time().msecsSinceStartOfDay() / 60000;
726 int low = 0;
727 // Binary chop to the right minute
728 while (high > low + 1) {
729 int mid = (high + low) / 2;
730 QDateTime probe = moment(QTime(mid / 60, mid % 60));
731 if (probe.isValid() && probe.date() == day) {
732 high = mid;
733 when = probe;
734 } else {
735 low = mid;
736 }
737 }
738 return when;
739}
740
741/*!
742 \since 5.14
743 \fn QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const
744 \fn QDateTime QDate::startOfDay(const QTimeZone &zone) const
745
746 Returns the start-moment of the day. Usually, this shall be midnight at the
747 start of the day: however, if a time-zone transition causes the given date
748 to skip over that midnight (e.g. a DST spring-forward skipping from the end
749 of the previous day to 01:00 of the new day), the actual earliest time in
750 the day is returned. This can only arise when the start-moment is specified
751 in terms of a time-zone (by passing its QTimeZone as \a zone) or in terms of
752 local time (by passing Qt::LocalTime as \a spec; this is its default).
753
754 The \a offsetSeconds is ignored unless \a spec is Qt::OffsetFromUTC, when it
755 gives the implied zone's offset from UTC. As UTC and such zones have no
756 transitions, the start of the day is QTime(0, 0) in these cases.
757
758 In the rare case of a date that was entirely skipped (this happens when a
759 zone east of the international date-line switches to being west of it), the
760 return shall be invalid. Passing Qt::TimeZone as \a spec (instead of
761 passing a QTimeZone) or passing an invalid time-zone as \a zone will also
762 produce an invalid result, as shall dates that start outside the range
763 representable by QDateTime.
764
765 \sa endOfDay()
766*/
767QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const
768{
769 if (!inDateTimeRange(jd, true))
770 return QDateTime();
771
772 switch (spec) {
773 case Qt::TimeZone: // should pass a QTimeZone instead of Qt::TimeZone
774 qWarning() << "Called QDate::startOfDay(Qt::TimeZone) on" << *this;
775 return QDateTime();
776 case Qt::OffsetFromUTC:
777 case Qt::UTC:
778 return QDateTime(*this, QTime(0, 0), spec, offsetSeconds);
779
780 case Qt::LocalTime:
781 if (offsetSeconds)
782 qWarning("Ignoring offset (%d seconds) passed with Qt::LocalTime", offsetSeconds);
783 break;
784 }
785 QDateTime when(*this, QTime(0, 0), spec);
786 if (!when.isValid())
787 when = toEarliest(*this, when);
788
789 return when.isValid() ? when : QDateTime();
790}
791
792#if QT_CONFIG(timezone)
793/*!
794 \overload
795 \since 5.14
796*/
797QDateTime QDate::startOfDay(const QTimeZone &zone) const
798{
799 if (!inDateTimeRange(jd, true) || !zone.isValid())
800 return QDateTime();
801
802 QDateTime when(*this, QTime(0, 0), zone);
803 if (when.isValid())
804 return when;
805
806 // The start of the day must have fallen in a spring-forward's gap; find the spring-forward:
807 if (zone.hasTransitions()) {
808 QTimeZone::OffsetData tran = zone.previousTransition(QDateTime(*this, QTime(23, 59, 59, 999), zone));
809 const QDateTime &at = tran.atUtc.toTimeZone(zone);
810 if (at.isValid() && at.date() == *this)
811 return at;
812 }
813
814 when = toEarliest(*this, when);
815 return when.isValid() ? when : QDateTime();
816}
817#endif // timezone
818
819static QDateTime toLatest(QDate day, const QDateTime &form)
820{
821 const Qt::TimeSpec spec = form.timeSpec();
822 const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0;
823#if QT_CONFIG(timezone)
824 QTimeZone zone;
825 if (spec == Qt::TimeZone)
826 zone = form.timeZone();
827#endif
828 auto moment = [=](QTime time) {
829 switch (spec) {
830 case Qt::OffsetFromUTC: return QDateTime(day, time, spec, offset);
831#if QT_CONFIG(timezone)
832 case Qt::TimeZone: return QDateTime(day, time, zone);
833#endif
834 default: return QDateTime(day, time, spec);
835 }
836 };
837 // Longest routine time-zone transition is 2 hours:
838 QDateTime when = moment(QTime(21, 59, 59, 999));
839 if (!when.isValid()) {
840 // Noon should be safe ...
841 when = moment(QTime(12, 0));
842 if (!when.isValid()) {
843 // ... unless it's a 24-hour jump (moving the date-line)
844 when = moment(QTime(0, 0));
845 if (!when.isValid())
846 return QDateTime();
847 }
848 }
849 int high = 24 * 60;
850 int low = when.time().msecsSinceStartOfDay() / 60000;
851 // Binary chop to the right minute
852 while (high > low + 1) {
853 int mid = (high + low) / 2;
854 QDateTime probe = moment(QTime(mid / 60, mid % 60, 59, 999));
855 if (probe.isValid() && probe.date() == day) {
856 low = mid;
857 when = probe;
858 } else {
859 high = mid;
860 }
861 }
862 return when;
863}
864
865/*!
866 \since 5.14
867 \fn QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const
868 \fn QDateTime QDate::endOfDay(const QTimeZone &zone) const
869
870 Returns the end-moment of the day. Usually, this is one millisecond before
871 the midnight at the end of the day: however, if a time-zone transition
872 causes the given date to skip over that midnight (e.g. a DST spring-forward
873 skipping from just before 23:00 to the start of the next day), the actual
874 latest time in the day is returned. This can only arise when the
875 start-moment is specified in terms of a time-zone (by passing its QTimeZone
876 as \a zone) or in terms of local time (by passing Qt::LocalTime as \a spec;
877 this is its default).
878
879 The \a offsetSeconds is ignored unless \a spec is Qt::OffsetFromUTC, when it
880 gives the implied zone's offset from UTC. As UTC and such zones have no
881 transitions, the end of the day is QTime(23, 59, 59, 999) in these cases.
882
883 In the rare case of a date that was entirely skipped (this happens when a
884 zone east of the international date-line switches to being west of it), the
885 return shall be invalid. Passing Qt::TimeZone as \a spec (instead of
886 passing a QTimeZone) will also produce an invalid result, as shall dates
887 that end outside the range representable by QDateTime.
888
889 \sa startOfDay()
890*/
891QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const
892{
893 if (!inDateTimeRange(jd, false))
894 return QDateTime();
895
896 switch (spec) {
897 case Qt::TimeZone: // should pass a QTimeZone instead of Qt::TimeZone
898 qWarning() << "Called QDate::endOfDay(Qt::TimeZone) on" << *this;
899 return QDateTime();
900 case Qt::UTC:
901 case Qt::OffsetFromUTC:
902 return QDateTime(*this, QTime(23, 59, 59, 999), spec, offsetSeconds);
903
904 case Qt::LocalTime:
905 if (offsetSeconds)
906 qWarning("Ignoring offset (%d seconds) passed with Qt::LocalTime", offsetSeconds);
907 break;
908 }
909 QDateTime when(*this, QTime(23, 59, 59, 999), spec);
910 if (!when.isValid())
911 when = toLatest(*this, when);
912 return when.isValid() ? when : QDateTime();
913}
914
915#if QT_CONFIG(timezone)
916/*!
917 \overload
918 \since 5.14
919*/
920QDateTime QDate::endOfDay(const QTimeZone &zone) const
921{
922 if (!inDateTimeRange(jd, false) || !zone.isValid())
923 return QDateTime();
924
925 QDateTime when(*this, QTime(23, 59, 59, 999), zone);
926 if (when.isValid())
927 return when;
928
929 // The end of the day must have fallen in a spring-forward's gap; find the spring-forward:
930 if (zone.hasTransitions()) {
931 QTimeZone::OffsetData tran = zone.nextTransition(QDateTime(*this, QTime(0, 0), zone));
932 const QDateTime &at = tran.atUtc.toTimeZone(zone);
933 if (at.isValid() && at.date() == *this)
934 return at;
935 }
936
937 when = toLatest(*this, when);
938 return when.isValid() ? when : QDateTime();
939}
940#endif // timezone
941
942#if QT_DEPRECATED_SINCE(5, 11) && QT_CONFIG(textdate)
943
944/*!
945 \since 4.5
946 \deprecated
947
948 Returns the short name of the \a month for the representation specified
949 by \a type.
950
951 The months are enumerated using the following convention:
952
953 \list
954 \li 1 = "Jan"
955 \li 2 = "Feb"
956 \li 3 = "Mar"
957 \li 4 = "Apr"
958 \li 5 = "May"
959 \li 6 = "Jun"
960 \li 7 = "Jul"
961 \li 8 = "Aug"
962 \li 9 = "Sep"
963 \li 10 = "Oct"
964 \li 11 = "Nov"
965 \li 12 = "Dec"
966 \endlist
967
968 The month names will be localized according to the system's
969 locale settings, i.e. using QLocale::system().
970
971 Returns an empty string if the date is invalid.
972
973 \sa toString(), longMonthName(), shortDayName(), longDayName()
974*/
975
976QString QDate::shortMonthName(int month, QDate::MonthNameType type)
977{
978 switch (type) {
979 case QDate::DateFormat:
980 return QCalendar().monthName(QLocale::system(), month,
981 QCalendar::Unspecified, QLocale::ShortFormat);
982 case QDate::StandaloneFormat:
983 return QCalendar().standaloneMonthName(QLocale::system(), month,
984 QCalendar::Unspecified, QLocale::ShortFormat);
985 }
986 return QString();
987}
988
989/*!
990 \since 4.5
991 \deprecated
992
993 Returns the long name of the \a month for the representation specified
994 by \a type.
995
996 The months are enumerated using the following convention:
997
998 \list
999 \li 1 = "January"
1000 \li 2 = "February"
1001 \li 3 = "March"
1002 \li 4 = "April"
1003 \li 5 = "May"
1004 \li 6 = "June"
1005 \li 7 = "July"
1006 \li 8 = "August"
1007 \li 9 = "September"
1008 \li 10 = "October"
1009 \li 11 = "November"
1010 \li 12 = "December"
1011 \endlist
1012
1013 The month names will be localized according to the system's
1014 locale settings, i.e. using QLocale::system().
1015
1016 Returns an empty string if the date is invalid.
1017
1018 \sa toString(), shortMonthName(), shortDayName(), longDayName()
1019*/
1020
1021QString QDate::longMonthName(int month, MonthNameType type)
1022{
1023 switch (type) {
1024 case QDate::DateFormat:
1025 return QCalendar().monthName(QLocale::system(), month,
1026 QCalendar::Unspecified, QLocale::LongFormat);
1027 case QDate::StandaloneFormat:
1028 return QCalendar().standaloneMonthName(QLocale::system(), month,
1029 QCalendar::Unspecified, QLocale::LongFormat);
1030 }
1031 return QString();
1032}
1033
1034/*!
1035 \since 4.5
1036 \deprecated
1037
1038 Returns the short name of the \a weekday for the representation specified
1039 by \a type.
1040
1041 The days are enumerated using the following convention:
1042
1043 \list
1044 \li 1 = "Mon"
1045 \li 2 = "Tue"
1046 \li 3 = "Wed"
1047 \li 4 = "Thu"
1048 \li 5 = "Fri"
1049 \li 6 = "Sat"
1050 \li 7 = "Sun"
1051 \endlist
1052
1053 The day names will be localized according to the system's
1054 locale settings, i.e. using QLocale::system().
1055
1056 Returns an empty string if the date is invalid.
1057
1058 \sa toString(), shortMonthName(), longMonthName(), longDayName()
1059*/
1060
1061QString QDate::shortDayName(int weekday, MonthNameType type)
1062{
1063 switch (type) {
1064 case QDate::DateFormat:
1065 return QLocale::system().dayName(weekday, QLocale::ShortFormat);
1066 case QDate::StandaloneFormat:
1067 return QLocale::system().standaloneDayName(weekday, QLocale::ShortFormat);
1068 }
1069 return QString();
1070}
1071
1072/*!
1073 \since 4.5
1074 \deprecated
1075
1076 Returns the long name of the \a weekday for the representation specified
1077 by \a type.
1078
1079 The days are enumerated using the following convention:
1080
1081 \list
1082 \li 1 = "Monday"
1083 \li 2 = "Tuesday"
1084 \li 3 = "Wednesday"
1085 \li 4 = "Thursday"
1086 \li 5 = "Friday"
1087 \li 6 = "Saturday"
1088 \li 7 = "Sunday"
1089 \endlist
1090
1091 The day names will be localized according to the system's
1092 locale settings, i.e. using QLocale::system().
1093
1094 Returns an empty string if the date is invalid.
1095
1096 \sa toString(), shortDayName(), shortMonthName(), longMonthName()
1097*/
1098
1099QString QDate::longDayName(int weekday, MonthNameType type)
1100{
1101 switch (type) {
1102 case QDate::DateFormat:
1103 return QLocale::system().dayName(weekday, QLocale::LongFormat);
1104 case QDate::StandaloneFormat:
1105 return QLocale::system().standaloneDayName(weekday, QLocale::LongFormat);
1106 }
1107 return QString();
1108}
1109#endif // textdate && deprecated
1110
1111#if QT_CONFIG(datestring) // depends on, so implies, textdate
1112
1113static QString toStringTextDate(QDate date)
1114{
1115 if (date.isValid()) {
1116 QCalendar cal; // Always Gregorian
1117 const auto parts = cal.partsFromDate(date);
1118 if (parts.isValid()) {
1119 const QLatin1Char sp(' ');
1120 return QLocale::system().dayName(cal.dayOfWeek(date), QLocale::ShortFormat) + sp
1121 + cal.monthName(QLocale::system(), parts.month, parts.year, QLocale::ShortFormat)
1122 + sp + QString::number(parts.day) + sp + QString::number(parts.year);
1123 }
1124 }
1125 return QString();
1126}
1127
1128static QString toStringIsoDate(QDate date)
1129{
1130 const auto parts = QCalendar().partsFromDate(date);
1131 if (parts.isValid() && parts.year >= 0 && parts.year <= 9999)
1132 return QString::asprintf("%04d-%02d-%02d", parts.year, parts.month, parts.day);
1133 return QString();
1134}
1135
1136/*!
1137 \overload
1138
1139 Returns the date as a string. The \a format parameter determines the format
1140 of the string.
1141
1142 If the \a format is Qt::TextDate, the string is formatted in the default
1143 way. The day and month names will be localized names using the system
1144 locale, i.e. QLocale::system(). An example of this formatting
1145 is "Sat May 20 1995".
1146
1147 If the \a format is Qt::ISODate, the string format corresponds
1148 to the ISO 8601 extended specification for representations of
1149 dates and times, taking the form yyyy-MM-dd, where yyyy is the
1150 year, MM is the month of the year (between 01 and 12), and dd is
1151 the day of the month between 01 and 31.
1152
1153 The \a format options Qt::SystemLocaleDate, Qt::SystemLocaleShortDate and
1154 Qt::SystemLocaleLongDate shall be removed in Qt 6. Their use should be
1155 replaced with
1156 \l {QLocale::toString()}{QLocale::system().toString(date, QLocale::ShortFormat)} or
1157 \l {QLocale::toString()}{QLocale::system().toString(date, QLocale::LongFormat)}.
1158
1159 The \a format options Qt::LocaleDate, Qt::DefaultLocaleShortDate and
1160 Qt::DefaultLocaleLongDate shall be removed in Qt 6. Their use should be
1161 replaced with
1162 \l {QLocale::toString()}{QLocale().toString(date, QLocale::ShortFormat)} or
1163 \l {QLocale::toString()}{QLocale().toString(date, QLocale::LongFormat)}.
1164
1165 If the \a format is Qt::RFC2822Date, the string is formatted in
1166 an \l{RFC 2822} compatible way. An example of this formatting is
1167 "20 May 1995".
1168
1169 If the date is invalid, an empty string will be returned.
1170
1171 \warning The Qt::ISODate format is only valid for years in the
1172 range 0 to 9999.
1173
1174 \sa fromString(), QLocale::toString()
1175*/
1176QString QDate::toString(Qt::DateFormat format) const
1177{
1178 if (!isValid())
1179 return QString();
1180
1181 switch (format) {
1182#if QT_DEPRECATED_SINCE(5, 15)
1183QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
1184 case Qt::SystemLocaleDate:
1185 case Qt::SystemLocaleShortDate:
1186 return QLocale::system().toString(*this, QLocale::ShortFormat);
1187 case Qt::SystemLocaleLongDate:
1188 return QLocale::system().toString(*this, QLocale::LongFormat);
1189 case Qt::LocaleDate:
1190 case Qt::DefaultLocaleShortDate:
1191 return QLocale().toString(*this, QLocale::ShortFormat);
1192 case Qt::DefaultLocaleLongDate:
1193 return QLocale().toString(*this, QLocale::LongFormat);
1194QT_WARNING_POP
1195#endif // 5.15
1196 case Qt::RFC2822Date:
1197 return QLocale::c().toString(*this, QStringView(u"dd MMM yyyy"));
1198 default:
1199 case Qt::TextDate:
1200 return toStringTextDate(*this);
1201 case Qt::ISODate:
1202 case Qt::ISODateWithMs:
1203 // No calendar dependence
1204 return toStringIsoDate(*this);
1205 }
1206}
1207
1208#if QT_DEPRECATED_SINCE(5, 15)
1209QString QDate::toString(Qt::DateFormat format, QCalendar cal) const
1210{
1211 if (!isValid())
1212 return QString();
1213
1214 switch (format) {
1215QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
1216 case Qt::SystemLocaleDate:
1217 case Qt::SystemLocaleShortDate:
1218 return QLocale::system().toString(*this, QLocale::ShortFormat, cal);
1219 case Qt::SystemLocaleLongDate:
1220 return QLocale::system().toString(*this, QLocale::LongFormat, cal);
1221 case Qt::LocaleDate:
1222 case Qt::DefaultLocaleShortDate:
1223 return QLocale().toString(*this, QLocale::ShortFormat, cal);
1224 case Qt::DefaultLocaleLongDate:
1225 return QLocale().toString(*this, QLocale::LongFormat, cal);
1226QT_WARNING_POP
1227 case Qt::RFC2822Date:
1228 return QLocale::c().toString(*this, QStringView(u"dd MMM yyyy"), cal);
1229 default:
1230 case Qt::TextDate:
1231 return toStringTextDate(*this);
1232 case Qt::ISODate:
1233 case Qt::ISODateWithMs:
1234 // No calendar dependence
1235 return toStringIsoDate(*this);
1236 }
1237}
1238#endif // 5.15
1239
1240/*!
1241 \fn QString QDate::toString(const QString &format) const
1242 \fn QString QDate::toString(const QString &format, QCalendar cal) const
1243 \fn QString QDate::toString(QStringView format) const
1244 \fn QString QDate::toString(QStringView format, QCalendar cal) const
1245
1246 Returns the date as a string. The \a format parameter determines the format
1247 of the result string. If \a cal is supplied, it determines the calendar used
1248 to represent the date; it defaults to Gregorian.
1249
1250 These expressions may be used:
1251
1252 \table
1253 \header \li Expression \li Output
1254 \row \li d \li The day as a number without a leading zero (1 to 31)
1255 \row \li dd \li The day as a number with a leading zero (01 to 31)
1256 \row \li ddd
1257 \li The abbreviated localized day name (e.g. 'Mon' to 'Sun').
1258 Uses the system locale to localize the name, i.e. QLocale::system().
1259 \row \li dddd
1260 \li The long localized day name (e.g. 'Monday' to 'Sunday').
1261 Uses the system locale to localize the name, i.e. QLocale::system().
1262 \row \li M \li The month as a number without a leading zero (1 to 12)
1263 \row \li MM \li The month as a number with a leading zero (01 to 12)
1264 \row \li MMM
1265 \li The abbreviated localized month name (e.g. 'Jan' to 'Dec').
1266 Uses the system locale to localize the name, i.e. QLocale::system().
1267 \row \li MMMM
1268 \li The long localized month name (e.g. 'January' to 'December').
1269 Uses the system locale to localize the name, i.e. QLocale::system().
1270 \row \li yy \li The year as a two digit number (00 to 99)
1271 \row \li yyyy \li The year as a four digit number. If the year is negative,
1272 a minus sign is prepended, making five characters.
1273 \endtable
1274
1275 Any sequence of characters enclosed in single quotes will be included
1276 verbatim in the output string (stripped of the quotes), even if it contains
1277 formatting characters. Two consecutive single quotes ("''") are replaced by
1278 a single quote in the output. All other characters in the format string are
1279 included verbatim in the output string.
1280
1281 Formats without separators (e.g. "ddMM") are supported but must be used with
1282 care, as the resulting strings aren't always reliably readable (e.g. if "dM"
1283 produces "212" it could mean either the 2nd of December or the 21st of
1284 February).
1285
1286 Example format strings (assuming that the QDate is the 20 July
1287 1969):
1288
1289 \table
1290 \header \li Format \li Result
1291 \row \li dd.MM.yyyy \li 20.07.1969
1292 \row \li ddd MMMM d yy \li Sun July 20 69
1293 \row \li 'The day is' dddd \li The day is Sunday
1294 \endtable
1295
1296 If the datetime is invalid, an empty string will be returned.
1297
1298 \note If localized month and day names are desired, please switch to using
1299 QLocale::system().toString() as QDate methods shall change to use English (C
1300 locale) names at Qt 6.
1301
1302 \sa fromString(), QDateTime::toString(), QTime::toString(), QLocale::toString()
1303
1304*/
1305QString QDate::toString(QStringView format) const
1306{
1307 return toString(format, QCalendar());
1308}
1309
1310QString QDate::toString(QStringView format, QCalendar cal) const
1311{
1312 return QLocale::system().toString(*this, format, cal); // QLocale::c() ### Qt6
1313}
1314
1315#if QT_STRINGVIEW_LEVEL < 2
1316QString QDate::toString(const QString &format) const
1317{
1318 return toString(qToStringViewIgnoringNull(format), QCalendar());
1319}
1320
1321QString QDate::toString(const QString &format, QCalendar cal) const
1322{
1323 return toString(qToStringViewIgnoringNull(format), cal);
1324}
1325#endif
1326
1327#endif // datestring
1328
1329/*!
1330 \fn bool QDate::setYMD(int y, int m, int d)
1331
1332 \deprecated in 5.0, use setDate() instead.
1333
1334 Sets the date's year \a y, month \a m, and day \a d.
1335
1336 If \a y is in the range 0 to 99, it is interpreted as 1900 to
1337 1999.
1338 Returns \c false if the date is invalid.
1339
1340 Use setDate() instead.
1341*/
1342
1343/*!
1344 \since 4.2
1345
1346 Sets this to represent the date, in the Gregorian calendar, with the given
1347 \a year, \a month and \a day numbers. Returns true if the resulting date is
1348 valid, otherwise it sets this to represent an invalid date and returns
1349 false.
1350
1351 \sa isValid(), QCalendar::dateFromParts()
1352*/
1353bool QDate::setDate(int year, int month, int day)
1354{
1355 if (QGregorianCalendar::julianFromParts(year, month, day, &jd))
1356 return true;
1357
1358 jd = nullJd();
1359 return false;
1360}
1361
1362/*!
1363 \since 5.14
1364
1365 Sets this to represent the date, in the given calendar \a cal, with the
1366 given \a year, \a month and \a day numbers. Returns true if the resulting
1367 date is valid, otherwise it sets this to represent an invalid date and
1368 returns false.
1369
1370 \sa isValid(), QCalendar::dateFromParts()
1371*/
1372
1373bool QDate::setDate(int year, int month, int day, QCalendar cal)
1374{
1375 *this = QDate(year, month, day, cal);
1376 return isValid();
1377}
1378
1379/*!
1380 \since 4.5
1381
1382 Extracts the date's year, month, and day, and assigns them to
1383 *\a year, *\a month, and *\a day. The pointers may be null.
1384
1385 Returns 0 if the date is invalid.
1386
1387 \note In Qt versions prior to 5.7, this function is marked as non-\c{const}.
1388
1389 \sa year(), month(), day(), isValid(), QCalendar::partsFromDate()
1390*/
1391void QDate::getDate(int *year, int *month, int *day) const
1392{
1393 QCalendar::YearMonthDay parts; // invalid by default
1394 if (isValid())
1395 parts = QGregorianCalendar::partsFromJulian(jd);
1396
1397 const bool ok = parts.isValid();
1398 if (year)
1399 *year = ok ? parts.year : 0;
1400 if (month)
1401 *month = ok ? parts.month : 0;
1402 if (day)
1403 *day = ok ? parts.day : 0;
1404}
1405
1406#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1407/*!
1408 \overload
1409 \internal
1410*/
1411void QDate::getDate(int *year, int *month, int *day)
1412{
1413 qAsConst(*this).getDate(year, month, day);
1414}
1415#endif // < Qt 6
1416
1417/*!
1418 Returns a QDate object containing a date \a ndays later than the
1419 date of this object (or earlier if \a ndays is negative).
1420
1421 Returns a null date if the current date is invalid or the new date is
1422 out of range.
1423
1424 \sa addMonths(), addYears(), daysTo()
1425*/
1426
1427QDate QDate::addDays(qint64 ndays) const
1428{
1429 if (isNull())
1430 return QDate();
1431
1432 // Due to limits on minJd() and maxJd() we know that any overflow
1433 // will be invalid and caught by fromJulianDay().
1434 return fromJulianDay(jd + ndays);
1435}
1436
1437/*!
1438 Returns a QDate object containing a date \a nmonths later than the
1439 date of this object (or earlier if \a nmonths is negative).
1440
1441 Uses \a cal as calendar, if supplied, else the Gregorian calendar.
1442
1443 \note If the ending day/month combination does not exist in the resulting
1444 month/year, this function will return a date that is the latest valid date
1445 in the selected month.
1446
1447 \sa addDays(), addYears()
1448*/
1449
1450QDate QDate::addMonths(int nmonths, QCalendar cal) const
1451{
1452 if (!isValid())
1453 return QDate();
1454
1455 if (nmonths == 0)
1456 return *this;
1457
1458 auto parts = cal.partsFromDate(*this);
1459
1460 if (!parts.isValid())
1461 return QDate();
1462 Q_ASSERT(parts.year || cal.hasYearZero());
1463
1464 parts.month += nmonths;
1465 while (parts.month <= 0) {
1466 if (--parts.year || cal.hasYearZero())
1467 parts.month += cal.monthsInYear(parts.year);
1468 }
1469 int count = cal.monthsInYear(parts.year);
1470 while (parts.month > count) {
1471 parts.month -= count;
1472 count = (++parts.year || cal.hasYearZero()) ? cal.monthsInYear(parts.year) : 0;
1473 }
1474
1475 return fixedDate(std::move(parts), cal);
1476}
1477
1478/*!
1479 \overload
1480*/
1481
1482QDate QDate::addMonths(int nmonths) const
1483{
1484 if (isNull())
1485 return QDate();
1486
1487 if (nmonths == 0)
1488 return *this;
1489
1490 auto parts = QGregorianCalendar::partsFromJulian(jd);
1491
1492 if (!parts.isValid())
1493 return QDate();
1494 Q_ASSERT(parts.year);
1495
1496 parts.month += nmonths;
1497 while (parts.month <= 0) {
1498 if (--parts.year) // skip over year 0
1499 parts.month += 12;
1500 }
1501 while (parts.month > 12) {
1502 parts.month -= 12;
1503 if (!++parts.year) // skip over year 0
1504 ++parts.year;
1505 }
1506
1507 return fixedDate(std::move(parts));
1508}
1509
1510/*!
1511 Returns a QDate object containing a date \a nyears later than the
1512 date of this object (or earlier if \a nyears is negative).
1513
1514 Uses \a cal as calendar, if supplied, else the Gregorian calendar.
1515
1516 \note If the ending day/month combination does not exist in the resulting
1517 year (e.g., for the Gregorian calendar, if the date was Feb 29 and the final
1518 year is not a leap year), this function will return a date that is the
1519 latest valid date in the given month (in the example, Feb 28).
1520
1521 \sa addDays(), addMonths()
1522*/
1523
1524QDate QDate::addYears(int nyears, QCalendar cal) const
1525{
1526 if (!isValid())
1527 return QDate();
1528
1529 auto parts = cal.partsFromDate(*this);
1530 if (!parts.isValid())
1531 return QDate();
1532
1533 int old_y = parts.year;
1534 parts.year += nyears;
1535
1536 // If we just crossed (or hit) a missing year zero, adjust year by +/- 1:
1537 if (!cal.hasYearZero() && ((old_y > 0) != (parts.year > 0) || !parts.year))
1538 parts.year += nyears > 0 ? +1 : -1;
1539
1540 return fixedDate(std::move(parts), cal);
1541}
1542
1543/*!
1544 \overload
1545*/
1546
1547QDate QDate::addYears(int nyears) const
1548{
1549 if (isNull())
1550 return QDate();
1551
1552 auto parts = QGregorianCalendar::partsFromJulian(jd);
1553 if (!parts.isValid())
1554 return QDate();
1555
1556 int old_y = parts.year;
1557 parts.year += nyears;
1558
1559 // If we just crossed (or hit) a missing year zero, adjust year by +/- 1:
1560 if ((old_y > 0) != (parts.year > 0) || !parts.year)
1561 parts.year += nyears > 0 ? +1 : -1;
1562
1563 return fixedDate(std::move(parts));
1564}
1565
1566/*!
1567 Returns the number of days from this date to \a d (which is
1568 negative if \a d is earlier than this date).
1569
1570 Returns 0 if either date is invalid.
1571
1572 Example:
1573 \snippet code/src_corelib_tools_qdatetime.cpp 0
1574
1575 \sa addDays()
1576*/
1577
1578qint64 QDate::daysTo(const QDate &d) const
1579{
1580 if (isNull() || d.isNull())
1581 return 0;
1582
1583 // Due to limits on minJd() and maxJd() we know this will never overflow
1584 return d.jd - jd;
1585}
1586
1587
1588/*!
1589 \fn bool QDate::operator==(const QDate &d) const
1590
1591 Returns \c true if this date and \a d represent the same day, otherwise
1592 \c false.
1593*/
1594
1595/*!
1596 \fn bool QDate::operator!=(const QDate &d) const
1597
1598 Returns \c true if this date is different from \a d; otherwise
1599 returns \c false.
1600
1601 \sa operator==()
1602*/
1603
1604/*!
1605 \fn bool QDate::operator<(const QDate &d) const
1606
1607 Returns \c true if this date is earlier than \a d; otherwise returns
1608 false.
1609*/
1610
1611/*!
1612 \fn bool QDate::operator<=(const QDate &d) const
1613
1614 Returns \c true if this date is earlier than or equal to \a d;
1615 otherwise returns \c false.
1616*/
1617
1618/*!
1619 \fn bool QDate::operator>(const QDate &d) const
1620
1621 Returns \c true if this date is later than \a d; otherwise returns
1622 false.
1623*/
1624
1625/*!
1626 \fn bool QDate::operator>=(const QDate &d) const
1627
1628 Returns \c true if this date is later than or equal to \a d;
1629 otherwise returns \c false.
1630*/
1631
1632/*!
1633 \fn QDate::currentDate()
1634 Returns the current date, as reported by the system clock.
1635
1636 \sa QTime::currentTime(), QDateTime::currentDateTime()
1637*/
1638
1639#if QT_CONFIG(datestring) // depends on, so implies, textdate
1640namespace {
1641
1642struct ParsedInt { int value = 0; bool ok = false; };
1643
1644/*
1645 /internal
1646
1647 Read an int that must be the whole text. QStringRef::toInt() will ignore
1648 spaces happily; but ISO date format should not.
1649*/
1650ParsedInt readInt(QStringView text)
1651{
1652 ParsedInt result;
1653 for (const auto &ch : text) {
1654 if (ch.isSpace())
1655 return result;
1656 }
1657 result.value = QLocale::c().toInt(text, &result.ok);
1658 return result;
1659}
1660
1661}
1662
1663/*!
1664 Returns the QDate represented by the \a string, using the
1665 \a format given, or an invalid date if the string cannot be
1666 parsed.
1667
1668 Note for Qt::TextDate: It is recommended that you use the English short
1669 month names (e.g. "Jan"). Although localized month names can also be used in
1670 Qt 5, they depend on the user's locale settings.
1671
1672 \note Support for localized dates, including the format options
1673 Qt::SystemLocaleDate, Qt::SystemLocaleShortDate, Qt::SystemLocaleLongDate,
1674 Qt::LocaleDate, Qt::DefaultLocaleShortDate, and Qt::DefaultLocaleLongDate,
1675 shall be removed in Qt 6. Use QLocale::toDate() instead.
1676
1677 \sa toString(), QLocale::toDate()
1678*/
1679
1680QDate QDate::fromString(const QString &string, Qt::DateFormat format)
1681{
1682 if (string.isEmpty())
1683 return QDate();
1684
1685 switch (format) {
1686#if QT_DEPRECATED_SINCE(5, 15)
1687QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
1688 case Qt::SystemLocaleDate:
1689 case Qt::SystemLocaleShortDate:
1690 return QLocale::system().toDate(string, QLocale::ShortFormat);
1691 case Qt::SystemLocaleLongDate:
1692 return QLocale::system().toDate(string, QLocale::LongFormat);
1693 case Qt::LocaleDate:
1694 case Qt::DefaultLocaleShortDate:
1695 return QLocale().toDate(string, QLocale::ShortFormat);
1696 case Qt::DefaultLocaleLongDate:
1697 return QLocale().toDate(string, QLocale::LongFormat);
1698QT_WARNING_POP
1699#endif // 5.15
1700 case Qt::RFC2822Date:
1701 return rfcDateImpl(string).date;
1702 default:
1703 case Qt::TextDate: {
1704 QVector<QStringRef> parts = string.splitRef(QLatin1Char(' '), Qt::SkipEmptyParts);
1705
1706 if (parts.count() != 4)
1707 return QDate();
1708
1709 bool ok = false;
1710 int year = parts.at(3).toInt(&ok);
1711 int day = ok ? parts.at(2).toInt(&ok) : 0;
1712 if (!ok || !day)
1713 return QDate();
1714
1715 const int month = fromShortMonthName(parts.at(1), year);
1716 if (month == -1) // Month name matches no English or localised name.
1717 return QDate();
1718
1719 return QDate(year, month, day);
1720 }
1721 case Qt::ISODate:
1722 // Semi-strict parsing, must be long enough and have punctuators as separators
1723 if (string.size() >= 10 && string.at(4).isPunct() && string.at(7).isPunct()
1724 && (string.size() == 10 || !string.at(10).isDigit())) {
1725 QStringView view(string);
1726 const ParsedInt year = readInt(view.mid(0, 4));
1727 const ParsedInt month = readInt(view.mid(5, 2));
1728 const ParsedInt day = readInt(view.mid(8, 2));
1729 if (year.ok && year.value > 0 && year.value <= 9999 && month.ok && day.ok)
1730 return QDate(year.value, month.value, day.value);
1731 }
1732 break;
1733 }
1734 return QDate();
1735}
1736
1737/*!
1738 Returns the QDate represented by the \a string, using the \a
1739 format given, or an invalid date if the string cannot be parsed.
1740
1741 Uses \a cal as calendar if supplied, else the Gregorian calendar. Ranges of
1742 values in the format descriptions below are for the latter; they may be
1743 different for other calendars.
1744
1745 These expressions may be used for the format:
1746
1747 \table
1748 \header \li Expression \li Output
1749 \row \li d \li The day as a number without a leading zero (1 to 31)
1750 \row \li dd \li The day as a number with a leading zero (01 to 31)
1751 \row \li ddd
1752 \li The abbreviated localized day name (e.g. 'Mon' to 'Sun').
1753 Uses the system locale to localize the name, i.e. QLocale::system().
1754 \row \li dddd
1755 \li The long localized day name (e.g. 'Monday' to 'Sunday').
1756 Uses the system locale to localize the name, i.e. QLocale::system().
1757 \row \li M \li The month as a number without a leading zero (1 to 12)
1758 \row \li MM \li The month as a number with a leading zero (01 to 12)
1759 \row \li MMM
1760 \li The abbreviated localized month name (e.g. 'Jan' to 'Dec').
1761 Uses the system locale to localize the name, i.e. QLocale::system().
1762 \row \li MMMM
1763 \li The long localized month name (e.g. 'January' to 'December').
1764 Uses the system locale to localize the name, i.e. QLocale::system().
1765 \row \li yy \li The year as a two digit number (00 to 99)
1766 \row \li yyyy \li The year as a four digit number, possibly plus a leading
1767 minus sign for negative years.
1768 \endtable
1769
1770 \note Unlike the other version of this function, day and month names must
1771 be given in the user's local language. It is only possible to use the English
1772 names if the user's language is English.
1773
1774 All other input characters will be treated as text. Any non-empty sequence
1775 of characters enclosed in single quotes will also be treated (stripped of
1776 the quotes) as text and not be interpreted as expressions. For example:
1777
1778 \snippet code/src_corelib_tools_qdatetime.cpp 1
1779
1780 If the format is not satisfied, an invalid QDate is returned. The
1781 expressions that don't expect leading zeroes (d, M) will be
1782 greedy. This means that they will use two digits even if this
1783 will put them outside the accepted range of values and leaves too
1784 few digits for other sections. For example, the following format
1785 string could have meant January 30 but the M will grab two
1786 digits, resulting in an invalid date:
1787
1788 \snippet code/src_corelib_tools_qdatetime.cpp 2
1789
1790 For any field that is not represented in the format the following
1791 defaults are used:
1792
1793 \table
1794 \header \li Field \li Default value
1795 \row \li Year \li 1900
1796 \row \li Month \li 1
1797 \row \li Day \li 1
1798 \endtable
1799
1800 The following examples demonstrate the default values:
1801
1802 \snippet code/src_corelib_tools_qdatetime.cpp 3
1803
1804 \note If localized month and day names are used, please switch to using
1805 QLocale::system().toDate() as QDate methods shall change to only recognize
1806 English (C locale) names at Qt 6.
1807
1808 \sa toString(), QDateTime::fromString(), QTime::fromString(),
1809 QLocale::toDate()
1810*/
1811
1812QDate QDate::fromString(const QString &string, const QString &format, QCalendar cal)
1813{
1814 QDate date;
1815#if QT_CONFIG(datetimeparser)
1816 QDateTimeParser dt(QMetaType::QDate, QDateTimeParser::FromString, cal);
1817 // dt.setDefaultLocale(QLocale::c()); ### Qt 6
1818 if (dt.parseFormat(format))
1819 dt.fromString(string, &date, nullptr);
1820#else
1821 Q_UNUSED(string);
1822 Q_UNUSED(format);
1823 Q_UNUSED(cal);
1824#endif
1825 return date;
1826}
1827
1828/*!
1829 \overload
1830*/
1831
1832QDate QDate::fromString(const QString &string, const QString &format)
1833{
1834 return fromString(string, format, QCalendar());
1835}
1836#endif // datestring
1837
1838/*!
1839 \overload
1840
1841 Returns \c true if the specified date (\a year, \a month, and \a day) is
1842 valid in the Gregorian calendar; otherwise returns \c false.
1843
1844 Example:
1845 \snippet code/src_corelib_tools_qdatetime.cpp 4
1846
1847 \sa isNull(), setDate(), QCalendar::isDateValid()
1848*/
1849
1850bool QDate::isValid(int year, int month, int day)
1851{
1852 return QGregorianCalendar::validParts(year, month, day);
1853}
1854
1855/*!
1856 \fn bool QDate::isLeapYear(int year)
1857
1858 Returns \c true if the specified \a year is a leap year in the Gregorian
1859 calendar; otherwise returns \c false.
1860
1861 \sa QCalendar::isLeapYear()
1862*/
1863
1864bool QDate::isLeapYear(int y)
1865{
1866 return QGregorianCalendar::leapTest(y);
1867}
1868
1869/*! \fn static QDate QDate::fromJulianDay(qint64 jd)
1870
1871 Converts the Julian day \a jd to a QDate.
1872
1873 \sa toJulianDay()
1874*/
1875
1876/*! \fn int QDate::toJulianDay() const
1877
1878 Converts the date to a Julian day.
1879
1880 \sa fromJulianDay()
1881*/
1882
1883/*****************************************************************************
1884 QTime member functions
1885 *****************************************************************************/
1886
1887/*!
1888 \class QTime
1889 \inmodule QtCore
1890 \reentrant
1891
1892 \brief The QTime class provides clock time functions.
1893
1894
1895 A QTime object contains a clock time, which it can express as the numbers of
1896 hours, minutes, seconds, and milliseconds since midnight. It provides
1897 functions for comparing times and for manipulating a time by adding a number
1898 of milliseconds.
1899
1900 QTime uses the 24-hour clock format; it has no concept of AM/PM.
1901 Unlike QDateTime, QTime knows nothing about time zones or
1902 daylight-saving time (DST).
1903
1904 A QTime object is typically created either by giving the number of hours,
1905 minutes, seconds, and milliseconds explicitly, or by using the static
1906 function currentTime(), which creates a QTime object that represents the
1907 system's local time.
1908
1909 The hour(), minute(), second(), and msec() functions provide
1910 access to the number of hours, minutes, seconds, and milliseconds
1911 of the time. The same information is provided in textual format by
1912 the toString() function.
1913
1914 The addSecs() and addMSecs() functions provide the time a given
1915 number of seconds or milliseconds later than a given time.
1916 Correspondingly, the number of seconds or milliseconds
1917 between two times can be found using secsTo() or msecsTo().
1918
1919 QTime provides a full set of operators to compare two QTime
1920 objects; an earlier time is considered smaller than a later one;
1921 if A.msecsTo(B) is positive, then A < B.
1922
1923 \sa QDate, QDateTime
1924*/
1925
1926/*!
1927 \fn QTime::QTime()
1928
1929 Constructs a null time object. For a null time, isNull() returns \c true and
1930 isValid() returns \c false. If you need a zero time, use QTime(0, 0). For
1931 the start of a day, see QDate::startOfDay().
1932
1933 \sa isNull(), isValid()
1934*/
1935
1936/*!
1937 Constructs a time with hour \a h, minute \a m, seconds \a s and
1938 milliseconds \a ms.
1939
1940 \a h must be in the range 0 to 23, \a m and \a s must be in the
1941 range 0 to 59, and \a ms must be in the range 0 to 999.
1942
1943 \sa isValid()
1944*/
1945
1946QTime::QTime(int h, int m, int s, int ms)
1947{
1948 setHMS(h, m, s, ms);
1949}
1950
1951
1952/*!
1953 \fn bool QTime::isNull() const
1954
1955 Returns \c true if the time is null (i.e., the QTime object was
1956 constructed using the default constructor); otherwise returns
1957 false. A null time is also an invalid time.
1958
1959 \sa isValid()
1960*/
1961
1962/*!
1963 Returns \c true if the time is valid; otherwise returns \c false. For example,
1964 the time 23:30:55.746 is valid, but 24:12:30 is invalid.
1965
1966 \sa isNull()
1967*/
1968
1969bool QTime::isValid() const
1970{
1971 return mds > NullTime && mds < MSECS_PER_DAY;
1972}
1973
1974
1975/*!
1976 Returns the hour part (0 to 23) of the time.
1977
1978 Returns -1 if the time is invalid.
1979
1980 \sa minute(), second(), msec()
1981*/
1982
1983int QTime::hour() const
1984{
1985 if (!isValid())
1986 return -1;
1987
1988 return ds() / MSECS_PER_HOUR;
1989}
1990
1991/*!
1992 Returns the minute part (0 to 59) of the time.
1993
1994 Returns -1 if the time is invalid.
1995
1996 \sa hour(), second(), msec()
1997*/
1998
1999int QTime::minute() const
2000{
2001 if (!isValid())
2002 return -1;
2003
2004 return (ds() % MSECS_PER_HOUR) / MSECS_PER_MIN;
2005}
2006
2007/*!
2008 Returns the second part (0 to 59) of the time.
2009
2010 Returns -1 if the time is invalid.
2011
2012 \sa hour(), minute(), msec()
2013*/
2014
2015int QTime::second() const
2016{
2017 if (!isValid())
2018 return -1;
2019
2020 return (ds() / 1000)%SECS_PER_MIN;
2021}
2022
2023/*!
2024 Returns the millisecond part (0 to 999) of the time.
2025
2026 Returns -1 if the time is invalid.
2027
2028 \sa hour(), minute(), second()
2029*/
2030
2031int QTime::msec() const
2032{
2033 if (!isValid())
2034 return -1;
2035
2036 return ds() % 1000;
2037}
2038
2039#if QT_CONFIG(datestring) // depends on, so implies, textdate
2040/*!
2041 \overload
2042
2043 Returns the time as a string. The \a format parameter determines
2044 the format of the string.
2045
2046 If \a format is Qt::TextDate, the string format is HH:mm:ss;
2047 e.g. 1 second before midnight would be "23:59:59".
2048
2049 If \a format is Qt::ISODate, the string format corresponds to the
2050 ISO 8601 extended specification for representations of dates,
2051 represented by HH:mm:ss. To include milliseconds in the ISO 8601
2052 date, use the \a format Qt::ISODateWithMs, which corresponds to
2053 HH:mm:ss.zzz.
2054
2055 The \a format options Qt::SystemLocaleDate:, Qt::SystemLocaleShortDate and
2056 Qt::SystemLocaleLongDate shall be removed in Qt 6. Their use should be
2057 replaced with:
2058 \l {QLocale::toString()}{QLocale::system().toString(time, QLocale::ShortFormat)} or
2059 \l {QLocale::toString()}{QLocale::system().toString(time, QLocale::LongFormat)}.
2060
2061 The \a format options Qt::LocaleDate, Qt::DefaultLocaleShortDate and
2062 Qt::DefaultLocaleLongDate shall be removed in Qt 6. Their use should be
2063 replaced with:
2064 \l {QLocale::toString()}{QLocale().toString(time, QLocale::ShortFormat)} or
2065 \l {QLocale::toString()}{QLocale().toString(time, QLocale::LongFormat)}.
2066
2067 If the \a format is Qt::RFC2822Date, the string is formatted in
2068 an \l{RFC 2822} compatible way. An example of this formatting is
2069 "23:59:20".
2070
2071 If the time is invalid, an empty string will be returned.
2072
2073 \sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
2074*/
2075
2076QString QTime::toString(Qt::DateFormat format) const
2077{
2078 if (!isValid())
2079 return QString();
2080
2081 switch (format) {
2082#if QT_DEPRECATED_SINCE(5, 15)
2083QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
2084 case Qt::SystemLocaleDate:
2085 case Qt::SystemLocaleShortDate:
2086 return QLocale::system().toString(*this, QLocale::ShortFormat);
2087 case Qt::SystemLocaleLongDate:
2088 return QLocale::system().toString(*this, QLocale::LongFormat);
2089 case Qt::LocaleDate:
2090 case Qt::DefaultLocaleShortDate:
2091 return QLocale().toString(*this, QLocale::ShortFormat);
2092 case Qt::DefaultLocaleLongDate:
2093 return QLocale().toString(*this, QLocale::LongFormat);
2094QT_WARNING_POP
2095#endif // 5.15
2096 case Qt::ISODateWithMs:
2097 return QString::asprintf("%02d:%02d:%02d.%03d", hour(), minute(), second(), msec());
2098 case Qt::RFC2822Date:
2099 case Qt::ISODate:
2100 case Qt::TextDate:
2101 default:
2102 return QString::asprintf("%02d:%02d:%02d", hour(), minute(), second());
2103 }
2104}
2105
2106/*!
2107 \fn QString QTime::toString(const QString &format) const
2108 \fn QString QTime::toString(QStringView format) const
2109
2110 Returns the time as a string. The \a format parameter determines
2111 the format of the result string.
2112
2113 These expressions may be used:
2114
2115 \table
2116 \header \li Expression \li Output
2117 \row \li h
2118 \li The hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
2119 \row \li hh
2120 \li The hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
2121 \row \li H
2122 \li The hour without a leading zero (0 to 23, even with AM/PM display)
2123 \row \li HH
2124 \li The hour with a leading zero (00 to 23, even with AM/PM display)
2125 \row \li m \li The minute without a leading zero (0 to 59)
2126 \row \li mm \li The minute with a leading zero (00 to 59)
2127 \row \li s \li The whole second, without any leading zero (0 to 59)
2128 \row \li ss \li The whole second, with a leading zero where applicable (00 to 59)
2129 \row \li z \li The fractional part of the second, to go after a decimal
2130 point, without trailing zeroes (0 to 999). Thus "\c{s.z}"
2131 reports the seconds to full available (millisecond) precision
2132 without trailing zeroes.
2133 \row \li zzz \li The fractional part of the second, to millisecond
2134 precision, including trailing zeroes where applicable (000 to 999).
2135 \row \li AP or A
2136 \li Use AM/PM display. \e A/AP will be replaced by an upper-case
2137 version of either QLocale::amText() or QLocale::pmText().
2138 \row \li ap or a
2139 \li Use am/pm display. \e a/ap will be replaced by a lower-case version
2140 of either QLocale::amText() or QLocale::pmText().
2141 \row \li t \li The timezone (for example "CEST")
2142 \endtable
2143
2144 Any non-empty sequence of characters enclosed in single quotes will be
2145 included verbatim in the output string (stripped of the quotes), even if it
2146 contains formatting characters. Two consecutive single quotes ("''") are
2147 replaced by a single quote in the output. All other characters in the format
2148 string are included verbatim in the output string.
2149
2150 Formats without separators (e.g. "ddMM") are supported but must be used with
2151 care, as the resulting strings aren't always reliably readable (e.g. if "dM"
2152 produces "212" it could mean either the 2nd of December or the 21st of
2153 February).
2154
2155 Example format strings (assuming that the QTime is 14:13:09.042 and the system
2156 locale is \c{en_US})
2157
2158 \table
2159 \header \li Format \li Result
2160 \row \li hh:mm:ss.zzz \li 14:13:09.042
2161 \row \li h:m:s ap \li 2:13:9 pm
2162 \row \li H:m:s a \li 14:13:9 pm
2163 \endtable
2164
2165 If the time is invalid, an empty string will be returned.
2166 If \a format is empty, the default format "hh:mm:ss" is used.
2167
2168 \note If localized forms of am or pm (the AP, ap, A or a formats) are
2169 desired, please switch to using QLocale::system().toString() as QTime
2170 methods shall change to use English (C locale) at Qt 6.
2171
2172 \sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
2173*/
2174QString QTime::toString(QStringView format) const
2175{
2176 return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
2177}
2178
2179#if QT_STRINGVIEW_VERSION < 2
2180QString QTime::toString(const QString &format) const
2181{
2182 return toString(qToStringViewIgnoringNull(format));
2183}
2184#endif
2185
2186#endif // datestring
2187
2188/*!
2189 Sets the time to hour \a h, minute \a m, seconds \a s and
2190 milliseconds \a ms.
2191
2192 \a h must be in the range 0 to 23, \a m and \a s must be in the
2193 range 0 to 59, and \a ms must be in the range 0 to 999.
2194 Returns \c true if the set time is valid; otherwise returns \c false.
2195
2196 \sa isValid()
2197*/
2198
2199bool QTime::setHMS(int h, int m, int s, int ms)
2200{
2201 if (!isValid(h,m,s,ms)) {
2202 mds = NullTime; // make this invalid
2203 return false;
2204 }
2205 mds = (h*SECS_PER_HOUR + m*SECS_PER_MIN + s)*1000 + ms;
2206 return true;
2207}
2208
2209/*!
2210 Returns a QTime object containing a time \a s seconds later
2211 than the time of this object (or earlier if \a s is negative).
2212
2213 Note that the time will wrap if it passes midnight.
2214
2215 Returns a null time if this time is invalid.
2216
2217 Example:
2218
2219 \snippet code/src_corelib_tools_qdatetime.cpp 5
2220
2221 \sa addMSecs(), secsTo(), QDateTime::addSecs()
2222*/
2223
2224QTime QTime::addSecs(int s) const
2225{
2226 s %= SECS_PER_DAY;
2227 return addMSecs(s * 1000);
2228}
2229
2230/*!
2231 Returns the number of seconds from this time to \a t.
2232 If \a t is earlier than this time, the number of seconds returned
2233 is negative.
2234
2235 Because QTime measures time within a day and there are 86400
2236 seconds in a day, the result is always between -86400 and 86400.
2237
2238 secsTo() does not take into account any milliseconds.
2239
2240 Returns 0 if either time is invalid.
2241
2242 \sa addSecs(), QDateTime::secsTo()
2243*/
2244
2245int QTime::secsTo(const QTime &t) const
2246{
2247 if (!isValid() || !t.isValid())
2248 return 0;
2249
2250 // Truncate milliseconds as we do not want to consider them.
2251 int ourSeconds = ds() / 1000;
2252 int theirSeconds = t.ds() / 1000;
2253 return theirSeconds - ourSeconds;
2254}
2255
2256/*!
2257 Returns a QTime object containing a time \a ms milliseconds later
2258 than the time of this object (or earlier if \a ms is negative).
2259
2260 Note that the time will wrap if it passes midnight. See addSecs()
2261 for an example.
2262
2263 Returns a null time if this time is invalid.
2264
2265 \sa addSecs(), msecsTo(), QDateTime::addMSecs()
2266*/
2267
2268QTime QTime::addMSecs(int ms) const
2269{
2270 QTime t;
2271 if (isValid()) {
2272 if (ms < 0) {
2273 // %,/ not well-defined for -ve, so always work with +ve.
2274 int negdays = (MSECS_PER_DAY - ms) / MSECS_PER_DAY;
2275 t.mds = (ds() + ms + negdays * MSECS_PER_DAY) % MSECS_PER_DAY;
2276 } else {
2277 t.mds = (ds() + ms) % MSECS_PER_DAY;
2278 }
2279 }
2280 return t;
2281}
2282
2283/*!
2284 Returns the number of milliseconds from this time to \a t.
2285 If \a t is earlier than this time, the number of milliseconds returned
2286 is negative.
2287
2288 Because QTime measures time within a day and there are 86400
2289 seconds in a day, the result is always between -86400000 and
2290 86400000 ms.
2291
2292 Returns 0 if either time is invalid.
2293
2294 \sa secsTo(), addMSecs(), QDateTime::msecsTo()
2295*/
2296
2297int QTime::msecsTo(const QTime &t) const
2298{
2299 if (!isValid() || !t.isValid())
2300 return 0;
2301 return t.ds() - ds();
2302}
2303
2304
2305/*!
2306 \fn bool QTime::operator==(const QTime &t) const
2307
2308 Returns \c true if this time is equal to \a t; otherwise returns \c false.
2309*/
2310
2311/*!
2312 \fn bool QTime::operator!=(const QTime &t) const
2313
2314 Returns \c true if this time is different from \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 earlier than \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 or equal to \a t;
2327 otherwise returns \c false.
2328*/
2329
2330/*!
2331 \fn bool QTime::operator>(const QTime &t) const
2332
2333 Returns \c true if this time is later than \a t; 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 or equal to \a t;
2340 otherwise returns \c false.
2341*/
2342
2343/*!
2344 \fn QTime QTime::fromMSecsSinceStartOfDay(int msecs)
2345
2346 Returns a new QTime instance with the time set to the number of \a msecs
2347 since the start of the day, i.e. since 00:00:00.
2348
2349 If \a msecs falls outside the valid range an invalid QTime will be returned.
2350
2351 \sa msecsSinceStartOfDay()
2352*/
2353
2354/*!
2355 \fn int QTime::msecsSinceStartOfDay() const
2356
2357 Returns the number of msecs since the start of the day, i.e. since 00:00:00.
2358
2359 \sa fromMSecsSinceStartOfDay()
2360*/
2361
2362/*!
2363 \fn QTime::currentTime()
2364
2365 Returns the current time as reported by the system clock.
2366
2367 Note that the accuracy depends on the accuracy of the underlying
2368 operating system; not all systems provide 1-millisecond accuracy.
2369
2370 Furthermore, currentTime() only increases within each day; it shall drop by
2371 24 hours each time midnight passes; and, beside this, changes in it may not
2372 correspond to elapsed time, if a daylight-saving transition intervenes.
2373
2374 \sa QDateTime::currentDateTime(), QDateTime::currentDateTimeUtc()
2375*/
2376
2377#if QT_CONFIG(datestring) // depends on, so implies, textdate
2378
2379static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *isMidnight24)
2380{
2381 if (isMidnight24)
2382 *isMidnight24 = false;
2383
2384 const int size = string.size();
2385 if (size < 5 || string.at(2) != QLatin1Char(':'))
2386 return QTime();
2387
2388 ParsedInt hour = readInt(string.mid(0, 2));
2389 ParsedInt minute = readInt(string.mid(3, 2));
2390 if (!hour.ok || !minute.ok)
2391 return QTime();
2392 // FIXME: ISO 8601 allows [,.]\d+ after hour, just as it does after minute
2393
2394 int second = 0;
2395 int msec = 0;
2396
2397 if (size == 5) {
2398 // HH:mm format
2399 second = 0;
2400 msec = 0;
2401 } else if (string.at(5) == QLatin1Char(',') || string.at(5) == QLatin1Char('.')) {
2402 if (format == Qt::TextDate)
2403 return QTime();
2404 // ISODate HH:mm.ssssss format
2405 // We only want 5 digits worth of fraction of minute. This follows the existing
2406 // behavior that determines how milliseconds are read; 4 millisecond digits are
2407 // read and then rounded to 3. If we read at most 5 digits for fraction of minute,
2408 // the maximum amount of millisecond digits it will expand to once converted to
2409 // seconds is 4. E.g. 12:34,99999 will expand to 12:34:59.9994. The milliseconds
2410 // will then be rounded up AND clamped to 999.
2411
2412 const QStringView minuteFractionStr = string.mid(6, qMin(qsizetype(5), string.size() - 6));
2413 const ParsedInt parsed = readInt(minuteFractionStr);
2414 if (!parsed.ok)
2415 return QTime();
2416 const float secondWithMs
2417 = double(parsed.value) * 60 / (std::pow(double(10), minuteFractionStr.size()));
2418
2419 second = std::floor(secondWithMs);
2420 const float secondFraction = secondWithMs - second;
2421 msec = qMin(qRound(secondFraction * 1000.0), 999);
2422 } else if (string.at(5) == QLatin1Char(':')) {
2423 // HH:mm:ss or HH:mm:ss.zzz
2424 const ParsedInt parsed = readInt(string.mid(6, qMin(qsizetype(2), string.size() - 6)));
2425 if (!parsed.ok)
2426 return QTime();
2427 second = parsed.value;
2428 if (size <= 8) {
2429 // No fractional part to read
2430 } else if (string.at(8) == QLatin1Char(',') || string.at(8) == QLatin1Char('.')) {
2431 QStringView msecStr(string.mid(9, qMin(qsizetype(4), string.size() - 9)));
2432 bool ok = true;
2433 // Can't use readInt() here, as we *do* allow trailing space - but not leading:
2434 if (!msecStr.isEmpty() && !msecStr.at(0).isDigit())
2435 return QTime();
2436 msecStr = msecStr.trimmed();
2437 int msecInt = msecStr.isEmpty() ? 0 : QLocale::c().toInt(msecStr, &ok);
2438 if (!ok)
2439 return QTime();
2440 const double secondFraction(msecInt / (std::pow(double(10), msecStr.size())));
2441 msec = qMin(qRound(secondFraction * 1000.0), 999);
2442 } else {
2443#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) // behavior change
2444 // Stray cruft after date-time: tolerate trailing space, but nothing else.
2445 for (const auto &ch : string.mid(8)) {
2446 if (!ch.isSpace())
2447 return QTime();
2448 }
2449#endif
2450 }
2451 } else {
2452 return QTime();
2453 }
2454
2455 const bool isISODate = format == Qt::ISODate || format == Qt::ISODateWithMs;
2456 if (isISODate && hour.value == 24 && minute.value == 0 && second == 0 && msec == 0) {
2457 if (isMidnight24)
2458 *isMidnight24 = true;
2459 hour.value = 0;
2460 }
2461
2462 return QTime(hour.value, minute.value, second, msec);
2463}
2464
2465/*!
2466 Returns the time represented in the \a string as a QTime using the
2467 \a format given, or an invalid time if this is not possible.
2468
2469 Note that fromString() uses a "C" locale encoded string to convert
2470 milliseconds to a float value. If the default locale is not "C",
2471 this may result in two conversion attempts (if the conversion
2472 fails for the default locale). This should be considered an
2473 implementation detail.
2474
2475
2476 \note Support for localized dates, including the format options
2477 Qt::SystemLocaleDate, Qt::SystemLocaleShortDate, Qt::SystemLocaleLongDate,
2478 Qt::LocaleDate, Qt::DefaultLocaleShortDate, and Qt::DefaultLocaleLongDate,
2479 shall be removed in Qt 6. Use QLocale::toTime() instead.
2480
2481 \sa toString(), QLocale::toTime()
2482*/
2483QTime QTime::fromString(const QString &string, Qt::DateFormat format)
2484{
2485 if (string.isEmpty())
2486 return QTime();
2487
2488 switch (format) {
2489#if QT_DEPRECATED_SINCE(5, 15)
2490QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
2491 case Qt::SystemLocaleDate:
2492 case Qt::SystemLocaleShortDate:
2493 return QLocale::system().toTime(string, QLocale::ShortFormat);
2494 case Qt::SystemLocaleLongDate:
2495 return QLocale::system().toTime(string, QLocale::LongFormat);
2496 case Qt::LocaleDate:
2497 case Qt::DefaultLocaleShortDate:
2498 return QLocale().toTime(string, QLocale::ShortFormat);
2499 case Qt::DefaultLocaleLongDate:
2500 return QLocale().toTime(string, QLocale::LongFormat);
2501QT_WARNING_POP
2502#endif // 5.15
2503 case Qt::RFC2822Date:
2504 return rfcDateImpl(string).time;
2505 case Qt::ISODate:
2506 case Qt::ISODateWithMs:
2507 case Qt::TextDate:
2508 default:
2509 return fromIsoTimeString(QStringView(string), format, nullptr);
2510 }
2511}
2512
2513/*!
2514 Returns the QTime represented by the \a string, using the \a
2515 format given, or an invalid time if the string cannot be parsed.
2516
2517 These expressions may be used for the format:
2518
2519 \table
2520 \header \li Expression \li Output
2521 \row \li h
2522 \li The hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
2523 \row \li hh
2524 \li The hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
2525 \row \li H
2526 \li The hour without a leading zero (0 to 23, even with AM/PM display)
2527 \row \li HH
2528 \li The hour with a leading zero (00 to 23, even with AM/PM display)
2529 \row \li m \li The minute without a leading zero (0 to 59)
2530 \row \li mm \li The minute with a leading zero (00 to 59)
2531 \row \li s \li The whole second, without any leading zero (0 to 59)
2532 \row \li ss \li The whole second, with a leading zero where applicable (00 to 59)
2533 \row \li z \li The fractional part of the second, to go after a decimal
2534 point, without trailing zeroes (0 to 999). Thus "\c{s.z}"
2535 reports the seconds to full available (millisecond) precision
2536 without trailing zeroes.
2537 \row \li zzz \li The fractional part of the second, to millisecond
2538 precision, including trailing zeroes where applicable (000 to 999).
2539 \row \li AP or A
2540 \li Interpret as an AM/PM time. \e A/AP will match an upper-case
2541 version of either QLocale::amText() or QLocale::pmText().
2542 \row \li ap or a
2543 \li Interpret as an am/pm time. \e a/ap will match a lower-case version
2544 of either QLocale::amText() or QLocale::pmText().
2545 \endtable
2546
2547 All other input characters will be treated as text. Any non-empty sequence
2548 of characters enclosed in single quotes will also be treated (stripped of
2549 the quotes) as text and not be interpreted as expressions.
2550
2551 \snippet code/src_corelib_tools_qdatetime.cpp 6
2552
2553 If the format is not satisfied, an invalid QTime is returned.
2554 Expressions that do not expect leading zeroes to be given (h, m, s
2555 and z) are greedy. This means that they will use two digits even if
2556 this puts them outside the range of accepted values and leaves too
2557 few digits for other sections. For example, the following string
2558 could have meant 00:07:10, but the m will grab two digits, resulting
2559 in an invalid time:
2560
2561 \snippet code/src_corelib_tools_qdatetime.cpp 7
2562
2563 Any field that is not represented in the format will be set to zero.
2564 For example:
2565
2566 \snippet code/src_corelib_tools_qdatetime.cpp 8
2567
2568 \note If localized forms of am or pm (the AP, ap, A or a formats) are used,
2569 please switch to using QLocale::system().toTime() as QTime methods shall
2570 change to only recognize English (C locale) at Qt 6.
2571
2572 \sa toString(), QDateTime::fromString(), QDate::fromString(),
2573 QLocale::toTime()
2574*/
2575
2576QTime QTime::fromString(const QString &string, const QString &format)
2577{
2578 QTime time;
2579#if QT_CONFIG(datetimeparser)
2580 QDateTimeParser dt(QMetaType::QTime, QDateTimeParser::FromString, QCalendar());
2581 // dt.setDefaultLocale(QLocale::c()); ### Qt 6
2582 if (dt.parseFormat(format))
2583 dt.fromString(string, nullptr, &time);
2584#else
2585 Q_UNUSED(string);
2586 Q_UNUSED(format);
2587#endif
2588 return time;
2589}
2590
2591#endif // datestring
2592
2593
2594/*!
2595 \overload
2596
2597 Returns \c true if the specified time is valid; otherwise returns
2598 false.
2599
2600 The time is valid if \a h is in the range 0 to 23, \a m and
2601 \a s are in the range 0 to 59, and \a ms is in the range 0 to 999.
2602
2603 Example:
2604
2605 \snippet code/src_corelib_tools_qdatetime.cpp 9
2606*/
2607
2608bool QTime::isValid(int h, int m, int s, int ms)
2609{
2610 return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000;
2611}
2612
2613#if QT_DEPRECATED_SINCE(5, 14) // ### Qt 6: remove
2614/*!
2615 Sets this time to the current time. This is practical for timing:
2616
2617 \snippet code/src_corelib_tools_qdatetime.cpp 10
2618
2619 \sa restart(), elapsed(), currentTime()
2620*/
2621
2622void QTime::start()
2623{
2624 *this = currentTime();
2625}
2626
2627/*!
2628 Sets this time to the current time and returns the number of
2629 milliseconds that have elapsed since the last time start() or
2630 restart() was called.
2631
2632 This function is guaranteed to be atomic and is thus very handy
2633 for repeated measurements. Call start() to start the first
2634 measurement, and restart() for each later measurement.
2635
2636 Note that the counter wraps to zero 24 hours after the last call
2637 to start() or restart().
2638
2639 \warning If the system's clock setting has been changed since the
2640 last time start() or restart() was called, the result is
2641 undefined. This can happen when daylight-saving time is turned on
2642 or off.
2643
2644 \sa start(), elapsed(), currentTime()
2645*/
2646
2647int QTime::restart()
2648{
2649 QTime t = currentTime();
2650 int n = msecsTo(t);
2651 if (n < 0) // passed midnight
2652 n += 86400*1000;
2653 *this = t;
2654 return n;
2655}
2656
2657/*!
2658 Returns the number of milliseconds that have elapsed since the
2659 last time start() or restart() was called.
2660
2661 Note that the counter wraps to zero 24 hours after the last call
2662 to start() or restart.
2663
2664 Note that the accuracy depends on the accuracy of the underlying
2665 operating system; not all systems provide 1-millisecond accuracy.
2666
2667 \warning If the system's clock setting has been changed since the
2668 last time start() or restart() was called, the result is
2669 undefined. This can happen when daylight-saving time is turned on
2670 or off.
2671
2672 \sa start(), restart()
2673*/
2674
2675int QTime::elapsed() const
2676{
2677 int n = msecsTo(currentTime());
2678 if (n < 0) // passed midnight
2679 n += 86400 * 1000;
2680 return n;
2681}
2682#endif // Use QElapsedTimer instead !
2683
2684/*****************************************************************************
2685 QDateTime static helper functions
2686 *****************************************************************************/
2687
2688// get the types from QDateTime (through QDateTimePrivate)
2689typedef QDateTimePrivate::QDateTimeShortData ShortData;
2690typedef QDateTimePrivate::QDateTimeData QDateTimeData;
2691
2692// Returns the platform variant of timezone, i.e. the standard time offset
2693// The timezone external variable is documented as always holding the
2694// Standard Time offset as seconds west of Greenwich, i.e. UTC+01:00 is -3600
2695// Note this may not be historicaly accurate.
2696// Relies on tzset, mktime, or localtime having been called to populate timezone
2697static int qt_timezone()
2698{
2699#if defined(_MSC_VER)
2700 long offset;
2701 _get_timezone(&offset);
2702 return offset;
2703#elif defined(Q_OS_BSD4) && !defined(Q_OS_DARWIN)
2704 time_t clock = time(NULL);
2705 struct tm t;
2706 localtime_r(&clock, &t);
2707 // QTBUG-36080 Workaround for systems without the POSIX timezone
2708 // variable. This solution is not very efficient but fixing it is up to
2709 // the libc implementations.
2710 //
2711 // tm_gmtoff has some important differences compared to the timezone
2712 // variable:
2713 // - It returns the number of seconds east of UTC, and we want the
2714 // number of seconds west of UTC.
2715 // - It also takes DST into account, so we need to adjust it to always
2716 // get the Standard Time offset.
2717 return -t.tm_gmtoff + (t.tm_isdst ? (long)SECS_PER_HOUR : 0L);
2718#elif defined(Q_OS_INTEGRITY) || defined(Q_OS_RTEMS)
2719 return 0;
2720#else
2721 return timezone;
2722#endif // Q_OS_WIN
2723}
2724
2725// Returns the tzname, assume tzset has been called already
2726static QString qt_tzname(QDateTimePrivate::DaylightStatus daylightStatus)
2727{
2728 int isDst = (daylightStatus == QDateTimePrivate::DaylightTime) ? 1 : 0;
2729#if defined(Q_CC_MSVC)
2730 size_t s = 0;
2731 char name[512];
2732 if (_get_tzname(&s, name, 512, isDst))
2733 return QString();
2734 return QString::fromLocal8Bit(name);
2735#else
2736 return QString::fromLocal8Bit(tzname[isDst]);
2737#endif // Q_OS_WIN
2738}
2739
2740#if QT_CONFIG(datetimeparser)
2741/*
2742 \internal
2743 Implemented here to share qt_tzname()
2744*/
2745int QDateTimeParser::startsWithLocalTimeZone(const QStringRef name)
2746{
2747 QDateTimePrivate::DaylightStatus zones[2] = {
2748 QDateTimePrivate::StandardTime,
2749 QDateTimePrivate::DaylightTime
2750 };
2751 for (const auto z : zones) {
2752 QString zone(qt_tzname(z));
2753 if (name.startsWith(zone))
2754 return zone.size();
2755 }
2756 return 0;
2757}
2758#endif // datetimeparser
2759
2760// Calls the platform variant of mktime for the given date, time and daylightStatus,
2761// and updates the date, time, daylightStatus and abbreviation with the returned values
2762// If the date falls outside the 1970 to 2037 range supported by mktime / time_t
2763// then null date/time will be returned, you should adjust the date first if
2764// you need a guaranteed result.
2765static qint64 qt_mktime(QDate *date, QTime *time, QDateTimePrivate::DaylightStatus *daylightStatus,
2766 QString *abbreviation, bool *ok = nullptr)
2767{
2768 const qint64 msec = time->msec();
2769 int yy, mm, dd;
2770 date->getDate(&yy, &mm, &dd);
2771
2772 // All other platforms provide standard C library time functions
2773 tm local;
2774 memset(&local, 0, sizeof(local)); // tm_[wy]day plus any non-standard fields
2775 local.tm_sec = time->second();
2776 local.tm_min = time->minute();
2777 local.tm_hour = time->hour();
2778 local.tm_mday = dd;
2779 local.tm_mon = mm - 1;
2780 local.tm_year = yy - 1900;
2781 if (daylightStatus)
2782 local.tm_isdst = int(*daylightStatus);
2783 else
2784 local.tm_isdst = -1;
2785
2786#if defined(Q_OS_WIN)
2787 int hh = local.tm_hour;
2788#endif // Q_OS_WIN
2789 time_t secsSinceEpoch = qMkTime(&local);
2790 if (secsSinceEpoch != time_t(-1)) {
2791 *date = QDate(local.tm_year + 1900, local.tm_mon + 1, local.tm_mday);
2792 *time = QTime(local.tm_hour, local.tm_min, local.tm_sec, msec);
2793#if defined(Q_OS_WIN)
2794 // Windows mktime for the missing hour subtracts 1 hour from the time
2795 // instead of adding 1 hour. If time differs and is standard time then
2796 // this has happened, so add 2 hours to the time and 1 hour to the msecs
2797 if (local.tm_isdst == 0 && local.tm_hour != hh) {
2798 if (time->hour() >= 22)
2799 *date = date->addDays(1);
2800 *time = time->addSecs(2 * SECS_PER_HOUR);
2801 secsSinceEpoch += SECS_PER_HOUR;
2802 local.tm_isdst = 1;
2803 }
2804#endif // Q_OS_WIN
2805 if (local.tm_isdst >= 1) {
2806 if (daylightStatus)
2807 *daylightStatus = QDateTimePrivate::DaylightTime;
2808 if (abbreviation)
2809 *abbreviation = qt_tzname(QDateTimePrivate::DaylightTime);
2810 } else if (local.tm_isdst == 0) {
2811 if (daylightStatus)
2812 *daylightStatus = QDateTimePrivate::StandardTime;
2813 if (abbreviation)
2814 *abbreviation = qt_tzname(QDateTimePrivate::StandardTime);
2815 } else {
2816 if (daylightStatus)
2817 *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
2818 if (abbreviation)
2819 *abbreviation = qt_tzname(QDateTimePrivate::StandardTime);
2820 }
2821 if (ok)
2822 *ok = true;
2823 } else {
2824 *date = QDate();
2825 *time = QTime();
2826 if (daylightStatus)
2827 *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
2828 if (abbreviation)
2829 *abbreviation = QString();
2830 if (ok)
2831 *ok = false;
2832 }
2833
2834 return ((qint64)secsSinceEpoch * 1000) + msec;
2835}
2836
2837// Calls the platform variant of localtime for the given msecs, and updates
2838// the date, time, and DST status with the returned values.
2839static bool qt_localtime(qint64 msecsSinceEpoch, QDate *localDate, QTime *localTime,
2840 QDateTimePrivate::DaylightStatus *daylightStatus)
2841{
2842 const time_t secsSinceEpoch = msecsSinceEpoch / 1000;
2843 const int msec = msecsSinceEpoch % 1000;
2844
2845 tm local;
2846 bool valid = false;
2847
2848 // localtime() is specified to work as if it called tzset().
2849 // localtime_r() does not have this constraint, so make an explicit call.
2850 // The explicit call should also request the timezone info be re-parsed.
2851 qTzSet();
2852#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
2853 // Use the reentrant version of localtime() where available
2854 // as is thread-safe and doesn't use a shared static data area
2855 tm *res = nullptr;
2856 res = localtime_r(&secsSinceEpoch, &local);
2857 if (res)
2858 valid = true;
2859#elif defined(Q_CC_MSVC)
2860 if (!_localtime64_s(&local, &secsSinceEpoch))
2861 valid = true;
2862#else
2863 // Returns shared static data which may be overwritten at any time
2864 // So copy the result asap
2865 tm *res = nullptr;
2866 res = localtime(&secsSinceEpoch);
2867 if (res) {
2868 local = *res;
2869 valid = true;
2870 }
2871#endif
2872 if (valid) {
2873 *localDate = QDate(local.tm_year + 1900, local.tm_mon + 1, local.tm_mday);
2874 *localTime = QTime(local.tm_hour, local.tm_min, local.tm_sec, msec);
2875 if (daylightStatus) {
2876 if (local.tm_isdst > 0)
2877 *daylightStatus = QDateTimePrivate::DaylightTime;
2878 else if (local.tm_isdst < 0)
2879 *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
2880 else
2881 *daylightStatus = QDateTimePrivate::StandardTime;
2882 }
2883 return true;
2884 } else {
2885 *localDate = QDate();
2886 *localTime = QTime();
2887 if (daylightStatus)
2888 *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
2889 return false;
2890 }
2891}
2892
2893// Converts an msecs value into a date and time
2894static void msecsToTime(qint64 msecs, QDate *date, QTime *time)
2895{
2896 qint64 jd = JULIAN_DAY_FOR_EPOCH;
2897 qint64 ds = 0;
2898
2899 if (msecs >= MSECS_PER_DAY || msecs <= -MSECS_PER_DAY) {
2900 jd += msecs / MSECS_PER_DAY;
2901 msecs %= MSECS_PER_DAY;
2902 }
2903
2904 if (msecs < 0) {
2905 ds = MSECS_PER_DAY - msecs - 1;
2906 jd -= ds / MSECS_PER_DAY;
2907 ds = ds % MSECS_PER_DAY;
2908 ds = MSECS_PER_DAY - ds - 1;
2909 } else {
2910 ds = msecs;
2911 }
2912
2913 if (date)
2914 *date = QDate::fromJulianDay(jd);
2915 if (time)
2916 *time = QTime::fromMSecsSinceStartOfDay(ds);
2917}
2918
2919// Converts a date/time value into msecs
2920static qint64 timeToMSecs(QDate date, QTime time)
2921{
2922 return ((date.toJulianDay() - JULIAN_DAY_FOR_EPOCH) * MSECS_PER_DAY)
2923 + time.msecsSinceStartOfDay();
2924}
2925
2926// Convert an MSecs Since Epoch into Local Time
2927static bool epochMSecsToLocalTime(qint64 msecs, QDate *localDate, QTime *localTime,
2928 QDateTimePrivate::DaylightStatus *daylightStatus = nullptr)
2929{
2930 if (msecs < 0) {
2931 // Docs state any LocalTime before 1970-01-01 will *not* have any Daylight Time applied
2932 // Instead just use the standard offset from UTC to convert to UTC time
2933 qTzSet();
2934 msecsToTime(msecs - qt_timezone() * 1000, localDate, localTime);
2935 if (daylightStatus)
2936 *daylightStatus = QDateTimePrivate::StandardTime;
2937 return true;
2938 } else if (msecs > (qint64(TIME_T_MAX) * 1000)) {
2939 // Docs state any LocalTime after 2037-12-31 *will* have any DST applied
2940 // but this may fall outside the supported time_t range, so need to fake it.
2941 // Use existing method to fake the conversion, but this is deeply flawed as it may
2942 // apply the conversion from the wrong day number, e.g. if rule is last Sunday of month
2943 // TODO Use QTimeZone when available to apply the future rule correctly
2944 QDate utcDate;
2945 QTime utcTime;
2946 msecsToTime(msecs, &utcDate, &utcTime);
2947 int year, month, day;
2948 utcDate.getDate(&year, &month, &day);
2949 // 2037 is not a leap year, so make sure date isn't Feb 29
2950 if (month == 2 && day == 29)
2951 --day;
2952 QDate fakeDate(2037, month, day);
2953 qint64 fakeMsecs = QDateTime(fakeDate, utcTime, Qt::UTC).toMSecsSinceEpoch();
2954 bool res = qt_localtime(fakeMsecs, localDate, localTime, daylightStatus);
2955 *localDate = localDate->addDays(fakeDate.daysTo(utcDate));
2956 return res;
2957 } else {
2958 // Falls inside time_t suported range so can use localtime
2959 return qt_localtime(msecs, localDate, localTime, daylightStatus);
2960 }
2961}
2962
2963// Convert a LocalTime expressed in local msecs encoding and the corresponding
2964// DST status into a UTC epoch msecs. Optionally populate the returned
2965// values from mktime for the adjusted local date and time.
2966static qint64 localMSecsToEpochMSecs(qint64 localMsecs,
2967 QDateTimePrivate::DaylightStatus *daylightStatus,
2968 QDate *localDate = nullptr, QTime *localTime = nullptr,
2969 QString *abbreviation = nullptr)
2970{
2971 QDate dt;
2972 QTime tm;
2973 msecsToTime(localMsecs, &dt, &tm);
2974
2975 const qint64 msecsMax = qint64(TIME_T_MAX) * 1000;
2976
2977 if (localMsecs <= qint64(MSECS_PER_DAY)) {
2978
2979 // Docs state any LocalTime before 1970-01-01 will *not* have any DST applied
2980
2981 // First, if localMsecs is within +/- 1 day of minimum time_t try mktime in case it does
2982 // fall after minimum and needs proper DST conversion
2983 if (localMsecs >= -qint64(MSECS_PER_DAY)) {
2984 bool valid;
2985 qint64 utcMsecs = qt_mktime(&dt, &tm, daylightStatus, abbreviation, &valid);
2986 if (valid && utcMsecs >= 0) {
2987 // mktime worked and falls in valid range, so use it
2988 if (localDate)
2989 *localDate = dt;
2990 if (localTime)
2991 *localTime = tm;
2992 return utcMsecs;
2993 }
2994 } else {
2995 // If we don't call mktime then need to call tzset to get offset
2996 qTzSet();
2997 }
2998 // Time is clearly before 1970-01-01 so just use standard offset to convert
2999 qint64 utcMsecs = localMsecs + qt_timezone() * 1000;
3000 if (localDate || localTime)
3001 msecsToTime(localMsecs, localDate, localTime);
3002 if (daylightStatus)
3003 *daylightStatus = QDateTimePrivate::StandardTime;
3004 if (abbreviation)
3005 *abbreviation = qt_tzname(QDateTimePrivate::StandardTime);
3006 return utcMsecs;
3007
3008 } else if (localMsecs >= msecsMax - MSECS_PER_DAY) {
3009
3010 // Docs state any LocalTime after 2037-12-31 *will* have any DST applied
3011 // but this may fall outside the supported time_t range, so need to fake it.
3012
3013 // First, if localMsecs is within +/- 1 day of maximum time_t try mktime in case it does
3014 // fall before maximum and can use proper DST conversion
3015 if (localMsecs <= msecsMax + MSECS_PER_DAY) {
3016 bool valid;
3017 qint64 utcMsecs = qt_mktime(&dt, &tm, daylightStatus, abbreviation, &valid);
3018 if (valid && utcMsecs <= msecsMax) {
3019 // mktime worked and falls in valid range, so use it
3020 if (localDate)
3021 *localDate = dt;
3022 if (localTime)
3023 *localTime = tm;
3024 return utcMsecs;
3025 }
3026 }
3027 // Use existing method to fake the conversion, but this is deeply flawed as it may
3028 // apply the conversion from the wrong day number, e.g. if rule is last Sunday of month
3029 // TODO Use QTimeZone when available to apply the future rule correctly
3030 int year, month, day;
3031 dt.getDate(&year, &month, &day);
3032 // 2037 is not a leap year, so make sure date isn't Feb 29
3033 if (month == 2 && day == 29)
3034 --day;
3035 QDate fakeDate(2037, month, day);
3036 qint64 fakeDiff = fakeDate.daysTo(dt);
3037 qint64 utcMsecs = qt_mktime(&fakeDate, &tm, daylightStatus, abbreviation);
3038 if (localDate)
3039 *localDate = fakeDate.addDays(fakeDiff);
3040 if (localTime)
3041 *localTime = tm;
3042 QDate utcDate;
3043 QTime utcTime;
3044 msecsToTime(utcMsecs, &utcDate, &utcTime);
3045 utcDate = utcDate.addDays(fakeDiff);
3046 utcMsecs = timeToMSecs(utcDate, utcTime);
3047 return utcMsecs;
3048
3049 } else {
3050
3051 // Clearly falls inside 1970-2037 suported range so can use mktime
3052 qint64 utcMsecs = qt_mktime(&dt, &tm, daylightStatus, abbreviation);
3053 if (localDate)
3054 *localDate = dt;
3055 if (localTime)
3056 *localTime = tm;
3057 return utcMsecs;
3058
3059 }
3060}
3061
3062static inline bool specCanBeSmall(Qt::TimeSpec spec)
3063{
3064 return spec == Qt::LocalTime || spec == Qt::UTC;
3065}
3066
3067static inline bool msecsCanBeSmall(qint64 msecs)
3068{
3069 if (!QDateTimeData::CanBeSmall)
3070 return false;
3071
3072 ShortData sd;
3073 sd.msecs = qintptr(msecs);
3074 return sd.msecs == msecs;
3075}
3076
3077static Q_DECL_CONSTEXPR inline
3078QDateTimePrivate::StatusFlags mergeSpec(QDateTimePrivate::StatusFlags status, Qt::TimeSpec spec)
3079{
3080 return QDateTimePrivate::StatusFlags((status & ~QDateTimePrivate::TimeSpecMask) |
3081 (int(spec) << QDateTimePrivate::TimeSpecShift));
3082}
3083
3084static Q_DECL_CONSTEXPR inline Qt::TimeSpec extractSpec(QDateTimePrivate::StatusFlags status)
3085{
3086 return Qt::TimeSpec((status & QDateTimePrivate::TimeSpecMask) >> QDateTimePrivate::TimeSpecShift);
3087}
3088
3089// Set the Daylight Status if LocalTime set via msecs
3090static Q_DECL_RELAXED_CONSTEXPR inline QDateTimePrivate::StatusFlags
3091mergeDaylightStatus(QDateTimePrivate::StatusFlags sf, QDateTimePrivate::DaylightStatus status)
3092{
3093 sf &= ~QDateTimePrivate::DaylightMask;
3094 if (status == QDateTimePrivate::DaylightTime) {
3095 sf |= QDateTimePrivate::SetToDaylightTime;
3096 } else if (status == QDateTimePrivate::StandardTime) {
3097 sf |= QDateTimePrivate::SetToStandardTime;
3098 }
3099 return sf;
3100}
3101
3102// Get the DST Status if LocalTime set via msecs
3103static Q_DECL_RELAXED_CONSTEXPR inline
3104QDateTimePrivate::DaylightStatus extractDaylightStatus(QDateTimePrivate::StatusFlags status)
3105{
3106 if (status & QDateTimePrivate::SetToDaylightTime)
3107 return QDateTimePrivate::DaylightTime;
3108 if (status & QDateTimePrivate::SetToStandardTime)
3109 return QDateTimePrivate::StandardTime;
3110 return QDateTimePrivate::UnknownDaylightTime;
3111}
3112
3113static inline qint64 getMSecs(const QDateTimeData &d)
3114{
3115 if (d.isShort()) {
3116 // same as, but producing better code
3117 //return d.data.msecs;
3118 return qintptr(d.d) >> 8;
3119 }
3120 return d->m_msecs;
3121}
3122
3123static inline QDateTimePrivate::StatusFlags getStatus(const QDateTimeData &d)
3124{
3125 if (d.isShort()) {
3126 // same as, but producing better code
3127 //return StatusFlag(d.data.status);
3128 return QDateTimePrivate::StatusFlag(qintptr(d.d) & 0xFF);
3129 }
3130 return d->m_status;
3131}
3132
3133static inline Qt::TimeSpec getSpec(const QDateTimeData &d)
3134{
3135 return extractSpec(getStatus(d));
3136}
3137
3138#if QT_CONFIG(timezone)
3139void QDateTimePrivate::setUtcOffsetByTZ(qint64 atMSecsSinceEpoch)
3140{
3141 m_offsetFromUtc = m_timeZone.d->offsetFromUtc(atMSecsSinceEpoch);
3142}
3143#endif
3144
3145// Refresh the LocalTime validity and offset
3146static void refreshDateTime(QDateTimeData &d)
3147{
3148 auto status = getStatus(d);
3149 const auto spec = extractSpec(status);
3150 const qint64 msecs = getMSecs(d);
3151 qint64 epochMSecs = 0;
3152 int offsetFromUtc = 0;
3153 QDate testDate;
3154 QTime testTime;
3155 Q_ASSERT(spec == Qt::TimeZone || spec == Qt::LocalTime);
3156
3157#if QT_CONFIG(timezone)
3158 // If not valid time zone then is invalid
3159 if (spec == Qt::TimeZone) {
3160 if (!d->m_timeZone.isValid()) {
3161 status &= ~QDateTimePrivate::ValidDateTime;
3162 } else {
3163 epochMSecs = QDateTimePrivate::zoneMSecsToEpochMSecs(msecs, d->m_timeZone, extractDaylightStatus(status), &testDate, &testTime);
3164 d->setUtcOffsetByTZ(epochMSecs);
3165 }
3166 }
3167#endif // timezone
3168
3169 // If not valid date and time then is invalid
3170 if (!(status & QDateTimePrivate::ValidDate) || !(status & QDateTimePrivate::ValidTime)) {
3171 status &= ~QDateTimePrivate::ValidDateTime;
3172 if (status & QDateTimePrivate::ShortData) {
3173 d.data.status = status;
3174 } else {
3175 d->m_status = status;
3176 d->m_offsetFromUtc = 0;
3177 }
3178 return;
3179 }
3180
3181 // We have a valid date and time and a Qt::LocalTime or Qt::TimeZone that needs calculating
3182 // LocalTime and TimeZone might fall into a "missing" DST transition hour
3183 // Calling toEpochMSecs will adjust the returned date/time if it does
3184 if (spec == Qt::LocalTime) {
3185 auto dstStatus = extractDaylightStatus(status);
3186 epochMSecs = localMSecsToEpochMSecs(msecs, &dstStatus, &testDate, &testTime);
3187 status = mergeDaylightStatus(status, dstStatus);
3188 }
3189 if (timeToMSecs(testDate, testTime) == msecs) {
3190 status |= QDateTimePrivate::ValidDateTime;
3191 // Cache the offset to use in offsetFromUtc()
3192 offsetFromUtc = (msecs - epochMSecs) / 1000;
3193 } else {
3194 status &= ~QDateTimePrivate::ValidDateTime;
3195 }
3196
3197 if (status & QDateTimePrivate::ShortData) {
3198 d.data.status = status;
3199 } else {
3200 d->m_status = status;
3201 d->m_offsetFromUtc = offsetFromUtc;
3202 }
3203}
3204
3205// Check the UTC / offsetFromUTC validity
3206static void checkValidDateTime(QDateTimeData &d)
3207{
3208 auto status = getStatus(d);
3209 auto spec = extractSpec(status);
3210 switch (spec) {
3211 case Qt::OffsetFromUTC:
3212 case Qt::UTC:
3213 // for these, a valid date and a valid time imply a valid QDateTime
3214 if ((status & QDateTimePrivate::ValidDate) && (status & QDateTimePrivate::ValidTime))
3215 status |= QDateTimePrivate::ValidDateTime;
3216 else
3217 status &= ~QDateTimePrivate::ValidDateTime;
3218 if (status & QDateTimePrivate::ShortData)
3219 d.data.status = status;
3220 else
3221 d->m_status = status;
3222 break;
3223 case Qt::TimeZone:
3224 case Qt::LocalTime:
3225 // for these, we need to check whether the timezone is valid and whether
3226 // the time is valid in that timezone. Expensive, but no other option.
3227 refreshDateTime(d);
3228 break;
3229 }
3230}
3231
3232static void setTimeSpec(QDateTimeData &d, Qt::TimeSpec spec, int offsetSeconds)
3233{
3234 auto status = getStatus(d);
3235 status &= ~(QDateTimePrivate::ValidDateTime | QDateTimePrivate::DaylightMask |
3236 QDateTimePrivate::TimeSpecMask);
3237
3238 switch (spec) {
3239 case Qt::OffsetFromUTC:
3240 if (offsetSeconds == 0)
3241 spec = Qt::UTC;
3242 break;
3243 case Qt::TimeZone:
3244 // Use system time zone instead
3245 spec = Qt::LocalTime;
3246 Q_FALLTHROUGH();
3247 case Qt::UTC:
3248 case Qt::LocalTime:
3249 offsetSeconds = 0;
3250 break;
3251 }
3252
3253 status = mergeSpec(status, spec);
3254 if (d.isShort() && offsetSeconds == 0) {
3255 d.data.status = status;
3256 } else {
3257 d.detach();
3258 d->m_status = status & ~QDateTimePrivate::ShortData;
3259 d->m_offsetFromUtc = offsetSeconds;
3260#if QT_CONFIG(timezone)
3261 d->m_timeZone = QTimeZone();
3262#endif // timezone
3263 }
3264}
3265
3266static void setDateTime(QDateTimeData &d, QDate date, QTime time)
3267{
3268 // If the date is valid and the time is not we set time to 00:00:00
3269 QTime useTime = time;
3270 if (!useTime.isValid() && date.isValid())
3271 useTime = QTime::fromMSecsSinceStartOfDay(0);
3272
3273 QDateTimePrivate::StatusFlags newStatus = { };
3274
3275 // Set date value and status
3276 qint64 days = 0;
3277 if (date.isValid()) {
3278 days = date.toJulianDay() - JULIAN_DAY_FOR_EPOCH;
3279 newStatus = QDateTimePrivate::ValidDate;
3280 }
3281
3282 // Set time value and status
3283 int ds = 0;
3284 if (useTime.isValid()) {
3285 ds = useTime.msecsSinceStartOfDay();
3286 newStatus |= QDateTimePrivate::ValidTime;
3287 }
3288
3289 // Set msecs serial value
3290 qint64 msecs = (days * MSECS_PER_DAY) + ds;
3291 if (d.isShort()) {
3292 // let's see if we can keep this short
3293 if (msecsCanBeSmall(msecs)) {
3294 // yes, we can
3295 d.data.msecs = qintptr(msecs);
3296 d.data.status &= ~(QDateTimePrivate::ValidityMask | QDateTimePrivate::DaylightMask);
3297 d.data.status |= newStatus;
3298 } else {
3299 // nope...
3300 d.detach();
3301 }
3302 }
3303 if (!d.isShort()) {
3304 d.detach();
3305 d->m_msecs = msecs;
3306 d->m_status &= ~(QDateTimePrivate::ValidityMask | QDateTimePrivate::DaylightMask);
3307 d->m_status |= newStatus;
3308 }
3309
3310 // Set if date and time are valid
3311 checkValidDateTime(d);
3312}
3313
3314static QPair<QDate, QTime> getDateTime(const QDateTimeData &d)
3315{
3316 QPair<QDate, QTime> result;
3317 qint64 msecs = getMSecs(d);
3318 auto status = getStatus(d);
3319 msecsToTime(msecs, &result.first, &result.second);
3320
3321 if (!status.testFlag(QDateTimePrivate::ValidDate))
3322 result.first = QDate();
3323
3324 if (!status.testFlag(QDateTimePrivate::ValidTime))
3325 result.second = QTime();
3326
3327 return result;
3328}
3329
3330/*****************************************************************************
3331 QDateTime::Data member functions
3332 *****************************************************************************/
3333
3334inline QDateTime::Data::Data()
3335{
3336 // default-constructed data has a special exception:
3337 // it can be small even if CanBeSmall == false
3338 // (optimization so we don't allocate memory in the default constructor)
3339 quintptr value = quintptr(mergeSpec(QDateTimePrivate::ShortData, Qt::LocalTime));
3340 d = reinterpret_cast<QDateTimePrivate *>(value);
3341}
3342
3343inline QDateTime::Data::Data(Qt::TimeSpec spec)
3344{
3345 if (CanBeSmall && Q_LIKELY(specCanBeSmall(spec))) {
3346 d = reinterpret_cast<QDateTimePrivate *>(quintptr(mergeSpec(QDateTimePrivate::ShortData, spec)));
3347 } else {
3348 // the structure is too small, we need to detach
3349 d = new QDateTimePrivate;
3350 d->ref.ref();
3351 d->m_status = mergeSpec({}, spec);
3352 }
3353}
3354
3355inline QDateTime::Data::Data(const Data &other)
3356 : d(other.d)
3357{
3358 if (!isShort()) {
3359 // check if we could shrink
3360 if (specCanBeSmall(extractSpec(d->m_status)) && msecsCanBeSmall(d->m_msecs)) {
3361 ShortData sd;
3362 sd.msecs = qintptr(d->m_msecs);
3363 sd.status = d->m_status | QDateTimePrivate::ShortData;
3364 data = sd;
3365 } else {
3366 // no, have to keep it big
3367 d->ref.ref();
3368 }
3369 }
3370}
3371
3372inline QDateTime::Data::Data(Data &&other)
3373 : d(other.d)
3374{
3375 // reset the other to a short state
3376 Data dummy;
3377 Q_ASSERT(dummy.isShort());
3378 other.d = dummy.d;
3379}
3380
3381inline QDateTime::Data &QDateTime::Data::operator=(const Data &other)
3382{
3383 if (d == other.d)
3384 return *this;
3385
3386 auto x = d;
3387 d = other.d;
3388 if (!other.isShort()) {
3389 // check if we could shrink
3390 if (specCanBeSmall(extractSpec(other.d->m_status)) && msecsCanBeSmall(other.d->m_msecs)) {
3391 ShortData sd;
3392 sd.msecs = qintptr(other.d->m_msecs);
3393 sd.status = other.d->m_status | QDateTimePrivate::ShortData;
3394 data = sd;
3395 } else {
3396 // no, have to keep it big
3397 other.d->ref.ref();
3398 }
3399 }
3400
3401 if (!(quintptr(x) & QDateTimePrivate::ShortData) && !x->ref.deref())
3402 delete x;
3403 return *this;
3404}
3405
3406inline QDateTime::Data::~Data()
3407{
3408 if (!isShort() && !d->ref.deref())
3409 delete d;
3410}
3411
3412inline bool QDateTime::Data::isShort() const
3413{
3414 bool b = quintptr(d) & QDateTimePrivate::ShortData;
3415
3416 // sanity check:
3417 Q_ASSERT(b || (d->m_status & QDateTimePrivate::ShortData) == 0);
3418
3419 // even if CanBeSmall = false, we have short data for a default-constructed
3420 // QDateTime object. But it's unlikely.
3421 if (CanBeSmall)
3422 return Q_LIKELY(b);
3423 return Q_UNLIKELY(b);
3424}
3425
3426inline void QDateTime::Data::detach()
3427{
3428 QDateTimePrivate *x;
3429 bool wasShort = isShort();
3430 if (wasShort) {
3431 // force enlarging
3432 x = new QDateTimePrivate;
3433 x->m_status = QDateTimePrivate::StatusFlag(data.status & ~QDateTimePrivate::ShortData);
3434 x->m_msecs = data.msecs;
3435 } else {
3436 if (d->ref.loadRelaxed() == 1)
3437 return;
3438
3439 x = new QDateTimePrivate(*d);
3440 }
3441
3442 x->ref.storeRelaxed(1);
3443 if (!wasShort && !d->ref.deref())
3444 delete d;
3445 d = x;
3446}
3447
3448inline const QDateTimePrivate *QDateTime::Data::operator->() const
3449{
3450 Q_ASSERT(!isShort());
3451 return d;
3452}
3453
3454inline QDateTimePrivate *QDateTime::Data::operator->()
3455{
3456 // should we attempt to detach here?
3457 Q_ASSERT(!isShort());
3458 Q_ASSERT(d->ref.loadRelaxed() == 1);
3459 return d;
3460}
3461
3462/*****************************************************************************
3463 QDateTimePrivate member functions
3464 *****************************************************************************/
3465
3466Q_NEVER_INLINE
3467QDateTime::Data QDateTimePrivate::create(const QDate &toDate, const QTime &toTime, Qt::TimeSpec toSpec,
3468 int offsetSeconds)
3469{
3470 QDateTime::Data result(toSpec);
3471 setTimeSpec(result, toSpec, offsetSeconds);
3472 setDateTime(result, toDate, toTime);
3473 return result;
3474}
3475
3476#if QT_CONFIG(timezone)
3477inline QDateTime::Data QDateTimePrivate::create(const QDate &toDate, const QTime &toTime,
3478 const QTimeZone &toTimeZone)
3479{
3480 QDateTime::Data result(Qt::TimeZone);
3481 Q_ASSERT(!result.isShort());
3482
3483 result.d->m_status = mergeSpec(result.d->m_status, Qt::TimeZone);
3484 result.d->m_timeZone = toTimeZone;
3485 setDateTime(result, toDate, toTime);
3486 return result;
3487}
3488
3489// Convert a TimeZone time expressed in zone msecs encoding into a UTC epoch msecs
3490// DST transitions are disambiguated by hint.
3491inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QTimeZone &zone,
3492 DaylightStatus hint,
3493 QDate *zoneDate, QTime *zoneTime)
3494{
3495 Q_ASSERT(zone.isValid());
3496 // Get the effective data from QTimeZone
3497 QTimeZonePrivate::Data data = zone.d->dataForLocalTime(zoneMSecs, int(hint));
3498 // Docs state any time before 1970-01-01 will *not* have any DST applied
3499 // but all affected times afterwards will have DST applied.
3500 if (data.atMSecsSinceEpoch < 0) {
3501 msecsToTime(zoneMSecs, zoneDate, zoneTime);
3502 return zoneMSecs - data.standardTimeOffset * 1000;
3503 } else {
3504 msecsToTime(data.atMSecsSinceEpoch + data.offsetFromUtc * 1000, zoneDate, zoneTime);
3505 return data.atMSecsSinceEpoch;
3506 }
3507}
3508#endif // timezone
3509
3510/*****************************************************************************
3511 QDateTime member functions
3512 *****************************************************************************/
3513
3514/*!
3515 \class QDateTime
3516 \inmodule QtCore
3517 \ingroup shared
3518 \reentrant
3519 \brief The QDateTime class provides date and time functions.
3520
3521
3522 A QDateTime object encodes a calendar date and a clock time (a
3523 "datetime"). It combines features of the QDate and QTime classes.
3524 It can read the current datetime from the system clock. It
3525 provides functions for comparing datetimes and for manipulating a
3526 datetime by adding a number of seconds, days, months, or years.
3527
3528 QDateTime can describe datetimes with respect to \l{Qt::LocalTime}{local
3529 time}, to \l{Qt::UTC}{UTC}, to a specified \l{Qt::OffsetFromUTC}{offset from
3530 UTC} or to a specified \l{Qt::TimeZone}{time zone}, in conjunction with the
3531 QTimeZone class. For example, a time zone of "Europe/Berlin" will apply the
3532 daylight-saving rules as used in Germany since 1970. In contrast, an offset
3533 from UTC of +3600 seconds is one hour ahead of UTC (usually written in ISO
3534 standard notation as "UTC+01:00"), with no daylight-saving offset or
3535 changes. When using either local time or a specified time zone, time-zone
3536 transitions such as the starts and ends of daylight-saving time (DST; but
3537 see below) are taken into account. The choice of system used to represent a
3538 datetime is described as its "timespec".
3539
3540 A QDateTime object is typically created either by giving a date and time
3541 explicitly in the constructor, or by using a static function such as
3542 currentDateTime() or fromMSecsSinceEpoch(). The date and time can be changed
3543 with setDate() and setTime(). A datetime can also be set using the
3544 setMSecsSinceEpoch() function that takes the time, in milliseconds, since
3545 00:00:00 on January 1, 1970. The fromString() function returns a QDateTime,
3546 given a string and a date format used to interpret the date within the
3547 string.
3548
3549 QDateTime::currentDateTime() returns a QDateTime that expresses the current
3550 time with respect to local time. QDateTime::currentDateTimeUtc() returns a
3551 QDateTime that expresses the current time with respect to UTC.
3552
3553 The date() and time() functions provide access to the date and
3554 time parts of the datetime. The same information is provided in
3555 textual format by the toString() function.
3556
3557 QDateTime provides a full set of operators to compare two
3558 QDateTime objects, where smaller means earlier and larger means
3559 later.
3560
3561 You can increment (or decrement) a datetime by a given number of
3562 milliseconds using addMSecs(), seconds using addSecs(), or days using
3563 addDays(). Similarly, you can use addMonths() and addYears(). The daysTo()
3564 function returns the number of days between two datetimes, secsTo() returns
3565 the number of seconds between two datetimes, and msecsTo() returns the
3566 number of milliseconds between two datetimes. These operations are aware of
3567 daylight-saving time (DST) and other time-zone transitions, where
3568 applicable.
3569
3570 Use toTimeSpec() to express a datetime in local time or UTC,
3571 toOffsetFromUtc() to express in terms of an offset from UTC, or toTimeZone()
3572 to express it with respect to a general time zone. You can use timeSpec() to
3573 find out what time-spec a QDateTime object stores its time relative to. When
3574 that is Qt::TimeZone, you can use timeZone() to find out which zone it is
3575 using.
3576
3577 \note QDateTime does not account for leap seconds.
3578
3579 \section1 Remarks
3580
3581 \section2 No Year 0
3582
3583 There is no year 0. Dates in that year are considered invalid. The
3584 year -1 is the year "1 before Christ" or "1 before current era."
3585 The day before 1 January 1 CE is 31 December 1 BCE.
3586
3587 \section2 Range of Valid Dates
3588
3589 The range of values that QDateTime can represent is dependent on the
3590 internal storage implementation. QDateTime is currently stored in a qint64
3591 as a serial msecs value encoding the date and time. This restricts the date
3592 range to about +/- 292 million years, compared to the QDate range of +/- 2
3593 billion years. Care must be taken when creating a QDateTime with extreme
3594 values that you do not overflow the storage. The exact range of supported
3595 values varies depending on the Qt::TimeSpec and time zone.
3596
3597 \section2 Use of Timezones
3598
3599 QDateTime uses the system's time zone information to determine the current
3600 local time zone and its offset from UTC. If the system is not configured
3601 correctly or not up-to-date, QDateTime will give wrong results.
3602
3603 QDateTime likewise uses system-provided information to determine the offsets
3604 of other timezones from UTC. If this information is incomplete or out of
3605 date, QDateTime will give wrong results. See the QTimeZone documentation for
3606 more details.
3607
3608 On modern Unix systems, this means QDateTime usually has accurate
3609 information about historical transitions (including DST, see below) whenever
3610 possible. On Windows, where the system doesn't support historical timezone
3611 data, historical accuracy is not maintained with respect to timezone
3612 transitions, notably including DST.
3613
3614 \section2 Daylight-Saving Time (DST)
3615
3616 QDateTime takes into account transitions between Standard Time and
3617 Daylight-Saving Time. For example, if the transition is at 2am and the clock
3618 goes forward to 3am, then there is a "missing" hour from 02:00:00 to
3619 02:59:59.999 which QDateTime considers to be invalid. Any date arithmetic
3620 performed will take this missing hour into account and return a valid
3621 result. For example, adding one minute to 01:59:59 will get 03:00:00.
3622
3623 The range of valid dates taking DST into account is 1970-01-01 to the
3624 present, and rules are in place for handling DST correctly until 2037-12-31,
3625 but these could change. For dates after 2037, QDateTime makes a \e{best
3626 guess} using the rules for year 2037, but we can't guarantee accuracy;
3627 indeed, for \e{any} future date, the time-zone may change its rules before
3628 that date comes around. For dates before 1970, QDateTime doesn't take DST
3629 changes into account, even if the system's time zone database provides that
3630 information, although it does take into account changes to the time-zone's
3631 standard offset, where this information is available.
3632
3633 \section2 Offsets From UTC
3634
3635 There is no explicit size restriction on an offset from UTC, but there is an
3636 implicit limit imposed when using the toString() and fromString() methods
3637 which use a [+|-]hh:mm format, effectively limiting the range to +/- 99
3638 hours and 59 minutes and whole minutes only. Note that currently no time
3639 zone lies outside the range of +/- 14 hours.
3640
3641 \sa QDate, QTime, QDateTimeEdit, QTimeZone
3642*/
3643
3644/*!
3645 \since 5.14
3646 \enum QDateTime::YearRange
3647
3648 This enumerated type describes the range of years (in the Gregorian
3649 calendar) representable by QDateTime:
3650
3651 \value First The later parts of this year are representable
3652 \value Last The earlier parts of this year are representable
3653
3654 All dates strictly between these two years are also representable.
3655 Note, however, that the Gregorian Calendar has no year zero.
3656
3657 \note QDate can describe dates in a wider range of years. For most
3658 purposes, this makes little difference, as the range of years that QDateTime
3659 can support reaches 292 million years either side of 1970.
3660
3661 \sa isValid(), QDate
3662*/
3663
3664/*!
3665 Constructs a null datetime (i.e. null date and null time). A null
3666 datetime is invalid, since the date is invalid.
3667
3668 \sa isValid()
3669*/
3670QDateTime::QDateTime() noexcept(Data::CanBeSmall)
3671{
3672}
3673
3674
3675#if QT_DEPRECATED_SINCE(5, 17) // ### Qt 6: remove
3676/*!
3677 Constructs a datetime with the given \a date, using Qt::LocalTime as the
3678 timeSpec() and the time at the start of that date.
3679
3680 \sa QDate::startOfDay()
3681*/
3682QDateTime::QDateTime(const QDate &date)
3683 : QDateTime(date.startOfDay(Qt::LocalTime, 0))
3684{
3685}
3686#endif
3687
3688/*!
3689 Constructs a datetime with the given \a date and \a time, using
3690 the time specification defined by \a spec.
3691
3692 If \a date is valid and \a time is not, the time will be set to midnight.
3693
3694 If \a spec is Qt::OffsetFromUTC then it will be set to Qt::UTC, i.e. an
3695 offset of 0 seconds. To create a Qt::OffsetFromUTC datetime use the
3696 correct constructor.
3697
3698 If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
3699 i.e. the current system time zone. To create a Qt::TimeZone datetime
3700 use the correct constructor.
3701*/
3702
3703QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec)
3704 : d(QDateTimePrivate::create(date, time, spec, 0))
3705{
3706}
3707
3708/*!
3709 \since 5.2
3710
3711 Constructs a datetime with the given \a date and \a time, using
3712 the time specification defined by \a spec and \a offsetSeconds seconds.
3713
3714 If \a date is valid and \a time is not, the time will be set to midnight.
3715
3716 If the \a spec is not Qt::OffsetFromUTC then \a offsetSeconds will be ignored.
3717
3718 If the \a spec is Qt::OffsetFromUTC and \a offsetSeconds is 0 then the
3719 timeSpec() will be set to Qt::UTC, i.e. an offset of 0 seconds.
3720
3721 If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
3722 i.e. the current system time zone. To create a Qt::TimeZone datetime
3723 use the correct constructor.
3724*/
3725
3726QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec, int offsetSeconds)
3727 : d(QDateTimePrivate::create(date, time, spec, offsetSeconds))
3728{
3729}
3730
3731#if QT_CONFIG(timezone)
3732/*!
3733 \since 5.2
3734
3735 Constructs a datetime with the given \a date and \a time, using
3736 the Time Zone specified by \a timeZone.
3737
3738 If \a date is valid and \a time is not, the time will be set to 00:00:00.
3739
3740 If \a timeZone is invalid then the datetime will be invalid.
3741*/
3742
3743QDateTime::QDateTime(const QDate &date, const QTime &time, const QTimeZone &timeZone)
3744 : d(QDateTimePrivate::create(date, time, timeZone))
3745{
3746}
3747#endif // timezone
3748
3749/*!
3750 Constructs a copy of the \a other datetime.
3751*/
3752QDateTime::QDateTime(const QDateTime &other) noexcept
3753 : d(other.d)
3754{
3755}
3756
3757/*!
3758 \since 5.8
3759 Moves the content of the temporary \a other datetime to this object and
3760 leaves \a other in an unspecified (but proper) state.
3761*/
3762QDateTime::QDateTime(QDateTime &&other) noexcept
3763 : d(std::move(other.d))
3764{
3765}
3766
3767/*!
3768 Destroys the datetime.
3769*/
3770QDateTime::~QDateTime()
3771{
3772}
3773
3774/*!
3775 Makes a copy of the \a other datetime and returns a reference to the
3776 copy.
3777*/
3778
3779QDateTime &QDateTime::operator=(const QDateTime &other) noexcept
3780{
3781 d = other.d;
3782 return *this;
3783}
3784/*!
3785 \fn void QDateTime::swap(QDateTime &other)
3786 \since 5.0
3787
3788 Swaps this datetime with \a other. This operation is very fast
3789 and never fails.
3790*/
3791
3792/*!
3793 Returns \c true if both the date and the time are null; otherwise
3794 returns \c false. A null datetime is invalid.
3795
3796 \sa QDate::isNull(), QTime::isNull(), isValid()
3797*/
3798
3799bool QDateTime::isNull() const
3800{
3801 auto status = getStatus(d);
3802 return !status.testFlag(QDateTimePrivate::ValidDate) &&
3803 !status.testFlag(QDateTimePrivate::ValidTime);
3804}
3805
3806/*!
3807 Returns \c true if both the date and the time are valid and they are valid in
3808 the current Qt::TimeSpec, otherwise returns \c false.
3809
3810 If the timeSpec() is Qt::LocalTime or Qt::TimeZone then the date and time are
3811 checked to see if they fall in the Standard Time to Daylight-Saving Time transition
3812 hour, i.e. if the transition is at 2am and the clock goes forward to 3am
3813 then the time from 02:00:00 to 02:59:59.999 is considered to be invalid.
3814
3815 \sa QDateTime::YearRange, QDate::isValid(), QTime::isValid()
3816*/
3817
3818bool QDateTime::isValid() const
3819{
3820 auto status = getStatus(d);
3821 return status & QDateTimePrivate::ValidDateTime;
3822}
3823
3824/*!
3825 Returns the date part of the datetime.
3826
3827 \sa setDate(), time(), timeSpec()
3828*/
3829
3830QDate QDateTime::date() const
3831{
3832 auto status = getStatus(d);
3833 if (!status.testFlag(QDateTimePrivate::ValidDate))
3834 return QDate();
3835 QDate dt;
3836 msecsToTime(getMSecs(d), &dt, nullptr);
3837 return dt;
3838}
3839
3840/*!
3841 Returns the time part of the datetime.
3842
3843 \sa setTime(), date(), timeSpec()
3844*/
3845
3846QTime QDateTime::time() const
3847{
3848 auto status = getStatus(d);
3849 if (!status.testFlag(QDateTimePrivate::ValidTime))
3850 return QTime();
3851 QTime tm;
3852 msecsToTime(getMSecs(d), nullptr, &tm);
3853 return tm;
3854}
3855
3856/*!
3857 Returns the time specification of the datetime.
3858
3859 \sa setTimeSpec(), date(), time(), Qt::TimeSpec
3860*/
3861
3862Qt::TimeSpec QDateTime::timeSpec() const
3863{
3864 return getSpec(d);
3865}
3866
3867#if QT_CONFIG(timezone)
3868/*!
3869 \since 5.2
3870
3871 Returns the time zone of the datetime.
3872
3873 If the timeSpec() is Qt::LocalTime then an instance of the current system
3874 time zone will be returned. Note however that if you copy this time zone
3875 the instance will not remain in sync if the system time zone changes.
3876
3877 \sa setTimeZone(), Qt::TimeSpec
3878*/
3879
3880QTimeZone QDateTime::timeZone() const
3881{
3882 switch (getSpec(d)) {
3883 case Qt::UTC:
3884 return QTimeZone::utc();
3885 case Qt::OffsetFromUTC:
3886 return QTimeZone(d->m_offsetFromUtc);
3887 case Qt::TimeZone:
3888 if (d->m_timeZone.isValid())
3889 return d->m_timeZone;
3890 break;
3891 case Qt::LocalTime:
3892 return QTimeZone::systemTimeZone();
3893 }
3894 return QTimeZone();
3895}
3896#endif // timezone
3897
3898/*!
3899 \since 5.2
3900
3901 Returns this date-time's Offset From UTC in seconds.
3902
3903 The result depends on timeSpec():
3904 \list
3905 \li \c Qt::UTC The offset is 0.
3906 \li \c Qt::OffsetFromUTC The offset is the value originally set.
3907 \li \c Qt::LocalTime The local time's offset from UTC is returned.
3908 \li \c Qt::TimeZone The offset used by the time-zone is returned.
3909 \endlist
3910
3911 For the last two, the offset at this date and time will be returned, taking
3912 account of Daylight-Saving Offset unless the date precedes the start of
3913 1970. The offset is the difference between the local time or time in the
3914 given time-zone and UTC time; it is positive in time-zones ahead of UTC
3915 (East of The Prime Meridian), negative for those behind UTC (West of The
3916 Prime Meridian).
3917
3918 \sa setOffsetFromUtc()
3919*/
3920
3921int QDateTime::offsetFromUtc() const
3922{
3923 if (!d.isShort())
3924 return d->m_offsetFromUtc;
3925 if (!isValid())
3926 return 0;
3927
3928 auto spec = getSpec(d);
3929 if (spec == Qt::LocalTime) {
3930 // we didn't cache the value, so we need to calculate it now...
3931 qint64 msecs = getMSecs(d);
3932 return (msecs - toMSecsSinceEpoch()) / 1000;
3933 }
3934
3935 Q_ASSERT(spec == Qt::UTC);
3936 return 0;
3937}
3938
3939/*!
3940 \since 5.2
3941
3942 Returns the Time Zone Abbreviation for the datetime.
3943
3944 If the timeSpec() is Qt::UTC this will be "UTC".
3945
3946 If the timeSpec() is Qt::OffsetFromUTC this will be in the format
3947 "UTC[+-]00:00".
3948
3949 If the timeSpec() is Qt::LocalTime then the host system is queried for the
3950 correct abbreviation.
3951
3952 Note that abbreviations may or may not be localized.
3953
3954 Note too that the abbreviation is not guaranteed to be a unique value,
3955 i.e. different time zones may have the same abbreviation.
3956
3957 \sa timeSpec()
3958*/
3959
3960QString QDateTime::timeZoneAbbreviation() const
3961{
3962 if (!isValid())
3963 return QString();
3964
3965 switch (getSpec(d)) {
3966 case Qt::UTC:
3967 return QLatin1String("UTC");
3968 case Qt::OffsetFromUTC:
3969 return QLatin1String("UTC") + toOffsetString(Qt::ISODate, d->m_offsetFromUtc);
3970 case Qt::TimeZone:
3971#if !QT_CONFIG(timezone)
3972 break;
3973#else
3974 Q_ASSERT(d->m_timeZone.isValid());
3975 return d->m_timeZone.d->abbreviation(toMSecsSinceEpoch());
3976#endif // timezone
3977 case Qt::LocalTime: {
3978 QString abbrev;
3979 auto status = extractDaylightStatus(getStatus(d));
3980 localMSecsToEpochMSecs(getMSecs(d), &status, nullptr, nullptr, &abbrev);
3981 return abbrev;
3982 }
3983 }
3984 return QString();
3985}
3986
3987/*!
3988 \since 5.2
3989
3990 Returns if this datetime falls in Daylight-Saving Time.
3991
3992 If the Qt::TimeSpec is not Qt::LocalTime or Qt::TimeZone then will always
3993 return false.
3994
3995 \sa timeSpec()
3996*/
3997
3998bool QDateTime::isDaylightTime() const
3999{
4000 if (!isValid())
4001 return false;
4002
4003 switch (getSpec(d)) {
4004 case Qt::UTC:
4005 case Qt::OffsetFromUTC:
4006 return false;
4007 case Qt::TimeZone:
4008#if !QT_CONFIG(timezone)
4009 break;
4010#else
4011 Q_ASSERT(d->m_timeZone.isValid());
4012 return d->m_timeZone.d->isDaylightTime(toMSecsSinceEpoch());
4013#endif // timezone
4014 case Qt::LocalTime: {
4015 auto status = extractDaylightStatus(getStatus(d));
4016 if (status == QDateTimePrivate::UnknownDaylightTime)
4017 localMSecsToEpochMSecs(getMSecs(d), &status);
4018 return (status == QDateTimePrivate::DaylightTime);
4019 }
4020 }
4021 return false;
4022}
4023
4024/*!
4025 Sets the date part of this datetime to \a date. If no time is set yet, it
4026 is set to midnight. If \a date is invalid, this QDateTime becomes invalid.
4027
4028 \sa date(), setTime(), setTimeSpec()
4029*/
4030
4031void QDateTime::setDate(const QDate &date)
4032{
4033 setDateTime(d, date, time());
4034}
4035
4036/*!
4037 Sets the time part of this datetime to \a time. If \a time is not valid,
4038 this function sets it to midnight. Therefore, it's possible to clear any
4039 set time in a QDateTime by setting it to a default QTime:
4040
4041 \code
4042 QDateTime dt = QDateTime::currentDateTime();
4043 dt.setTime(QTime());
4044 \endcode
4045
4046 \sa time(), setDate(), setTimeSpec()
4047*/
4048
4049void QDateTime::setTime(const QTime &time)
4050{
4051 setDateTime(d, date(), time);
4052}
4053
4054/*!
4055 Sets the time specification used in this datetime to \a spec.
4056 The datetime will refer to a different point in time.
4057
4058 If \a spec is Qt::OffsetFromUTC then the timeSpec() will be set
4059 to Qt::UTC, i.e. an effective offset of 0.
4060
4061 If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
4062 i.e. the current system time zone.
4063
4064 Example:
4065 \snippet code/src_corelib_tools_qdatetime.cpp 19
4066
4067 \sa timeSpec(), setDate(), setTime(), setTimeZone(), Qt::TimeSpec
4068*/
4069
4070void QDateTime::setTimeSpec(Qt::TimeSpec spec)
4071{
4072 QT_PREPEND_NAMESPACE(setTimeSpec(d, spec, 0));
4073 checkValidDateTime(d);
4074}
4075
4076/*!
4077 \since 5.2
4078
4079 Sets the timeSpec() to Qt::OffsetFromUTC and the offset to \a offsetSeconds.
4080 The datetime will refer to a different point in time.
4081
4082 The maximum and minimum offset is 14 positive or negative hours. If
4083 \a offsetSeconds is larger or smaller than that, then the result is
4084 undefined.
4085
4086 If \a offsetSeconds is 0 then the timeSpec() will be set to Qt::UTC.
4087
4088 \sa isValid(), offsetFromUtc()
4089*/
4090
4091void QDateTime::setOffsetFromUtc(int offsetSeconds)
4092{
4093 QT_PREPEND_NAMESPACE(setTimeSpec(d, Qt::OffsetFromUTC, offsetSeconds));
4094 checkValidDateTime(d);
4095}
4096
4097#if QT_CONFIG(timezone)
4098/*!
4099 \since 5.2
4100
4101 Sets the time zone used in this datetime to \a toZone.
4102 The datetime will refer to a different point in time.
4103
4104 If \a toZone is invalid then the datetime will be invalid.
4105
4106 \sa timeZone(), Qt::TimeSpec
4107*/
4108
4109void QDateTime::setTimeZone(const QTimeZone &toZone)
4110{
4111 d.detach(); // always detach
4112 d->m_status = mergeSpec(d->m_status, Qt::TimeZone);
4113 d->m_offsetFromUtc = 0;
4114 d->m_timeZone = toZone;
4115 refreshDateTime(d);
4116}
4117#endif // timezone
4118
4119/*!
4120 \since 4.7
4121
4122 Returns the datetime as the number of milliseconds that have passed
4123 since 1970-01-01T00:00:00.000, Coordinated Universal Time (Qt::UTC).
4124
4125 On systems that do not support time zones, this function will
4126 behave as if local time were Qt::UTC.
4127
4128 The behavior for this function is undefined if the datetime stored in
4129 this object is not valid. However, for all valid dates, this function
4130 returns a unique value.
4131
4132 \sa toSecsSinceEpoch(), setMSecsSinceEpoch()
4133*/
4134qint64 QDateTime::toMSecsSinceEpoch() const
4135{
4136 // Note: QDateTimeParser relies on this producing a useful result, even when
4137 // !isValid(), at least when the invalidity is a time in a fall-back (that
4138 // we'll have adjusted to lie outside it, but marked invalid because it's
4139 // not what was asked for). Other things may be doing similar.
4140 switch (getSpec(d)) {
4141 case Qt::UTC:
4142 return getMSecs(d);
4143
4144 case Qt::OffsetFromUTC:
4145 return d->m_msecs - (d->m_offsetFromUtc * 1000);
4146
4147 case Qt::LocalTime: {
4148 // recalculate the local timezone
4149 auto status = extractDaylightStatus(