summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qdatetime.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/tools/qdatetime.cpp')
-rw-r--r--src/corelib/tools/qdatetime.cpp5685
1 files changed, 0 insertions, 5685 deletions
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
deleted file mode 100644
index 9220d210f1..0000000000
--- a/src/corelib/tools/qdatetime.cpp
+++ /dev/null
@@ -1,5685 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qplatformdefs.h"
-#include "private/qdatetime_p.h"
-#if QT_CONFIG(datetimeparser)
-#include "private/qdatetimeparser_p.h"
-#endif
-
-#include "qdatastream.h"
-#include "qset.h"
-#include "qlocale.h"
-#include "qdatetime.h"
-#if QT_CONFIG(timezone)
-#include "qtimezoneprivate_p.h"
-#endif
-#include "qregexp.h"
-#include "qdebug.h"
-#ifndef Q_OS_WIN
-#include <locale.h>
-#endif
-
-#include <cmath>
-#ifdef Q_CC_MINGW
-# include <unistd.h> // Define _POSIX_THREAD_SAFE_FUNCTIONS to obtain localtime_r()
-#endif
-#include <time.h>
-#ifdef Q_OS_WIN
-# include <qt_windows.h>
-# ifdef Q_OS_WINRT
-# include "qfunctions_winrt.h"
-# endif
-#endif
-
-#if defined(Q_OS_MAC)
-#include <private/qcore_mac_p.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-/*****************************************************************************
- Date/Time Constants
- *****************************************************************************/
-
-enum {
- SECS_PER_DAY = 86400,
- MSECS_PER_DAY = 86400000,
- SECS_PER_HOUR = 3600,
- MSECS_PER_HOUR = 3600000,
- SECS_PER_MIN = 60,
- MSECS_PER_MIN = 60000,
- TIME_T_MAX = 2145916799, // int maximum 2037-12-31T23:59:59 UTC
- JULIAN_DAY_FOR_EPOCH = 2440588 // result of julianDayFromDate(1970, 1, 1)
-};
-
-/*****************************************************************************
- QDate static helper functions
- *****************************************************************************/
-
-static inline QDate fixedDate(int y, int m, int d)
-{
- QDate result(y, m, 1);
- result.setDate(y, m, qMin(d, result.daysInMonth()));
- return result;
-}
-
-/*
- Division, rounding down (rather than towards zero).
-
- From C++11 onwards, integer division is defined to round towards zero, so we
- can rely on that when implementing this. This is only used with denominator b
- > 0, so we only have to treat negative numerator, a, specially.
- */
-static inline qint64 floordiv(qint64 a, int b)
-{
- return (a - (a < 0 ? b - 1 : 0)) / b;
-}
-
-static inline int floordiv(int a, int b)
-{
- return (a - (a < 0 ? b - 1 : 0)) / b;
-}
-
-static inline qint64 julianDayFromDate(int year, int month, int day)
-{
- // Adjust for no year 0
- if (year < 0)
- ++year;
-
-/*
- * Math from The Calendar FAQ at http://www.tondering.dk/claus/cal/julperiod.php
- * This formula is correct for all julian days, when using mathematical integer
- * division (round to negative infinity), not c++11 integer division (round to zero)
- */
- int a = floordiv(14 - month, 12);
- qint64 y = (qint64)year + 4800 - a;
- int m = month + 12 * a - 3;
- return day + floordiv(153 * m + 2, 5) + 365 * y + floordiv(y, 4) - floordiv(y, 100) + floordiv(y, 400) - 32045;
-}
-
-struct ParsedDate
-{
- int year, month, day;
-};
-
-// prevent this function from being inlined into all 10 users
-Q_NEVER_INLINE
-static ParsedDate getDateFromJulianDay(qint64 julianDay)
-{
-/*
- * Math from The Calendar FAQ at http://www.tondering.dk/claus/cal/julperiod.php
- * This formula is correct for all julian days, when using mathematical integer
- * division (round to negative infinity), not c++11 integer division (round to zero)
- */
- qint64 a = julianDay + 32044;
- qint64 b = floordiv(4 * a + 3, 146097);
- int c = a - floordiv(146097 * b, 4);
-
- int d = floordiv(4 * c + 3, 1461);
- int e = c - floordiv(1461 * d, 4);
- int m = floordiv(5 * e + 2, 153);
-
- int day = e - floordiv(153 * m + 2, 5) + 1;
- int month = m + 3 - 12 * floordiv(m, 10);
- int year = 100 * b + d - 4800 + floordiv(m, 10);
-
- // Adjust for no year 0
- if (year <= 0)
- --year ;
-
- return { year, month, day };
-}
-
-/*****************************************************************************
- Date/Time formatting helper functions
- *****************************************************************************/
-
-#if QT_CONFIG(textdate)
-static const char qt_shortMonthNames[][4] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
-static int qt_monthNumberFromShortName(QStringRef shortName)
-{
- for (unsigned int i = 0; i < sizeof(qt_shortMonthNames) / sizeof(qt_shortMonthNames[0]); ++i) {
- if (shortName == QLatin1String(qt_shortMonthNames[i], 3))
- return i + 1;
- }
- return -1;
-}
-static int qt_monthNumberFromShortName(const QString &shortName)
-{ return qt_monthNumberFromShortName(QStringRef(&shortName)); }
-
-static int fromShortMonthName(const QStringRef &monthName)
-{
- // Assume that English monthnames are the default
- int month = qt_monthNumberFromShortName(monthName);
- if (month != -1)
- return month;
- // If English names can't be found, search the localized ones
- for (int i = 1; i <= 12; ++i) {
- if (monthName == QLocale::system().monthName(i, QLocale::ShortFormat))
- return i;
- }
- return -1;
-}
-#endif // textdate
-
-#if QT_CONFIG(datestring)
-struct ParsedRfcDateTime {
- QDate date;
- QTime time;
- int utcOffset;
-};
-
-static ParsedRfcDateTime rfcDateImpl(const QString &s)
-{
- ParsedRfcDateTime result;
-
- // Matches "Wdy, dd Mon yyyy HH:mm:ss ±hhmm" (Wdy, being optional)
- QRegExp rex(QStringLiteral("^(?:[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))?"));
- if (s.indexOf(rex) == 0) {
- const QStringList cap = rex.capturedTexts();
- result.date = QDate(cap[3].toInt(), qt_monthNumberFromShortName(cap[2]), cap[1].toInt());
- if (!cap[4].isEmpty())
- result.time = QTime(cap[4].toInt(), cap[5].toInt(), cap[6].toInt());
- const bool positiveOffset = (cap[7] == QLatin1String("+"));
- const int hourOffset = cap[8].toInt();
- const int minOffset = cap[9].toInt();
- result.utcOffset = ((hourOffset * 60 + minOffset) * (positiveOffset ? 60 : -60));
- } else {
- // Matches "Wdy Mon dd HH:mm:ss yyyy"
- QRegExp rex(QStringLiteral("^[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))?"));
- if (s.indexOf(rex) == 0) {
- const QStringList cap = rex.capturedTexts();
- result.date = QDate(cap[6].toInt(), qt_monthNumberFromShortName(cap[1]), cap[2].toInt());
- if (!cap[3].isEmpty())
- result.time = QTime(cap[3].toInt(), cap[4].toInt(), cap[5].toInt());
- const bool positiveOffset = (cap[7] == QLatin1String("+"));
- const int hourOffset = cap[8].toInt();
- const int minOffset = cap[9].toInt();
- result.utcOffset = ((hourOffset * 60 + minOffset) * (positiveOffset ? 60 : -60));
- }
- }
-
- return result;
-}
-#endif // datestring
-
-// Return offset in [+-]HH:mm format
-static QString toOffsetString(Qt::DateFormat format, int offset)
-{
- return QString::asprintf("%c%02d%s%02d",
- offset >= 0 ? '+' : '-',
- qAbs(offset) / SECS_PER_HOUR,
- // Qt::ISODate puts : between the hours and minutes, but Qt:TextDate does not:
- format == Qt::TextDate ? "" : ":",
- (qAbs(offset) / 60) % 60);
-}
-
-#if QT_CONFIG(datestring)
-// Parse offset in [+-]HH[[:]mm] format
-static int fromOffsetString(const QStringRef &offsetString, bool *valid) noexcept
-{
- *valid = false;
-
- const int size = offsetString.size();
- if (size < 2 || size > 6)
- return 0;
-
- // sign will be +1 for a positive and -1 for a negative offset
- int sign;
-
- // First char must be + or -
- const QChar signChar = offsetString.at(0);
- if (signChar == QLatin1Char('+'))
- sign = 1;
- else if (signChar == QLatin1Char('-'))
- sign = -1;
- else
- return 0;
-
- // Split the hour and minute parts
- const QStringRef time = offsetString.mid(1);
- int hhLen = time.indexOf(QLatin1Char(':'));
- int mmIndex;
- if (hhLen == -1)
- mmIndex = hhLen = 2; // [+-]HHmm or [+-]HH format
- else
- mmIndex = hhLen + 1;
-
- const QStringRef hhRef = time.left(hhLen);
- bool ok = false;
- const int hour = hhRef.toInt(&ok);
- if (!ok)
- return 0;
-
- const QStringRef mmRef = time.mid(mmIndex);
- const int minute = mmRef.isEmpty() ? 0 : mmRef.toInt(&ok);
- if (!ok || minute < 0 || minute > 59)
- return 0;
-
- *valid = true;
- return sign * ((hour * 60) + minute) * 60;
-}
-#endif // datestring
-
-static constexpr int daysInUsualMonth(int month) // (February isn't usual.)
-{
- // Long if odd up to July = 7, or if even from 8 = August onwards:
- return Q_ASSERT(month != 2 && month > 0 && month <= 12), 30 | ((month & 1) ^ (month >> 3));
-}
-
-/*****************************************************************************
- QDate member functions
- *****************************************************************************/
-
-/*!
- \since 4.5
-
- \enum QDate::MonthNameType
-
- This enum describes the types of the string representation used
- for the month name.
-
- \value DateFormat This type of name can be used for date-to-string formatting.
- \value StandaloneFormat This type is used when you need to enumerate months or weekdays.
- Usually standalone names are represented in singular forms with
- capitalized first letter.
-*/
-
-/*!
- \class QDate
- \inmodule QtCore
- \reentrant
- \brief The QDate class provides date functions.
-
-
- A QDate object encodes a calendar date, i.e. year, month, and day numbers,
- in the proleptic Gregorian calendar by default. It can read the current date
- from the system clock. It provides functions for comparing dates, and for
- manipulating dates. For example, it is possible to add and subtract days,
- months, and years to dates.
-
- A QDate object is typically created by giving the year, month, and day
- numbers explicitly. Note that QDate interprets two digit years as presented,
- i.e., as years 0 through 99, without adding any offset. A QDate can also be
- constructed with the static function currentDate(), which creates a QDate
- object containing the system clock's date. An explicit date can also be set
- using setDate(). The fromString() function returns a QDate given a string
- and a date format which is used to interpret the date within the string.
-
- The year(), month(), and day() functions provide access to the
- year, month, and day numbers. Also, dayOfWeek() and dayOfYear()
- functions are provided. The same information is provided in
- textual format by the toString(), shortDayName(), longDayName(),
- shortMonthName(), and longMonthName() functions.
-
- QDate provides a full set of operators to compare two QDate
- objects where smaller means earlier, and larger means later.
-
- You can increment (or decrement) a date by a given number of days
- using addDays(). Similarly you can use addMonths() and addYears().
- The daysTo() function returns the number of days between two
- dates.
-
- The daysInMonth() and daysInYear() functions return how many days
- there are in this date's month and year, respectively. The
- isLeapYear() function indicates whether a date is in a leap year.
-
- \section1 Remarks
-
- \section2 No Year 0
-
- There is no year 0. Dates in that year are considered invalid. The year -1
- is the year "1 before Christ" or "1 before current era." The day before 1
- January 1 CE, QDate(1, 1, 1), is 31 December 1 BCE, QDate(-1, 12, 31).
-
- \section2 Range of Valid Dates
-
- Dates are stored internally as a Julian Day number, an integer count of
- every day in a contiguous range, with 24 November 4714 BCE in the Gregorian
- calendar being Julian Day 0 (1 January 4713 BCE in the Julian calendar).
- As well as being an efficient and accurate way of storing an absolute date,
- it is suitable for converting a Date into other calendar systems such as
- Hebrew, Islamic or Chinese. The Julian Day number can be obtained using
- QDate::toJulianDay() and can be set using QDate::fromJulianDay().
-
- The range of dates able to be stored by QDate as a Julian Day number is
- for technical reasons limited to between -784350574879 and 784354017364,
- which means from before 2 billion BCE to after 2 billion CE.
-
- \sa QTime, QDateTime, QDateEdit, QDateTimeEdit, QCalendarWidget
-*/
-
-/*!
- \fn QDate::QDate()
-
- Constructs a null date. Null dates are invalid.
-
- \sa isNull(), isValid()
-*/
-
-/*!
- Constructs a date with year \a y, month \a m and day \a d.
-
- If the specified date is invalid, the date is not set and
- isValid() returns \c false.
-
- \warning Years 1 to 99 are interpreted as is. Year 0 is invalid.
-
- \sa isValid()
-*/
-
-QDate::QDate(int y, int m, int d)
-{
- setDate(y, m, d);
-}
-
-
-/*!
- \fn bool QDate::isNull() const
-
- Returns \c true if the date is null; otherwise returns \c false. A null
- date is invalid.
-
- \note The behavior of this function is equivalent to isValid().
-
- \sa isValid()
-*/
-
-/*!
- \fn bool QDate::isValid() const
-
- Returns \c true if this date is valid; otherwise returns \c false.
-
- \sa isNull()
-*/
-
-/*!
- Returns the year of this date. Negative numbers indicate years
- before 1 CE, such that year -44 is 44 BCE.
-
- Returns 0 if the date is invalid.
-
- \sa month(), day()
-*/
-
-int QDate::year() const
-{
- if (isNull())
- return 0;
-
- return getDateFromJulianDay(jd).year;
-}
-
-/*!
- Returns the number corresponding to the month of this date, using
- the following convention:
-
- \list
- \li 1 = "January"
- \li 2 = "February"
- \li 3 = "March"
- \li 4 = "April"
- \li 5 = "May"
- \li 6 = "June"
- \li 7 = "July"
- \li 8 = "August"
- \li 9 = "September"
- \li 10 = "October"
- \li 11 = "November"
- \li 12 = "December"
- \endlist
-
- Returns 0 if the date is invalid.
-
- \sa year(), day()
-*/
-
-int QDate::month() const
-{
- if (isNull())
- return 0;
-
- return getDateFromJulianDay(jd).month;
-}
-
-/*!
- Returns the day of the month (1 to 31) of this date.
-
- Returns 0 if the date is invalid.
-
- \sa year(), month(), dayOfWeek()
-*/
-
-int QDate::day() const
-{
- if (isNull())
- return 0;
-
- return getDateFromJulianDay(jd).day;
-}
-
-/*!
- Returns the weekday (1 = Monday to 7 = Sunday) for this date.
-
- Returns 0 if the date is invalid.
-
- \sa day(), dayOfYear(), Qt::DayOfWeek
-*/
-
-int QDate::dayOfWeek() const
-{
- if (isNull())
- return 0;
-
- if (jd >= 0)
- return (jd % 7) + 1;
- else
- return ((jd + 1) % 7) + 7;
-}
-
-/*!
- Returns the day of the year (1 to 365 or 366 on leap years) for
- this date.
-
- Returns 0 if the date is invalid.
-
- \sa day(), dayOfWeek()
-*/
-
-int QDate::dayOfYear() const
-{
- if (isNull())
- return 0;
-
- return jd - julianDayFromDate(year(), 1, 1) + 1;
-}
-
-/*!
- Returns the number of days in the month (28 to 31) for this date.
-
- Returns 0 if the date is invalid.
-
- \sa day(), daysInYear()
-*/
-
-int QDate::daysInMonth() const
-{
- if (isNull())
- return 0;
-
- const ParsedDate pd = getDateFromJulianDay(jd);
- if (pd.month == 2)
- return isLeapYear(pd.year) ? 29 : 28;
-
- return daysInUsualMonth(pd.month);
-}
-
-/*!
- Returns the number of days in the year (365 or 366) for this date.
-
- Returns 0 if the date is invalid.
-
- \sa day(), daysInMonth()
-*/
-
-int QDate::daysInYear() const
-{
- if (isNull())
- return 0;
-
- return isLeapYear(getDateFromJulianDay(jd).year) ? 366 : 365;
-}
-
-/*!
- Returns the week number (1 to 53), and stores the year in
- *\a{yearNumber} unless \a yearNumber is null (the default).
-
- Returns 0 if the date is invalid.
-
- In accordance with ISO 8601, weeks start on Monday and the first
- Thursday of a year is always in week 1 of that year. Most years
- have 52 weeks, but some have 53.
-
- *\a{yearNumber} is not always the same as year(). For example, 1
- January 2000 has week number 52 in the year 1999, and 31 December
- 2002 has week number 1 in the year 2003.
-
- \sa isValid()
-*/
-
-int QDate::weekNumber(int *yearNumber) const
-{
- if (!isValid())
- return 0;
-
- int year = QDate::year();
- int yday = dayOfYear();
- int wday = dayOfWeek();
-
- int week = (yday - wday + 10) / 7;
-
- if (week == 0) {
- // last week of previous year
- --year;
- week = (yday + 365 + (QDate::isLeapYear(year) ? 1 : 0) - wday + 10) / 7;
- Q_ASSERT(week == 52 || week == 53);
- } else if (week == 53) {
- // maybe first week of next year
- int w = (yday - 365 - (QDate::isLeapYear(year) ? 1 : 0) - wday + 10) / 7;
- if (w > 0) {
- ++year;
- week = w;
- }
- Q_ASSERT(week == 53 || week == 1);
- }
-
- if (yearNumber != 0)
- *yearNumber = year;
- return week;
-}
-
-static bool inDateTimeRange(qint64 jd, bool start)
-{
- using Bounds = std::numeric_limits<qint64>;
- if (jd < Bounds::min() + JULIAN_DAY_FOR_EPOCH)
- return false;
- jd -= JULIAN_DAY_FOR_EPOCH;
- const qint64 maxDay = Bounds::max() / MSECS_PER_DAY;
- const qint64 minDay = Bounds::min() / MSECS_PER_DAY - 1;
- // (Divisions rounded towards zero, as MSECS_PER_DAY has factors other than two.)
- // Range includes start of last day and end of first:
- if (start)
- return jd > minDay && jd <= maxDay;
- return jd >= minDay && jd < maxDay;
-}
-
-static QDateTime toEarliest(const QDate &day, const QDateTime &form)
-{
- const Qt::TimeSpec spec = form.timeSpec();
- const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0;
-#if QT_CONFIG(timezone)
- QTimeZone zone;
- if (spec == Qt::TimeZone)
- zone = form.timeZone();
-#endif
- auto moment = [=](QTime time) {
- switch (spec) {
- case Qt::OffsetFromUTC: return QDateTime(day, time, spec, offset);
-#if QT_CONFIG(timezone)
- case Qt::TimeZone: return QDateTime(day, time, zone);
-#endif
- default: return QDateTime(day, time, spec);
- }
- };
- // Longest routine time-zone transition is 2 hours:
- QDateTime when = moment(QTime(2, 0));
- if (!when.isValid()) {
- // Noon should be safe ...
- when = moment(QTime(12, 0));
- if (!when.isValid()) {
- // ... unless it's a 24-hour jump (moving the date-line)
- when = moment(QTime(23, 59, 59, 999));
- if (!when.isValid())
- return QDateTime();
- }
- }
- int high = when.time().msecsSinceStartOfDay() / 60000;
- int low = 0;
- // Binary chop to the right minute
- while (high > low + 1) {
- int mid = (high + low) / 2;
- QDateTime probe = moment(QTime(mid / 60, mid % 60));
- if (probe.isValid() && probe.date() == day) {
- high = mid;
- when = probe;
- } else {
- low = mid;
- }
- }
- return when;
-}
-
-/*!
- \since 5.14
- \fn QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const
- \fn QDateTime QDate::startOfDay(const QTimeZone &zone) const
-
- Returns the start-moment of the day. Usually, this shall be midnight at the
- start of the day: however, if a time-zone transition causes the given date
- to skip over that midnight (e.g. a DST spring-forward skipping from the end
- of the previous day to 01:00 of the new day), the actual earliest time in
- the day is returned. This can only arise when the start-moment is specified
- in terms of a time-zone (by passing its QTimeZone as \a zone) or in terms of
- local time (by passing Qt::LocalTime as \a spec; this is its default).
-
- The \a offsetSeconds is ignored unless \a spec is Qt::OffsetFromUTC, when it
- gives the implied zone's offset from UTC. As UTC and such zones have no
- transitions, the start of the day is QTime(0, 0) in these cases.
-
- In the rare case of a date that was entirely skipped (this happens when a
- zone east of the international date-line switches to being west of it), the
- return shall be invalid. Passing Qt::TimeZone as \a spec (instead of
- passing a QTimeZone) or passing an invalid time-zone as \a zone will also
- produce an invalid result, as shall dates that start outside the range
- representable by QDateTime.
-
- \sa endOfDay()
-*/
-QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const
-{
- if (!inDateTimeRange(jd, true))
- return QDateTime();
-
- switch (spec) {
- case Qt::TimeZone: // should pass a QTimeZone instead of Qt::TimeZone
- qWarning() << "Called QDate::startOfDay(Qt::TimeZone) on" << *this;
- return QDateTime();
- case Qt::OffsetFromUTC:
- case Qt::UTC:
- return QDateTime(*this, QTime(0, 0), spec, offsetSeconds);
-
- case Qt::LocalTime:
- if (offsetSeconds)
- qWarning("Ignoring offset (%d seconds) passed with Qt::LocalTime", offsetSeconds);
- break;
- }
- QDateTime when(*this, QTime(0, 0), spec);
- if (!when.isValid())
- when = toEarliest(*this, when);
-
- return when.isValid() ? when : QDateTime();
-}
-
-#if QT_CONFIG(timezone)
-/*!
- \overload
- \since 5.14
-*/
-QDateTime QDate::startOfDay(const QTimeZone &zone) const
-{
- if (!inDateTimeRange(jd, true) || !zone.isValid())
- return QDateTime();
-
- QDateTime when(*this, QTime(0, 0), zone);
- if (when.isValid())
- return when;
-
- // The start of the day must have fallen in a spring-forward's gap; find the spring-forward:
- if (zone.hasTransitions()) {
- QTimeZone::OffsetData tran = zone.previousTransition(QDateTime(*this, QTime(23, 59, 59, 999), zone));
- const QDateTime &at = tran.atUtc.toTimeZone(zone);
- if (at.isValid() && at.date() == *this)
- return at;
- }
-
- when = toEarliest(*this, when);
- return when.isValid() ? when : QDateTime();
-}
-#endif // timezone
-
-static QDateTime toLatest(const QDate &day, const QDateTime &form)
-{
- const Qt::TimeSpec spec = form.timeSpec();
- const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0;
-#if QT_CONFIG(timezone)
- QTimeZone zone;
- if (spec == Qt::TimeZone)
- zone = form.timeZone();
-#endif
- auto moment = [=](QTime time) {
- switch (spec) {
- case Qt::OffsetFromUTC: return QDateTime(day, time, spec, offset);
-#if QT_CONFIG(timezone)
- case Qt::TimeZone: return QDateTime(day, time, zone);
-#endif
- default: return QDateTime(day, time, spec);
- }
- };
- // Longest routine time-zone transition is 2 hours:
- QDateTime when = moment(QTime(21, 59, 59, 999));
- if (!when.isValid()) {
- // Noon should be safe ...
- when = moment(QTime(12, 0));
- if (!when.isValid()) {
- // ... unless it's a 24-hour jump (moving the date-line)
- when = moment(QTime(0, 0));
- if (!when.isValid())
- return QDateTime();
- }
- }
- int high = 24 * 60;
- int low = when.time().msecsSinceStartOfDay() / 60000;
- // Binary chop to the right minute
- while (high > low + 1) {
- int mid = (high + low) / 2;
- QDateTime probe = moment(QTime(mid / 60, mid % 60, 59, 999));
- if (probe.isValid() && probe.date() == day) {
- low = mid;
- when = probe;
- } else {
- high = mid;
- }
- }
- return when;
-}
-
-/*!
- \since 5.14
- \fn QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const
- \fn QDateTime QDate::endOfDay(const QTimeZone &zone) const
-
- Returns the end-moment of the day. Usually, this is one millisecond before
- the midnight at the end of the day: however, if a time-zone transition
- causes the given date to skip over that midnight (e.g. a DST spring-forward
- skipping from just before 23:00 to the start of the next day), the actual
- latest time in the day is returned. This can only arise when the
- start-moment is specified in terms of a time-zone (by passing its QTimeZone
- as \a zone) or in terms of local time (by passing Qt::LocalTime as \a spec;
- this is its default).
-
- The \a offsetSeconds is ignored unless \a spec is Qt::OffsetFromUTC, when it
- gives the implied zone's offset from UTC. As UTC and such zones have no
- transitions, the end of the day is QTime(23, 59, 59, 999) in these cases.
-
- In the rare case of a date that was entirely skipped (this happens when a
- zone east of the international date-line switches to being west of it), the
- return shall be invalid. Passing Qt::TimeZone as \a spec (instead of
- passing a QTimeZone) will also produce an invalid result, as shall dates
- that end outside the range representable by QDateTime.
-
- \sa startOfDay()
-*/
-QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const
-{
- if (!inDateTimeRange(jd, false))
- return QDateTime();
-
- switch (spec) {
- case Qt::TimeZone: // should pass a QTimeZone instead of Qt::TimeZone
- qWarning() << "Called QDate::endOfDay(Qt::TimeZone) on" << *this;
- return QDateTime();
- case Qt::UTC:
- case Qt::OffsetFromUTC:
- return QDateTime(*this, QTime(23, 59, 59, 999), spec, offsetSeconds);
-
- case Qt::LocalTime:
- if (offsetSeconds)
- qWarning("Ignoring offset (%d seconds) passed with Qt::LocalTime", offsetSeconds);
- break;
- }
- QDateTime when(*this, QTime(23, 59, 59, 999), spec);
- if (!when.isValid())
- when = toLatest(*this, when);
- return when.isValid() ? when : QDateTime();
-}
-
-#if QT_CONFIG(timezone)
-/*!
- \overload
- \since 5.14
-*/
-QDateTime QDate::endOfDay(const QTimeZone &zone) const
-{
- if (!inDateTimeRange(jd, false) || !zone.isValid())
- return QDateTime();
-
- QDateTime when(*this, QTime(23, 59, 59, 999), zone);
- if (when.isValid())
- return when;
-
- // The end of the day must have fallen in a spring-forward's gap; find the spring-forward:
- if (zone.hasTransitions()) {
- QTimeZone::OffsetData tran = zone.nextTransition(QDateTime(*this, QTime(0, 0), zone));
- const QDateTime &at = tran.atUtc.toTimeZone(zone);
- if (at.isValid() && at.date() == *this)
- return at;
- }
-
- when = toLatest(*this, when);
- return when.isValid() ? when : QDateTime();
-}
-#endif // timezone
-
-#if QT_DEPRECATED_SINCE(5, 11) && QT_CONFIG(textdate)
-
-/*!
- \since 4.5
- \deprecated
-
- Returns the short name of the \a month for the representation specified
- by \a type.
-
- The months are enumerated using the following convention:
-
- \list
- \li 1 = "Jan"
- \li 2 = "Feb"
- \li 3 = "Mar"
- \li 4 = "Apr"
- \li 5 = "May"
- \li 6 = "Jun"
- \li 7 = "Jul"
- \li 8 = "Aug"
- \li 9 = "Sep"
- \li 10 = "Oct"
- \li 11 = "Nov"
- \li 12 = "Dec"
- \endlist
-
- The month names will be localized according to the system's
- locale settings, i.e. using QLocale::system().
-
- Returns an empty string if the date is invalid.
-
- \sa toString(), longMonthName(), shortDayName(), longDayName()
-*/
-
-QString QDate::shortMonthName(int month, QDate::MonthNameType type)
-{
- switch (type) {
- case QDate::DateFormat:
- return QLocale::system().monthName(month, QLocale::ShortFormat);
- case QDate::StandaloneFormat:
- return QLocale::system().standaloneMonthName(month, QLocale::ShortFormat);
- }
- return QString();
-}
-
-/*!
- \since 4.5
- \deprecated
-
- Returns the long name of the \a month for the representation specified
- by \a type.
-
- The months are enumerated using the following convention:
-
- \list
- \li 1 = "January"
- \li 2 = "February"
- \li 3 = "March"
- \li 4 = "April"
- \li 5 = "May"
- \li 6 = "June"
- \li 7 = "July"
- \li 8 = "August"
- \li 9 = "September"
- \li 10 = "October"
- \li 11 = "November"
- \li 12 = "December"
- \endlist
-
- The month names will be localized according to the system's
- locale settings, i.e. using QLocale::system().
-
- Returns an empty string if the date is invalid.
-
- \sa toString(), shortMonthName(), shortDayName(), longDayName()
-*/
-
-QString QDate::longMonthName(int month, MonthNameType type)
-{
- switch (type) {
- case QDate::DateFormat:
- return QLocale::system().monthName(month, QLocale::LongFormat);
- case QDate::StandaloneFormat:
- return QLocale::system().standaloneMonthName(month, QLocale::LongFormat);
- }
- return QString();
-}
-
-/*!
- \since 4.5
- \deprecated
-
- Returns the short name of the \a weekday for the representation specified
- by \a type.
-
- The days are enumerated using the following convention:
-
- \list
- \li 1 = "Mon"
- \li 2 = "Tue"
- \li 3 = "Wed"
- \li 4 = "Thu"
- \li 5 = "Fri"
- \li 6 = "Sat"
- \li 7 = "Sun"
- \endlist
-
- The day names will be localized according to the system's
- locale settings, i.e. using QLocale::system().
-
- Returns an empty string if the date is invalid.
-
- \sa toString(), shortMonthName(), longMonthName(), longDayName()
-*/
-
-QString QDate::shortDayName(int weekday, MonthNameType type)
-{
- switch (type) {
- case QDate::DateFormat:
- return QLocale::system().dayName(weekday, QLocale::ShortFormat);
- case QDate::StandaloneFormat:
- return QLocale::system().standaloneDayName(weekday, QLocale::ShortFormat);
- }
- return QString();
-}
-
-/*!
- \since 4.5
- \deprecated
-
- Returns the long name of the \a weekday for the representation specified
- by \a type.
-
- The days are enumerated using the following convention:
-
- \list
- \li 1 = "Monday"
- \li 2 = "Tuesday"
- \li 3 = "Wednesday"
- \li 4 = "Thursday"
- \li 5 = "Friday"
- \li 6 = "Saturday"
- \li 7 = "Sunday"
- \endlist
-
- The day names will be localized according to the system's
- locale settings, i.e. using QLocale::system().
-
- Returns an empty string if the date is invalid.
-
- \sa toString(), shortDayName(), shortMonthName(), longMonthName()
-*/
-
-QString QDate::longDayName(int weekday, MonthNameType type)
-{
- switch (type) {
- case QDate::DateFormat:
- return QLocale::system().dayName(weekday, QLocale::LongFormat);
- case QDate::StandaloneFormat:
- return QLocale::system().standaloneDayName(weekday, QLocale::LongFormat);
- }
- return QString();
-}
-#endif // textdate && deprecated
-
-#if QT_CONFIG(datestring)
-
-#if QT_CONFIG(textdate)
-static QString toStringTextDate(QDate date)
-{
- const ParsedDate pd = getDateFromJulianDay(date.toJulianDay());
- static const QLatin1Char sp(' ');
- return QLocale::system().dayName(date.dayOfWeek(), QLocale::ShortFormat) + sp
- + QLocale::system().monthName(pd.month, QLocale::ShortFormat) + sp
- + QString::number(pd.day) + sp
- + QString::number(pd.year);
-}
-#endif // textdate
-
-static QString toStringIsoDate(qint64 jd)
-{
- const ParsedDate pd = getDateFromJulianDay(jd);
- if (pd.year >= 0 && pd.year <= 9999)
- return QString::asprintf("%04d-%02d-%02d", pd.year, pd.month, pd.day);
- else
- return QString();
-}
-
-/*!
- \fn QString QDate::toString(Qt::DateFormat format) const
-
- \overload
-
- Returns the date as a string. The \a format parameter determines
- the format of the string.
-
- If the \a format is Qt::TextDate, the string is formatted in
- the default way. QDate::shortDayName() and QDate::shortMonthName()
- are used to generate the string, so the day and month names will
- be localized names using the system locale, i.e. QLocale::system(). An
- example of this formatting is "Sat May 20 1995".
-
- If the \a format is Qt::ISODate, the string format corresponds
- to the ISO 8601 extended specification for representations of
- dates and times, taking the form yyyy-MM-dd, where yyyy is the
- year, MM is the month of the year (between 01 and 12), and dd is
- the day of the month between 01 and 31.
-
- If the \a format is Qt::SystemLocaleShortDate or
- Qt::SystemLocaleLongDate, the string format depends on the locale
- settings of the system. Identical to calling
- QLocale::system().toString(date, QLocale::ShortFormat) or
- QLocale::system().toString(date, QLocale::LongFormat).
-
- If the \a format is Qt::DefaultLocaleShortDate or
- Qt::DefaultLocaleLongDate, the string format depends on the
- default application locale. This is the locale set with
- QLocale::setDefault(), or the system locale if no default locale
- has been set. Identical to calling
- \l {QLocale::toString()}{QLocale().toString(date, QLocale::ShortFormat) } or
- \l {QLocale::toString()}{QLocale().toString(date, QLocale::LongFormat)}.
-
- If the \a format is Qt::RFC2822Date, the string is formatted in
- an \l{RFC 2822} compatible way. An example of this formatting is
- "20 May 1995".
-
- If the date is invalid, an empty string will be returned.
-
- \warning The Qt::ISODate format is only valid for years in the
- range 0 to 9999. This restriction may apply to locale-aware
- formats as well, depending on the locale settings.
-
- \sa fromString(), shortDayName(), shortMonthName(), QLocale::toString()
-*/
-QString QDate::toString(Qt::DateFormat format) const
-{
- if (!isValid())
- return QString();
-
- switch (format) {
- case Qt::SystemLocaleDate:
- case Qt::SystemLocaleShortDate:
- return QLocale::system().toString(*this, QLocale::ShortFormat);
- case Qt::SystemLocaleLongDate:
- return QLocale::system().toString(*this, QLocale::LongFormat);
- case Qt::LocaleDate:
- case Qt::DefaultLocaleShortDate:
- return QLocale().toString(*this, QLocale::ShortFormat);
- case Qt::DefaultLocaleLongDate:
- return QLocale().toString(*this, QLocale::LongFormat);
- case Qt::RFC2822Date:
- return QLocale::c().toString(*this, QStringViewLiteral("dd MMM yyyy"));
- default:
-#if QT_CONFIG(textdate)
- case Qt::TextDate:
- return toStringTextDate(*this);
-#endif
- case Qt::ISODate:
- case Qt::ISODateWithMs:
- return toStringIsoDate(jd);
- }
-}
-
-/*!
- \fn QString QDate::toString(const QString &format) const
- \fn QString QDate::toString(QStringView format) const
-
- Returns the date as a string. The \a format parameter determines
- the format of the result string.
-
- These expressions may be used:
-
- \table
- \header \li Expression \li Output
- \row \li d \li the day as number without a leading zero (1 to 31)
- \row \li dd \li the day as number with a leading zero (01 to 31)
- \row \li ddd
- \li the abbreviated localized day name (e.g. 'Mon' to 'Sun').
- Uses the system locale to localize the name, i.e. QLocale::system().
- \row \li dddd
- \li the long localized day name (e.g. 'Monday' to 'Sunday').
- Uses the system locale to localize the name, i.e. QLocale::system().
- \row \li M \li the month as number without a leading zero (1 to 12)
- \row \li MM \li the month as number with a leading zero (01 to 12)
- \row \li MMM
- \li the abbreviated localized month name (e.g. 'Jan' to 'Dec').
- Uses the system locale to localize the name, i.e. QLocale::system().
- \row \li MMMM
- \li the long localized month name (e.g. 'January' to 'December').
- Uses the system locale to localize the name, i.e. QLocale::system().
- \row \li yy \li the year as two digit number (00 to 99)
- \row \li yyyy \li the year as four digit number. If the year is negative,
- a minus sign is prepended in addition.
- \endtable
-
- Any sequence of characters enclosed in single quotes will be included
- verbatim in the output string (stripped of the quotes), even if it contains
- formatting characters. Two consecutive single quotes ("''") are replaced by
- a single quote in the output. All other characters in the format string are
- included verbatim in the output string.
-
- Formats without separators (e.g. "ddMM") are supported but must be used with
- care, as the resulting strings aren't always reliably readable (e.g. if "dM"
- produces "212" it could mean either the 2nd of December or the 21st of
- February).
-
- Example format strings (assuming that the QDate is the 20 July
- 1969):
-
- \table
- \header \li Format \li Result
- \row \li dd.MM.yyyy \li 20.07.1969
- \row \li ddd MMMM d yy \li Sun July 20 69
- \row \li 'The day is' dddd \li The day is Sunday
- \endtable
-
- If the datetime is invalid, an empty string will be returned.
-
- \sa fromString(), QDateTime::toString(), QTime::toString(), QLocale::toString()
-
-*/
-QString QDate::toString(QStringView format) const
-{
- return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
-}
-
-#if QT_STRINGVIEW_LEVEL < 2
-QString QDate::toString(const QString &format) const
-{
- return toString(qToStringViewIgnoringNull(format));
-}
-#endif
-
-#endif // datestring
-
-/*!
- \fn bool QDate::setYMD(int y, int m, int d)
-
- \deprecated in 5.0, use setDate() instead.
-
- Sets the date's year \a y, month \a m, and day \a d.
-
- If \a y is in the range 0 to 99, it is interpreted as 1900 to
- 1999.
- Returns \c false if the date is invalid.
-
- Use setDate() instead.
-*/
-
-/*!
- \since 4.2
-
- Sets the date's \a year, \a month, and \a day. Returns \c true if
- the date is valid; otherwise returns \c false.
-
- If the specified date is invalid, the QDate object is set to be
- invalid.
-
- \sa isValid()
-*/
-bool QDate::setDate(int year, int month, int day)
-{
- if (isValid(year, month, day))
- jd = julianDayFromDate(year, month, day);
- else
- jd = nullJd();
-
- return isValid();
-}
-
-/*!
- \since 4.5
-
- Extracts the date's year, month, and day, and assigns them to
- *\a year, *\a month, and *\a day. The pointers may be null.
-
- Returns 0 if the date is invalid.
-
- \note In Qt versions prior to 5.7, this function is marked as non-\c{const}.
-
- \sa year(), month(), day(), isValid()
-*/
-void QDate::getDate(int *year, int *month, int *day) const
-{
- ParsedDate pd = { 0, 0, 0 };
- if (isValid())
- pd = getDateFromJulianDay(jd);
-
- if (year)
- *year = pd.year;
- if (month)
- *month = pd.month;
- if (day)
- *day = pd.day;
-}
-
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/*!
- \overload
- \internal
-*/
-void QDate::getDate(int *year, int *month, int *day)
-{
- qAsConst(*this).getDate(year, month, day);
-}
-#endif // < Qt 6
-
-/*!
- Returns a QDate object containing a date \a ndays later than the
- date of this object (or earlier if \a ndays is negative).
-
- Returns a null date if the current date is invalid or the new date is
- out of range.
-
- \sa addMonths(), addYears(), daysTo()
-*/
-
-QDate QDate::addDays(qint64 ndays) const
-{
- if (isNull())
- return QDate();
-
- // Due to limits on minJd() and maxJd() we know that any overflow
- // will be invalid and caught by fromJulianDay().
- return fromJulianDay(jd + ndays);
-}
-
-/*!
- Returns a QDate object containing a date \a nmonths later than the
- date of this object (or earlier if \a nmonths is negative).
-
- \note If the ending day/month combination does not exist in the
- resulting month/year, this function will return a date that is the
- latest valid date.
-
- \sa addDays(), addYears()
-*/
-
-QDate QDate::addMonths(int nmonths) const
-{
- if (!isValid())
- return QDate();
- if (!nmonths)
- return *this;
-
- int old_y, y, m, d;
- {
- const ParsedDate pd = getDateFromJulianDay(jd);
- y = pd.year;
- m = pd.month;
- d = pd.day;
- }
- old_y = y;
-
- bool increasing = nmonths > 0;
-
- while (nmonths != 0) {
- if (nmonths < 0 && nmonths + 12 <= 0) {
- y--;
- nmonths+=12;
- } else if (nmonths < 0) {
- m+= nmonths;
- nmonths = 0;
- if (m <= 0) {
- --y;
- m += 12;
- }
- } else if (nmonths - 12 >= 0) {
- y++;
- nmonths -= 12;
- } else if (m == 12) {
- y++;
- m = 0;
- } else {
- m += nmonths;
- nmonths = 0;
- if (m > 12) {
- ++y;
- m -= 12;
- }
- }
- }
-
- // was there a sign change?
- if ((old_y > 0 && y <= 0) ||
- (old_y < 0 && y >= 0))
- // yes, adjust the date by +1 or -1 years
- y += increasing ? +1 : -1;
-
- return fixedDate(y, m, d);
-}
-
-/*!
- Returns a QDate object containing a date \a nyears later than the
- date of this object (or earlier if \a nyears is negative).
-
- \note If the ending day/month combination does not exist in the
- resulting year (i.e., if the date was Feb 29 and the final year is
- not a leap year), this function will return a date that is the
- latest valid date (that is, Feb 28).
-
- \sa addDays(), addMonths()
-*/
-
-QDate QDate::addYears(int nyears) const
-{
- if (!isValid())
- return QDate();
-
- ParsedDate pd = getDateFromJulianDay(jd);
-
- int old_y = pd.year;
- pd.year += nyears;
-
- // was there a sign change?
- if ((old_y > 0 && pd.year <= 0) ||
- (old_y < 0 && pd.year >= 0))
- // yes, adjust the date by +1 or -1 years
- pd.year += nyears > 0 ? +1 : -1;
-
- return fixedDate(pd.year, pd.month, pd.day);
-}
-
-/*!
- Returns the number of days from this date to \a d (which is
- negative if \a d is earlier than this date).
-
- Returns 0 if either date is invalid.
-
- Example:
- \snippet code/src_corelib_tools_qdatetime.cpp 0
-
- \sa addDays()
-*/
-
-qint64 QDate::daysTo(const QDate &d) const
-{
- if (isNull() || d.isNull())
- return 0;
-
- // Due to limits on minJd() and maxJd() we know this will never overflow
- return d.jd - jd;
-}
-
-
-/*!
- \fn bool QDate::operator==(const QDate &d) const
-
- Returns \c true if this date is equal to \a d; otherwise returns
- false.
-
-*/
-
-/*!
- \fn bool QDate::operator!=(const QDate &d) const
-
- Returns \c true if this date is different from \a d; otherwise
- returns \c false.
-*/
-
-/*!
- \fn bool QDate::operator<(const QDate &d) const
-
- Returns \c true if this date is earlier than \a d; otherwise returns
- false.
-*/
-
-/*!
- \fn bool QDate::operator<=(const QDate &d) const
-
- Returns \c true if this date is earlier than or equal to \a d;
- otherwise returns \c false.
-*/
-
-/*!
- \fn bool QDate::operator>(const QDate &d) const
-
- Returns \c true if this date is later than \a d; otherwise returns
- false.
-*/
-
-/*!
- \fn bool QDate::operator>=(const QDate &d) const
-
- Returns \c true if this date is later than or equal to \a d;
- otherwise returns \c false.
-*/
-
-/*!
- \fn QDate::currentDate()
- Returns the current date, as reported by the system clock.
-
- \sa QTime::currentTime(), QDateTime::currentDateTime()
-*/
-
-#if QT_CONFIG(datestring)
-/*!
- Returns the QDate represented by the \a string, using the
- \a format given, or an invalid date if the string cannot be
- parsed.
-
- Note for Qt::TextDate: It is recommended that you use the
- English short month names (e.g. "Jan"). Although localized month
- names can also be used, they depend on the user's locale settings.
-
- \sa toString(), QLocale::toDate()
-*/
-
-QDate QDate::fromString(const QString &string, Qt::DateFormat format)
-{
- if (string.isEmpty())
- return QDate();
-
- switch (format) {
- case Qt::SystemLocaleDate:
- case Qt::SystemLocaleShortDate:
- return QLocale::system().toDate(string, QLocale::ShortFormat);
- case Qt::SystemLocaleLongDate:
- return QLocale::system().toDate(string, QLocale::LongFormat);
- case Qt::LocaleDate:
- case Qt::DefaultLocaleShortDate:
- return QLocale().toDate(string, QLocale::ShortFormat);
- case Qt::DefaultLocaleLongDate:
- return QLocale().toDate(string, QLocale::LongFormat);
- case Qt::RFC2822Date:
- return rfcDateImpl(string).date;
- default:
-#if QT_CONFIG(textdate)
- case Qt::TextDate: {
- QVector<QStringRef> parts = string.splitRef(QLatin1Char(' '), QString::SkipEmptyParts);
-
- if (parts.count() != 4)
- return QDate();
-
- QStringRef monthName = parts.at(1);
- const int month = fromShortMonthName(monthName);
- if (month == -1) {
- // Month name matches neither English nor other localised name.
- return QDate();
- }
-
- bool ok = false;
- int year = parts.at(3).toInt(&ok);
- if (!ok)
- return QDate();
-
- return QDate(year, month, parts.at(2).toInt());
- }
-#endif // textdate
- case Qt::ISODate: {
- // Semi-strict parsing, must be long enough and have non-numeric separators
- if (string.size() < 10 || string.at(4).isDigit() || string.at(7).isDigit()
- || (string.size() > 10 && string.at(10).isDigit())) {
- return QDate();
- }
- const int year = string.midRef(0, 4).toInt();
- if (year <= 0 || year > 9999)
- return QDate();
- return QDate(year, string.midRef(5, 2).toInt(), string.midRef(8, 2).toInt());
- }
- }
- return QDate();
-}
-
-/*!
- Returns the QDate represented by the \a string, using the \a
- format given, or an invalid date if the string cannot be parsed.
-
- These expressions may be used for the format:
-
- \table
- \header \li Expression \li Output
- \row \li d \li The day as a number without a leading zero (1 to 31)
- \row \li dd \li The day as a number with a leading zero (01 to 31)
- \row \li ddd
- \li The abbreviated localized day name (e.g. 'Mon' to 'Sun').
- Uses the system locale to localize the name, i.e. QLocale::system().
- \row \li dddd
- \li The long localized day name (e.g. 'Monday' to 'Sunday').
- Uses the system locale to localize the name, i.e. QLocale::system().
- \row \li M \li The month as a number without a leading zero (1 to 12)
- \row \li MM \li The month as a number with a leading zero (01 to 12)
- \row \li MMM
- \li The abbreviated localized month name (e.g. 'Jan' to 'Dec').
- Uses the system locale to localize the name, i.e. QLocale::system().
- \row \li MMMM
- \li The long localized month name (e.g. 'January' to 'December').
- Uses the system locale to localize the name, i.e. QLocale::system().
- \row \li yy \li The year as two digit number (00 to 99)
- \row \li yyyy \li The year as four digit number. If the year is negative,
- a minus sign is prepended in addition.
- \endtable
-
- All other input characters will be treated as text. Any sequence
- of characters that are enclosed in single quotes will also be
- treated as text and will not be used as an expression. For example:
-
- \snippet code/src_corelib_tools_qdatetime.cpp 1
-
- If the format is not satisfied, an invalid QDate is returned. The
- expressions that don't expect leading zeroes (d, M) will be
- greedy. This means that they will use two digits even if this
- will put them outside the accepted range of values and leaves too
- few digits for other sections. For example, the following format
- string could have meant January 30 but the M will grab two
- digits, resulting in an invalid date:
-
- \snippet code/src_corelib_tools_qdatetime.cpp 2
-
- For any field that is not represented in the format the following
- defaults are used:
-
- \table
- \header \li Field \li Default value
- \row \li Year \li 1900
- \row \li Month \li 1
- \row \li Day \li 1
- \endtable
-
- The following examples demonstrate the default values:
-
- \snippet code/src_corelib_tools_qdatetime.cpp 3
-
- \sa toString(), QDateTime::fromString(), QTime::fromString(),
- QLocale::toDate()
-*/
-
-QDate QDate::fromString(const QString &string, const QString &format)
-{
- QDate date;
-#if QT_CONFIG(datetimeparser)
- QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString);
- // dt.setDefaultLocale(QLocale::c()); ### Qt 6
- if (dt.parseFormat(format))
- dt.fromString(string, &date, 0);
-#else
- Q_UNUSED(string);
- Q_UNUSED(format);
-#endif
- return date;
-}
-#endif // datestring
-
-/*!
- \overload
-
- Returns \c true if the specified date (\a year, \a month, and \a
- day) is valid; otherwise returns \c false.
-
- Example:
- \snippet code/src_corelib_tools_qdatetime.cpp 4
-
- \sa isNull(), setDate()
-*/
-
-bool QDate::isValid(int year, int month, int day)
-{
- // There is no year 0 in the Gregorian calendar.
- return year && day > 0 && month > 0 && month <= 12 &&
- day <= (month == 2 ? isLeapYear(year) ? 29 : 28 : daysInUsualMonth(month));
-}
-
-/*!
- \fn bool QDate::isLeapYear(int year)
-
- Returns \c true if the specified \a year is a leap year; otherwise
- returns \c false.
-*/
-
-bool QDate::isLeapYear(int y)
-{
- // No year 0 in Gregorian calendar, so -1, -5, -9 etc are leap years
- if ( y < 1)
- ++y;
-
- return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
-}
-
-/*! \fn static QDate QDate::fromJulianDay(qint64 jd)
-
- Converts the Julian day \a jd to a QDate.
-
- \sa toJulianDay()
-*/
-
-/*! \fn int QDate::toJulianDay() const
-
- Converts the date to a Julian day.
-
- \sa fromJulianDay()
-*/
-
-/*****************************************************************************
- QTime member functions
- *****************************************************************************/
-
-/*!
- \class QTime
- \inmodule QtCore
- \reentrant
-
- \brief The QTime class provides clock time functions.
-
-
- A QTime object contains a clock time, which it can express as the numbers of
- hours, minutes, seconds, and milliseconds since midnight. It provides
- functions for comparing times and for manipulating a time by adding a number
- of milliseconds.
-
- QTime uses the 24-hour clock format; it has no concept of AM/PM.
- Unlike QDateTime, QTime knows nothing about time zones or
- daylight-saving time (DST).
-
- A QTime object is typically created either by giving the number
- of hours, minutes, seconds, and milliseconds explicitly, or by
- using the static function currentTime(), which creates a QTime
- object that contains the system's local time. Note that the
- accuracy depends on the accuracy of the underlying operating
- system; not all systems provide 1-millisecond accuracy.
-
- The hour(), minute(), second(), and msec() functions provide
- access to the number of hours, minutes, seconds, and milliseconds
- of the time. The same information is provided in textual format by
- the toString() function.
-
- The addSecs() and addMSecs() functions provide the time a given
- number of seconds or milliseconds later than a given time.
- Correspondingly, the number of seconds or milliseconds
- between two times can be found using secsTo() or msecsTo().
-
- QTime provides a full set of operators to compare two QTime
- objects; an earlier time is considered smaller than a later one;
- if A.msecsTo(B) is positive, then A < B.
-
- \sa QDate, QDateTime
-*/
-
-/*!
- \fn QTime::QTime()
-
- Constructs a null time object. For a null time, isNull() returns \c true and
- isValid() returns \c false. If you need a zero time, use QTime(0, 0). For
- the start of a day, see QDate::startOfDay().
-
- \sa isNull(), isValid()
-*/
-
-/*!
- Constructs a time with hour \a h, minute \a m, seconds \a s and
- milliseconds \a ms.
-
- \a h must be in the range 0 to 23, \a m and \a s must be in the
- range 0 to 59, and \a ms must be in the range 0 to 999.
-
- \sa isValid()
-*/
-
-QTime::QTime(int h, int m, int s, int ms)
-{
- setHMS(h, m, s, ms);
-}
-
-
-/*!
- \fn bool QTime::isNull() const
-
- Returns \c true if the time is null (i.e., the QTime object was
- constructed using the default constructor); otherwise returns
- false. A null time is also an invalid time.
-
- \sa isValid()
-*/
-
-/*!
- Returns \c true if the time is valid; otherwise returns \c false. For example,
- the time 23:30:55.746 is valid, but 24:12:30 is invalid.
-
- \sa isNull()
-*/
-
-bool QTime::isValid() const
-{
- return mds > NullTime && mds < MSECS_PER_DAY;
-}
-
-
-/*!
- Returns the hour part (0 to 23) of the time.
-
- Returns -1 if the time is invalid.
-
- \sa minute(), second(), msec()
-*/
-
-int QTime::hour() const
-{
- if (!isValid())
- return -1;
-
- return ds() / MSECS_PER_HOUR;
-}
-
-/*!
- Returns the minute part (0 to 59) of the time.
-
- Returns -1 if the time is invalid.
-
- \sa hour(), second(), msec()
-*/
-
-int QTime::minute() const
-{
- if (!isValid())
- return -1;
-
- return (ds() % MSECS_PER_HOUR) / MSECS_PER_MIN;
-}
-
-/*!
- Returns the second part (0 to 59) of the time.
-
- Returns -1 if the time is invalid.
-
- \sa hour(), minute(), msec()
-*/
-
-int QTime::second() const
-{
- if (!isValid())
- return -1;
-
- return (ds() / 1000)%SECS_PER_MIN;
-}
-
-/*!
- Returns the millisecond part (0 to 999) of the time.
-
- Returns -1 if the time is invalid.
-
- \sa hour(), minute(), second()
-*/
-
-int QTime::msec() const
-{
- if (!isValid())
- return -1;
-
- return ds() % 1000;
-}
-
-#if QT_CONFIG(datestring)
-/*!
- \overload
-
- Returns the time as a string. The \a format parameter determines
- the format of the string.
-
- If \a format is Qt::TextDate, the string format is HH:mm:ss;
- e.g. 1 second before midnight would be "23:59:59".
-
- If \a format is Qt::ISODate, the string format corresponds to the
- ISO 8601 extended specification for representations of dates,
- represented by HH:mm:ss. To include milliseconds in the ISO 8601
- date, use the \a format Qt::ISODateWithMs, which corresponds to
- HH:mm:ss.zzz.
-
- If the \a format is Qt::SystemLocaleShortDate or
- Qt::SystemLocaleLongDate, the string format depends on the locale
- settings of the system. Identical to calling
- QLocale::system().toString(time, QLocale::ShortFormat) or
- QLocale::system().toString(time, QLocale::LongFormat).
-
- If the \a format is Qt::DefaultLocaleShortDate or
- Qt::DefaultLocaleLongDate, the string format depends on the
- default application locale. This is the locale set with
- QLocale::setDefault(), or the system locale if no default locale
- has been set. Identical to calling
-
- \l {QLocale::toString()}{QLocale().toString(time, QLocale::ShortFormat)} or
- \l {QLocale::toString()}{QLocale().toString(time, QLocale::LongFormat)}.
-
- If the \a format is Qt::RFC2822Date, the string is formatted in
- an \l{RFC 2822} compatible way. An example of this formatting is
- "23:59:20".
-
- If the time is invalid, an empty string will be returned.
-
- \sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
-*/
-
-QString QTime::toString(Qt::DateFormat format) const
-{
- if (!isValid())
- return QString();
-
- switch (format) {
- case Qt::SystemLocaleDate:
- case Qt::SystemLocaleShortDate:
- return QLocale::system().toString(*this, QLocale::ShortFormat);
- case Qt::SystemLocaleLongDate:
- return QLocale::system().toString(*this, QLocale::LongFormat);
- case Qt::LocaleDate:
- case Qt::DefaultLocaleShortDate:
- return QLocale().toString(*this, QLocale::ShortFormat);
- case Qt::DefaultLocaleLongDate:
- return QLocale().toString(*this, QLocale::LongFormat);
- case Qt::ISODateWithMs:
- return QString::asprintf("%02d:%02d:%02d.%03d", hour(), minute(), second(), msec());
- case Qt::RFC2822Date:
- case Qt::ISODate:
- case Qt::TextDate:
- default:
- return QString::asprintf("%02d:%02d:%02d", hour(), minute(), second());
- }
-}
-
-/*!
- \fn QString QTime::toString(const QString &format) const
- \fn QString QTime::toString(QStringView format) const
-
- Returns the time as a string. The \a format parameter determines
- the format of the result string.
-
- These expressions may be used:
-
- \table
- \header \li Expression \li Output
- \row \li h
- \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
- \row \li hh
- \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
- \row \li H
- \li the hour without a leading zero (0 to 23, even with AM/PM display)
- \row \li HH
- \li the hour with a leading zero (00 to 23, even with AM/PM display)
- \row \li m \li the minute without a leading zero (0 to 59)
- \row \li mm \li the minute with a leading zero (00 to 59)
- \row \li s \li the whole second, without any leading zero (0 to 59)
- \row \li ss \li the whole second, with a leading zero where applicable (00 to 59)
- \row \li z \li the fractional part of the second, to go after a decimal
- point, without trailing zeroes (0 to 999). Thus "\c{s.z}"
- reports the seconds to full available (millisecond) precision
- without trailing zeroes.
- \row \li zzz \li the fractional part of the second, to millisecond
- precision, including trailing zeroes where applicable (000 to 999).
- \row \li AP or A
- \li use AM/PM display. \e A/AP will be replaced by either
- QLocale::amText() or QLocale::pmText().
- \row \li ap or a
- \li use am/pm display. \e a/ap will be replaced by a lower-case version of
- QLocale::amText() or QLocale::pmText().
- \row \li t \li the timezone (for example "CEST")
- \endtable
-
- Any sequence of characters enclosed in single quotes will be included
- verbatim in the output string (stripped of the quotes), even if it contains
- formatting characters. Two consecutive single quotes ("''") are replaced by
- a single quote in the output. All other characters in the format string are
- included verbatim in the output string.
-
- Formats without separators (e.g. "ddMM") are supported but must be used with
- care, as the resulting strings aren't always reliably readable (e.g. if "dM"
- produces "212" it could mean either the 2nd of December or the 21st of
- February).
-
- Example format strings (assuming that the QTime is 14:13:09.042 and the system
- locale is \c{en_US})
-
- \table
- \header \li Format \li Result
- \row \li hh:mm:ss.zzz \li 14:13:09.042
- \row \li h:m:s ap \li 2:13:9 pm
- \row \li H:m:s a \li 14:13:9 pm
- \endtable
-
- If the time is invalid, an empty string will be returned.
- If \a format is empty, the default format "hh:mm:ss" is used.
-
- \sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
-*/
-QString QTime::toString(QStringView format) const
-{
- return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
-}
-
-#if QT_STRINGVIEW_VERSION < 2
-QString QTime::toString(const QString &format) const
-{
- return toString(qToStringViewIgnoringNull(format));
-}
-#endif
-
-#endif // datestring
-
-/*!
- Sets the time to hour \a h, minute \a m, seconds \a s and
- milliseconds \a ms.
-
- \a h must be in the range 0 to 23, \a m and \a s must be in the
- range 0 to 59, and \a ms must be in the range 0 to 999.
- Returns \c true if the set time is valid; otherwise returns \c false.
-
- \sa isValid()
-*/
-
-bool QTime::setHMS(int h, int m, int s, int ms)
-{
- if (!isValid(h,m,s,ms)) {
- mds = NullTime; // make this invalid
- return false;
- }
- mds = (h*SECS_PER_HOUR + m*SECS_PER_MIN + s)*1000 + ms;
- return true;
-}
-
-/*!
- Returns a QTime object containing a time \a s seconds later
- than the time of this object (or earlier if \a s is negative).
-
- Note that the time will wrap if it passes midnight.
-
- Returns a null time if this time is invalid.
-
- Example:
-
- \snippet code/src_corelib_tools_qdatetime.cpp 5
-
- \sa addMSecs(), secsTo(), QDateTime::addSecs()
-*/
-
-QTime QTime::addSecs(int s) const
-{
- s %= SECS_PER_DAY;
- return addMSecs(s * 1000);
-}
-
-/*!
- Returns the number of seconds from this time to \a t.
- If \a t is earlier than this time, the number of seconds returned
- is negative.
-
- Because QTime measures time within a day and there are 86400
- seconds in a day, the result is always between -86400 and 86400.
-
- secsTo() does not take into account any milliseconds.
-
- Returns 0 if either time is invalid.
-
- \sa addSecs(), QDateTime::secsTo()
-*/
-
-int QTime::secsTo(const QTime &t) const
-{
- if (!isValid() || !t.isValid())
- return 0;
-
- // Truncate milliseconds as we do not want to consider them.
- int ourSeconds = ds() / 1000;
- int theirSeconds = t.ds() / 1000;
- return theirSeconds - ourSeconds;
-}
-
-/*!
- Returns a QTime object containing a time \a ms milliseconds later
- than the time of this object (or earlier if \a ms is negative).
-
- Note that the time will wrap if it passes midnight. See addSecs()
- for an example.
-
- Returns a null time if this time is invalid.
-
- \sa addSecs(), msecsTo(), QDateTime::addMSecs()
-*/
-
-QTime QTime::addMSecs(int ms) const
-{
- QTime t;
- if (isValid()) {
- if (ms < 0) {
- // %,/ not well-defined for -ve, so always work with +ve.
- int negdays = (MSECS_PER_DAY - ms) / MSECS_PER_DAY;
- t.mds = (ds() + ms + negdays * MSECS_PER_DAY) % MSECS_PER_DAY;
- } else {
- t.mds = (ds() + ms) % MSECS_PER_DAY;
- }
- }
- return t;
-}
-
-/*!
- Returns the number of milliseconds from this time to \a t.
- If \a t is earlier than this time, the number of milliseconds returned
- is negative.
-
- Because QTime measures time within a day and there are 86400
- seconds in a day, the result is always between -86400000 and
- 86400000 ms.
-
- Returns 0 if either time is invalid.
-
- \sa secsTo(), addMSecs(), QDateTime::msecsTo()
-*/
-
-int QTime::msecsTo(const QTime &t) const
-{
- if (!isValid() || !t.isValid())
- return 0;
- return t.ds() - ds();
-}
-
-
-/*!
- \fn bool QTime::operator==(const QTime &t) const
-
- Returns \c true if this time is equal to \a t; otherwise returns \c false.
-*/
-
-/*!
- \fn bool QTime::operator!=(const QTime &t) const
-
- Returns \c true if this time is different from \a t; otherwise returns \c false.
-*/
-
-/*!
- \fn bool QTime::operator<(const QTime &t) const
-
- Returns \c true if this time is earlier than \a t; otherwise returns \c false.
-*/
-
-/*!
- \fn bool QTime::operator<=(const QTime &t) const
-
- Returns \c true if this time is earlier than or equal to \a t;
- otherwise returns \c false.
-*/
-
-/*!
- \fn bool QTime::operator>(const QTime &t) const
-
- Returns \c true if this time is later than \a t; otherwise returns \c false.
-*/
-
-/*!
- \fn bool QTime::operator>=(const QTime &t) const
-
- Returns \c true if this time is later than or equal to \a t;
- otherwise returns \c false.
-*/
-
-/*!
- \fn QTime QTime::fromMSecsSinceStartOfDay(int msecs)
-
- Returns a new QTime instance with the time set to the number of \a msecs
- since the start of the day, i.e. since 00:00:00.
-
- If \a msecs falls outside the valid range an invalid QTime will be returned.
-
- \sa msecsSinceStartOfDay()
-*/
-
-/*!
- \fn int QTime::msecsSinceStartOfDay() const
-
- Returns the number of msecs since the start of the day, i.e. since 00:00:00.
-
- \sa fromMSecsSinceStartOfDay()
-*/
-
-/*!
- \fn QTime::currentTime()
-
- Returns the current time as reported by the system clock.
-
- Note that the accuracy depends on the accuracy of the underlying
- operating system; not all systems provide 1-millisecond accuracy.
-*/
-
-#if QT_CONFIG(datestring)
-
-static QTime fromIsoTimeString(const QStringRef &string, Qt::DateFormat format, bool *isMidnight24)
-{
- if (isMidnight24)
- *isMidnight24 = false;
-
- const int size = string.size();
- if (size < 5)
- return QTime();
-
- bool ok = false;
- int hour = string.mid(0, 2).toInt(&ok);
- if (!ok)
- return QTime();
- const int minute = string.mid(3, 2).toInt(&ok);
- if (!ok)
- return QTime();
- int second = 0;
- int msec = 0;
-
- if (size == 5) {
- // HH:mm format
- second = 0;
- msec = 0;
- } else if (string.at(5) == QLatin1Char(',') || string.at(5) == QLatin1Char('.')) {
- if (format == Qt::TextDate)
- return QTime();
- // ISODate HH:mm.ssssss format
- // We only want 5 digits worth of fraction of minute. This follows the existing
- // behavior that determines how milliseconds are read; 4 millisecond digits are
- // read and then rounded to 3. If we read at most 5 digits for fraction of minute,
- // the maximum amount of millisecond digits it will expand to once converted to
- // seconds is 4. E.g. 12:34,99999 will expand to 12:34:59.9994. The milliseconds
- // will then be rounded up AND clamped to 999.
-
- const QStringRef minuteFractionStr = string.mid(6, 5);
- const long minuteFractionInt = minuteFractionStr.toLong(&ok);
- if (!ok)
- return QTime();
- const float minuteFraction = double(minuteFractionInt) / (std::pow(double(10), minuteFractionStr.count()));
-
- const float secondWithMs = minuteFraction * 60;
- const float secondNoMs = std::floor(secondWithMs);
- const float secondFraction = secondWithMs - secondNoMs;
- second = secondNoMs;
- msec = qMin(qRound(secondFraction * 1000.0), 999);
- } else {
- // HH:mm:ss or HH:mm:ss.zzz
- second = string.mid(6, 2).toInt(&ok);
- if (!ok)
- return QTime();
- if (size > 8 && (string.at(8) == QLatin1Char(',') || string.at(8) == QLatin1Char('.'))) {
- const QStringRef msecStr(string.mid(9, 4));
- int msecInt = msecStr.isEmpty() ? 0 : msecStr.toInt(&ok);
- if (!ok)
- return QTime();
- const double secondFraction(msecInt / (std::pow(double(10), msecStr.count())));
- msec = qMin(qRound(secondFraction * 1000.0), 999);
- }
- }
-
- const bool isISODate = format == Qt::ISODate || format == Qt::ISODateWithMs;
- if (isISODate && hour == 24 && minute == 0 && second == 0 && msec == 0) {
- if (isMidnight24)
- *isMidnight24 = true;
- hour = 0;
- }
-
- return QTime(hour, minute, second, msec);
-}
-
-/*!
- Returns the time represented in the \a string as a QTime using the
- \a format given, or an invalid time if this is not possible.
-
- Note that fromString() uses a "C" locale encoded string to convert
- milliseconds to a float value. If the default locale is not "C",
- this may result in two conversion attempts (if the conversion
- fails for the default locale). This should be considered an
- implementation detail.
-
- \sa toString(), QLocale::toTime()
-*/
-QTime QTime::fromString(const QString &string, Qt::DateFormat format)
-{
- if (string.isEmpty())
- return QTime();
-
- switch (format) {
- case Qt::SystemLocaleDate:
- case Qt::SystemLocaleShortDate:
- return QLocale::system().toTime(string, QLocale::ShortFormat);
- case Qt::SystemLocaleLongDate:
- return QLocale::system().toTime(string, QLocale::LongFormat);
- case Qt::LocaleDate:
- case Qt::DefaultLocaleShortDate:
- return QLocale().toTime(string, QLocale::ShortFormat);
- case Qt::DefaultLocaleLongDate:
- return QLocale().toTime(string, QLocale::LongFormat);
- case Qt::RFC2822Date:
- return rfcDateImpl(string).time;
- case Qt::ISODate:
- case Qt::ISODateWithMs:
- case Qt::TextDate:
- default:
- return fromIsoTimeString(QStringRef(&string), format, 0);
- }
-}
-
-/*!
- Returns the QTime represented by the \a string, using the \a
- format given, or an invalid time if the string cannot be parsed.
-
- These expressions may be used for the format:
-
- \table
- \header \li Expression \li Output
- \row \li h
- \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
- \row \li hh
- \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
- \row \li m \li the minute without a leading zero (0 to 59)
- \row \li mm \li the minute with a leading zero (00 to 59)
- \row \li s \li the whole second, without any leading zero (0 to 59)
- \row \li ss \li the whole second, with a leading zero where applicable (00 to 59)
- \row \li z \li the fractional part of the second, to go after a decimal
- point, without trailing zeroes (0 to 999). Thus "\c{s.z}"
- reports the seconds to full available (millisecond) precision
- without trailing zeroes.
- \row \li zzz \li the fractional part of the second, to millisecond
- precision, including trailing zeroes where applicable (000 to 999).
- \row \li AP
- \li interpret as an AM/PM time. \e AP must be either "AM" or "PM".
- \row \li ap
- \li Interpret as an AM/PM time. \e ap must be either "am" or "pm".
- \endtable
-
- All other input characters will be treated as text. Any sequence
- of characters that are enclosed in single quotes will also be
- treated as text and not be used as an expression.
-
- \snippet code/src_corelib_tools_qdatetime.cpp 6
-
- If the format is not satisfied, an invalid QTime is returned.
- Expressions that do not expect leading zeroes to be given (h, m, s
- and z) are greedy. This means that they will use two digits even if
- this puts them outside the range of accepted values and leaves too
- few digits for other sections. For example, the following string
- could have meant 00:07:10, but the m will grab two digits, resulting
- in an invalid time:
-
- \snippet code/src_corelib_tools_qdatetime.cpp 7
-
- Any field that is not represented in the format will be set to zero.
- For example:
-
- \snippet code/src_corelib_tools_qdatetime.cpp 8
-
- \sa toString(), QDateTime::fromString(), QDate::fromString(),
- QLocale::toTime()
-*/
-
-QTime QTime::fromString(const QString &string, const QString &format)
-{
- QTime time;
-#if QT_CONFIG(datetimeparser)
- QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString);
- // dt.setDefaultLocale(QLocale::c()); ### Qt 6
- if (dt.parseFormat(format))
- dt.fromString(string, 0, &time);
-#else
- Q_UNUSED(string);
- Q_UNUSED(format);
-#endif
- return time;
-}
-
-#endif // datestring
-
-
-/*!
- \overload
-
- Returns \c true if the specified time is valid; otherwise returns
- false.
-
- The time is valid if \a h is in the range 0 to 23, \a m and
- \a s are in the range 0 to 59, and \a ms is in the range 0 to 999.
-
- Example:
-
- \snippet code/src_corelib_tools_qdatetime.cpp 9
-*/
-
-bool QTime::isValid(int h, int m, int s, int ms)
-{
- return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000;
-}
-
-#if QT_DEPRECATED_SINCE(5, 14) // ### Qt 6: remove
-/*!
- Sets this time to the current time. This is practical for timing:
-
- \snippet code/src_corelib_tools_qdatetime.cpp 10
-
- \sa restart(), elapsed(), currentTime()
-*/
-
-void QTime::start()
-{
- *this = currentTime();
-}
-
-/*!
- Sets this time to the current time and returns the number of
- milliseconds that have elapsed since the last time start() or
- restart() was called.
-
- This function is guaranteed to be atomic and is thus very handy
- for repeated measurements. Call start() to start the first
- measurement, and restart() for each later measurement.
-
- Note that the counter wraps to zero 24 hours after the last call
- to start() or restart().
-
- \warning If the system's clock setting has been changed since the
- last time start() or restart() was called, the result is
- undefined. This can happen when daylight-saving time is turned on
- or off.
-
- \sa start(), elapsed(), currentTime()
-*/
-
-int QTime::restart()
-{
- QTime t = currentTime();
- int n = msecsTo(t);
- if (n < 0) // passed midnight
- n += 86400*1000;
- *this = t;
- return n;
-}
-
-/*!
- Returns the number of milliseconds that have elapsed since the
- last time start() or restart() was called.
-
- Note that the counter wraps to zero 24 hours after the last call
- to start() or restart.
-
- Note that the accuracy depends on the accuracy of the underlying
- operating system; not all systems provide 1-millisecond accuracy.
-
- \warning If the system's clock setting has been changed since the
- last time start() or restart() was called, the result is
- undefined. This can happen when daylight-saving time is turned on
- or off.
-
- \sa start(), restart()
-*/
-
-int QTime::elapsed() const
-{
- int n = msecsTo(currentTime());
- if (n < 0) // passed midnight
- n += 86400 * 1000;
- return n;
-}
-#endif // Use QElapsedTimer instead !
-
-/*****************************************************************************
- QDateTime static helper functions
- *****************************************************************************/
-
-// get the types from QDateTime (through QDateTimePrivate)
-typedef QDateTimePrivate::QDateTimeShortData ShortData;
-typedef QDateTimePrivate::QDateTimeData QDateTimeData;
-
-// Returns the platform variant of timezone, i.e. the standard time offset
-// The timezone external variable is documented as always holding the
-// Standard Time offset as seconds west of Greenwich, i.e. UTC+01:00 is -3600
-// Note this may not be historicaly accurate.
-// Relies on tzset, mktime, or localtime having been called to populate timezone
-static int qt_timezone()
-{
-#if defined(_MSC_VER)
- long offset;
- _get_timezone(&offset);
- return offset;
-#elif defined(Q_OS_BSD4) && !defined(Q_OS_DARWIN)
- time_t clock = time(NULL);
- struct tm t;
- localtime_r(&clock, &t);
- // QTBUG-36080 Workaround for systems without the POSIX timezone
- // variable. This solution is not very efficient but fixing it is up to
- // the libc implementations.
- //
- // tm_gmtoff has some important differences compared to the timezone
- // variable:
- // - It returns the number of seconds east of UTC, and we want the
- // number of seconds west of UTC.
- // - It also takes DST into account, so we need to adjust it to always
- // get the Standard Time offset.
- return -t.tm_gmtoff + (t.tm_isdst ? (long)SECS_PER_HOUR : 0L);
-#elif defined(Q_OS_INTEGRITY)
- return 0;
-#else
- return timezone;
-#endif // Q_OS_WIN
-}
-
-// Returns the tzname, assume tzset has been called already
-static QString qt_tzname(QDateTimePrivate::DaylightStatus daylightStatus)
-{
- int isDst = (daylightStatus == QDateTimePrivate::DaylightTime) ? 1 : 0;
-#if defined(Q_CC_MSVC)
- size_t s = 0;
- char name[512];
- if (_get_tzname(&s, name, 512, isDst))
- return QString();
- return QString::fromLocal8Bit(name);
-#else
- return QString::fromLocal8Bit(tzname[isDst]);
-#endif // Q_OS_WIN
-}
-
-#if QT_CONFIG(datetimeparser) && QT_CONFIG(timezone)
-/*
- \internal
- Implemented here to share qt_tzname()
-*/
-int QDateTimeParser::startsWithLocalTimeZone(const QStringRef name)
-{
- QDateTimePrivate::DaylightStatus zones[2] = {
- QDateTimePrivate::StandardTime,
- QDateTimePrivate::DaylightTime
- };
- for (const auto z : zones) {
- QString zone(qt_tzname(z));
- if (name.startsWith(zone))
- return zone.size();
- }
- return 0;
-}
-#endif // datetimeparser && timezone
-
-// Calls the platform variant of mktime for the given date, time and daylightStatus,
-// and updates the date, time, daylightStatus and abbreviation with the returned values
-// If the date falls outside the 1970 to 2037 range supported by mktime / time_t
-// then null date/time will be returned, you should adjust the date first if
-// you need a guaranteed result.
-static qint64 qt_mktime(QDate *date, QTime *time, QDateTimePrivate::DaylightStatus *daylightStatus,
- QString *abbreviation, bool *ok = 0)
-{
- const qint64 msec = time->msec();
- int yy, mm, dd;
- date->getDate(&yy, &mm, &dd);
-
- // All other platforms provide standard C library time functions
- tm local;
- memset(&local, 0, sizeof(local)); // tm_[wy]day plus any non-standard fields
- local.tm_sec = time->second();
- local.tm_min = time->minute();
- local.tm_hour = time->hour();
- local.tm_mday = dd;
- local.tm_mon = mm - 1;
- local.tm_year = yy - 1900;
- if (daylightStatus)
- local.tm_isdst = int(*daylightStatus);
- else
- local.tm_isdst = -1;
-
-#if defined(Q_OS_WIN)
- int hh = local.tm_hour;
-#endif // Q_OS_WIN
- time_t secsSinceEpoch = qMkTime(&local);
- if (secsSinceEpoch != time_t(-1)) {
- *date = QDate(local.tm_year + 1900, local.tm_mon + 1, local.tm_mday);
- *time = QTime(local.tm_hour, local.tm_min, local.tm_sec, msec);
-#if defined(Q_OS_WIN)
- // Windows mktime for the missing hour subtracts 1 hour from the time
- // instead of adding 1 hour. If time differs and is standard time then
- // this has happened, so add 2 hours to the time and 1 hour to the msecs
- if (local.tm_isdst == 0 && local.tm_hour != hh) {
- if (time->hour() >= 22)
- *date = date->addDays(1);
- *time = time->addSecs(2 * SECS_PER_HOUR);
- secsSinceEpoch += SECS_PER_HOUR;
- local.tm_isdst = 1;
- }
-#endif // Q_OS_WIN
- if (local.tm_isdst >= 1) {
- if (daylightStatus)
- *daylightStatus = QDateTimePrivate::DaylightTime;
- if (abbreviation)
- *abbreviation = qt_tzname(QDateTimePrivate::DaylightTime);
- } else if (local.tm_isdst == 0) {
- if (daylightStatus)
- *daylightStatus = QDateTimePrivate::StandardTime;
- if (abbreviation)
- *abbreviation = qt_tzname(QDateTimePrivate::StandardTime);
- } else {
- if (daylightStatus)
- *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
- if (abbreviation)
- *abbreviation = qt_tzname(QDateTimePrivate::StandardTime);
- }
- if (ok)
- *ok = true;
- } else {
- *date = QDate();
- *time = QTime();
- if (daylightStatus)
- *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
- if (abbreviation)
- *abbreviation = QString();
- if (ok)
- *ok = false;
- }
-
- return ((qint64)secsSinceEpoch * 1000) + msec;
-}
-
-// Calls the platform variant of localtime for the given msecs, and updates
-// the date, time, and DST status with the returned values.
-static bool qt_localtime(qint64 msecsSinceEpoch, QDate *localDate, QTime *localTime,
- QDateTimePrivate::DaylightStatus *daylightStatus)
-{
- const time_t secsSinceEpoch = msecsSinceEpoch / 1000;
- const int msec = msecsSinceEpoch % 1000;
-
- tm local;
- bool valid = false;
-
- // localtime() is specified to work as if it called tzset().
- // localtime_r() does not have this constraint, so make an explicit call.
- // The explicit call should also request the timezone info be re-parsed.
- qTzSet();
-#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
- // Use the reentrant version of localtime() where available
- // as is thread-safe and doesn't use a shared static data area
- tm *res = 0;
- res = localtime_r(&secsSinceEpoch, &local);
- if (res)
- valid = true;
-#elif defined(Q_CC_MSVC)
- if (!_localtime64_s(&local, &secsSinceEpoch))
- valid = true;
-#else
- // Returns shared static data which may be overwritten at any time
- // So copy the result asap
- tm *res = 0;
- res = localtime(&secsSinceEpoch);
- if (res) {
- local = *res;
- valid = true;
- }
-#endif
- if (valid) {
- *localDate = QDate(local.tm_year + 1900, local.tm_mon + 1, local.tm_mday);
- *localTime = QTime(local.tm_hour, local.tm_min, local.tm_sec, msec);
- if (daylightStatus) {
- if (local.tm_isdst > 0)
- *daylightStatus = QDateTimePrivate::DaylightTime;
- else if (local.tm_isdst < 0)
- *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
- else
- *daylightStatus = QDateTimePrivate::StandardTime;
- }
- return true;
- } else {
- *localDate = QDate();
- *localTime = QTime();
- if (daylightStatus)
- *daylightStatus = QDateTimePrivate::UnknownDaylightTime;
- return false;
- }
-}
-
-// Converts an msecs value into a date and time
-static void msecsToTime(qint64 msecs, QDate *date, QTime *time)
-{
- qint64 jd = JULIAN_DAY_FOR_EPOCH;
- qint64 ds = 0;
-
- if (msecs >= MSECS_PER_DAY || msecs <= -MSECS_PER_DAY) {
- jd += msecs / MSECS_PER_DAY;
- msecs %= MSECS_PER_DAY;
- }
-
- if (msecs < 0) {
- ds = MSECS_PER_DAY - msecs - 1;
- jd -= ds / MSECS_PER_DAY;
- ds = ds % MSECS_PER_DAY;
- ds = MSECS_PER_DAY - ds - 1;
- } else {
- ds = msecs;
- }
-
- if (date)
- *date = QDate::fromJulianDay(jd);
- if (time)
- *time = QTime::fromMSecsSinceStartOfDay(ds);
-}
-
-// Converts a date/time value into msecs
-static qint64 timeToMSecs(const QDate &date, const QTime &time)
-{
- return ((date.toJulianDay() - JULIAN_DAY_FOR_EPOCH) * MSECS_PER_DAY)
- + time.msecsSinceStartOfDay();
-}
-
-// Convert an MSecs Since Epoch into Local Time
-static bool epochMSecsToLocalTime(qint64 msecs, QDate *localDate, QTime *localTime,
- QDateTimePrivate::DaylightStatus *daylightStatus = 0)
-{
- if (msecs < 0) {
- // Docs state any LocalTime before 1970-01-01 will *not* have any Daylight Time applied
- // Instead just use the standard offset from UTC to convert to UTC time
- qTzSet();
- msecsToTime(msecs - qt_timezone() * 1000, localDate, localTime);
- if (daylightStatus)
- *daylightStatus = QDateTimePrivate::StandardTime;
- return true;
- } else if (msecs > (qint64(TIME_T_MAX) * 1000)) {
- // Docs state any LocalTime after 2037-12-31 *will* have any DST applied
- // but this may fall outside the supported time_t range, so need to fake it.
- // Use existing method to fake the conversion, but this is deeply flawed as it may
- // apply the conversion from the wrong day number, e.g. if rule is last Sunday of month
- // TODO Use QTimeZone when available to apply the future rule correctly
- QDate utcDate;
- QTime utcTime;
- msecsToTime(msecs, &utcDate, &utcTime);
- int year, month, day;
- utcDate.getDate(&year, &month, &day);
- // 2037 is not a leap year, so make sure date isn't Feb 29
- if (month == 2 && day == 29)
- --day;
- QDate fakeDate(2037, month, day);
- qint64 fakeMsecs = QDateTime(fakeDate, utcTime, Qt::UTC).toMSecsSinceEpoch();
- bool res = qt_localtime(fakeMsecs, localDate, localTime, daylightStatus);
- *localDate = localDate->addDays(fakeDate.daysTo(utcDate));
- return res;
- } else {
- // Falls inside time_t suported range so can use localtime
- return qt_localtime(msecs, localDate, localTime, daylightStatus);
- }
-}
-
-// Convert a LocalTime expressed in local msecs encoding and the corresponding
-// DST status into a UTC epoch msecs. Optionally populate the returned
-// values from mktime for the adjusted local date and time.
-static qint64 localMSecsToEpochMSecs(qint64 localMsecs,
- QDateTimePrivate::DaylightStatus *daylightStatus,
- QDate *localDate = 0, QTime *localTime = 0,
- QString *abbreviation = 0)
-{
- QDate dt;
- QTime tm;
- msecsToTime(localMsecs, &dt, &tm);
-
- const qint64 msecsMax = qint64(TIME_T_MAX) * 1000;
-
- if (localMsecs <= qint64(MSECS_PER_DAY)) {
-
- // Docs state any LocalTime before 1970-01-01 will *not* have any DST applied
-
- // First, if localMsecs is within +/- 1 day of minimum time_t try mktime in case it does
- // fall after minimum and needs proper DST conversion
- if (localMsecs >= -qint64(MSECS_PER_DAY)) {
- bool valid;
- qint64 utcMsecs = qt_mktime(&dt, &tm, daylightStatus, abbreviation, &valid);
- if (valid && utcMsecs >= 0) {
- // mktime worked and falls in valid range, so use it
- if (localDate)
- *localDate = dt;
- if (localTime)
- *localTime = tm;
- return utcMsecs;
- }
- } else {
- // If we don't call mktime then need to call tzset to get offset
- qTzSet();
- }
- // Time is clearly before 1970-01-01 so just use standard offset to convert
- qint64 utcMsecs = localMsecs + qt_timezone() * 1000;
- if (localDate || localTime)
- msecsToTime(localMsecs, localDate, localTime);
- if (daylightStatus)
- *daylightStatus = QDateTimePrivate::StandardTime;
- if (abbreviation)
- *abbreviation = qt_tzname(QDateTimePrivate::StandardTime);
- return utcMsecs;
-
- } else if (localMsecs >= msecsMax - MSECS_PER_DAY) {
-
- // Docs state any LocalTime after 2037-12-31 *will* have any DST applied
- // but this may fall outside the supported time_t range, so need to fake it.
-
- // First, if localMsecs is within +/- 1 day of maximum time_t try mktime in case it does
- // fall before maximum and can use proper DST conversion
- if (localMsecs <= msecsMax + MSECS_PER_DAY) {
- bool valid;
- qint64 utcMsecs = qt_mktime(&dt, &tm, daylightStatus, abbreviation, &valid);
- if (valid && utcMsecs <= msecsMax) {
- // mktime worked and falls in valid range, so use it
- if (localDate)
- *localDate = dt;
- if (localTime)
- *localTime = tm;
- return utcMsecs;
- }
- }
- // Use existing method to fake the conversion, but this is deeply flawed as it may
- // apply the conversion from the wrong day number, e.g. if rule is last Sunday of month
- // TODO Use QTimeZone when available to apply the future rule correctly
- int year, month, day;
- dt.getDate(&year, &month, &day);
- // 2037 is not a leap year, so make sure date isn't Feb 29
- if (month == 2 && day == 29)
- --day;
- QDate fakeDate(2037, month, day);
- qint64 fakeDiff = fakeDate.daysTo(dt);
- qint64 utcMsecs = qt_mktime(&fakeDate, &tm, daylightStatus, abbreviation);
- if (localDate)
- *localDate = fakeDate.addDays(fakeDiff);
- if (localTime)
- *localTime = tm;
- QDate utcDate;
- QTime utcTime;
- msecsToTime(utcMsecs, &utcDate, &utcTime);
- utcDate = utcDate.addDays(fakeDiff);
- utcMsecs = timeToMSecs(utcDate, utcTime);
- return utcMsecs;
-
- } else {
-
- // Clearly falls inside 1970-2037 suported range so can use mktime
- qint64 utcMsecs = qt_mktime(&dt, &tm, daylightStatus, abbreviation);
- if (localDate)
- *localDate = dt;
- if (localTime)
- *localTime = tm;
- return utcMsecs;
-
- }
-}
-
-static inline bool specCanBeSmall(Qt::TimeSpec spec)
-{
- return spec == Qt::LocalTime || spec == Qt::UTC;
-}
-
-static inline bool msecsCanBeSmall(qint64 msecs)
-{
- if (!QDateTimeData::CanBeSmall)
- return false;
-
- ShortData sd;
- sd.msecs = qintptr(msecs);
- return sd.msecs == msecs;
-}
-
-static Q_DECL_CONSTEXPR inline
-QDateTimePrivate::StatusFlags mergeSpec(QDateTimePrivate::StatusFlags status, Qt::TimeSpec spec)
-{
- return QDateTimePrivate::StatusFlags((status & ~QDateTimePrivate::TimeSpecMask) |
- (int(spec) << QDateTimePrivate::TimeSpecShift));
-}
-
-static Q_DECL_CONSTEXPR inline Qt::TimeSpec extractSpec(QDateTimePrivate::StatusFlags status)
-{
- return Qt::TimeSpec((status & QDateTimePrivate::TimeSpecMask) >> QDateTimePrivate::TimeSpecShift);
-}
-
-// Set the Daylight Status if LocalTime set via msecs
-static Q_DECL_RELAXED_CONSTEXPR inline QDateTimePrivate::StatusFlags
-mergeDaylightStatus(QDateTimePrivate::StatusFlags sf, QDateTimePrivate::DaylightStatus status)
-{
- sf &= ~QDateTimePrivate::DaylightMask;
- if (status == QDateTimePrivate::DaylightTime) {
- sf |= QDateTimePrivate::SetToDaylightTime;
- } else if (status == QDateTimePrivate::StandardTime) {
- sf |= QDateTimePrivate::SetToStandardTime;
- }
- return sf;
-}
-
-// Get the DST Status if LocalTime set via msecs
-static Q_DECL_RELAXED_CONSTEXPR inline
-QDateTimePrivate::DaylightStatus extractDaylightStatus(QDateTimePrivate::StatusFlags status)
-{
- if (status & QDateTimePrivate::SetToDaylightTime)
- return QDateTimePrivate::DaylightTime;
- if (status & QDateTimePrivate::SetToStandardTime)
- return QDateTimePrivate::StandardTime;
- return QDateTimePrivate::UnknownDaylightTime;
-}
-
-static inline qint64 getMSecs(const QDateTimeData &d)
-{
- if (d.isShort()) {
- // same as, but producing better code
- //return d.data.msecs;
- return qintptr(d.d) >> 8;
- }
- return d->m_msecs;
-}
-
-static inline QDateTimePrivate::StatusFlags getStatus(const QDateTimeData &d)
-{
- if (d.isShort()) {
- // same as, but producing better code
- //return StatusFlag(d.data.status);
- return QDateTimePrivate::StatusFlag(qintptr(d.d) & 0xFF);
- }
- return d->m_status;
-}
-
-static inline Qt::TimeSpec getSpec(const QDateTimeData &d)
-{
- return extractSpec(getStatus(d));
-}
-
-#if QT_CONFIG(timezone)
-void QDateTimePrivate::setUtcOffsetByTZ(qint64 atMSecsSinceEpoch)
-{
- m_offsetFromUtc = m_timeZone.d->offsetFromUtc(atMSecsSinceEpoch);
-}
-#endif
-
-// Refresh the LocalTime validity and offset
-static void refreshDateTime(QDateTimeData &d)
-{
- auto status = getStatus(d);
- const auto spec = extractSpec(status);
- const qint64 msecs = getMSecs(d);
- qint64 epochMSecs = 0;
- int offsetFromUtc = 0;
- QDate testDate;
- QTime testTime;
- Q_ASSERT(spec == Qt::TimeZone || spec == Qt::LocalTime);
-
-#if QT_CONFIG(timezone)
- // If not valid time zone then is invalid
- if (spec == Qt::TimeZone) {
- if (!d->m_timeZone.isValid()) {
- status &= ~QDateTimePrivate::ValidDateTime;
- } else {
- epochMSecs = QDateTimePrivate::zoneMSecsToEpochMSecs(msecs, d->m_timeZone, extractDaylightStatus(status), &testDate, &testTime);
- d->setUtcOffsetByTZ(epochMSecs);
- }
- }
-#endif // timezone
-
- // If not valid date and time then is invalid
- if (!(status & QDateTimePrivate::ValidDate) || !(status & QDateTimePrivate::ValidTime)) {
- status &= ~QDateTimePrivate::ValidDateTime;
- if (status & QDateTimePrivate::ShortData) {
- d.data.status = status;
- } else {
- d->m_status = status;
- d->m_offsetFromUtc = 0;
- }
- return;
- }
-
- // We have a valid date and time and a Qt::LocalTime or Qt::TimeZone that needs calculating
- // LocalTime and TimeZone might fall into a "missing" DST transition hour
- // Calling toEpochMSecs will adjust the returned date/time if it does
- if (spec == Qt::LocalTime) {
- auto dstStatus = extractDaylightStatus(status);
- epochMSecs = localMSecsToEpochMSecs(msecs, &dstStatus, &testDate, &testTime);
- }
- if (timeToMSecs(testDate, testTime) == msecs) {
- status |= QDateTimePrivate::ValidDateTime;
- // Cache the offset to use in offsetFromUtc()
- offsetFromUtc = (msecs - epochMSecs) / 1000;
- } else {
- status &= ~QDateTimePrivate::ValidDateTime;
- }
-
- if (status & QDateTimePrivate::ShortData) {
- d.data.status = status;
- } else {
- d->m_status = status;
- d->m_offsetFromUtc = offsetFromUtc;
- }
-}
-
-// Check the UTC / offsetFromUTC validity
-static void checkValidDateTime(QDateTimeData &d)
-{
- auto status = getStatus(d);
- auto spec = extractSpec(status);
- switch (spec) {
- case Qt::OffsetFromUTC:
- case Qt::UTC:
- // for these, a valid date and a valid time imply a valid QDateTime
- if ((status & QDateTimePrivate::ValidDate) && (status & QDateTimePrivate::ValidTime))
- status |= QDateTimePrivate::ValidDateTime;
- else
- status &= ~QDateTimePrivate::ValidDateTime;
- if (status & QDateTimePrivate::ShortData)
- d.data.status = status;
- else
- d->m_status = status;
- break;
- case Qt::TimeZone:
- case Qt::LocalTime:
- // for these, we need to check whether the timezone is valid and whether
- // the time is valid in that timezone. Expensive, but no other option.
- refreshDateTime(d);
- break;
- }
-}
-
-static void setTimeSpec(QDateTimeData &d, Qt::TimeSpec spec, int offsetSeconds)
-{
- auto status = getStatus(d);
- status &= ~(QDateTimePrivate::ValidDateTime | QDateTimePrivate::DaylightMask |
- QDateTimePrivate::TimeSpecMask);
-
- switch (spec) {
- case Qt::OffsetFromUTC:
- if (offsetSeconds == 0)
- spec = Qt::UTC;
- break;
- case Qt::TimeZone:
- // Use system time zone instead
- spec = Qt::LocalTime;
- Q_FALLTHROUGH();
- case Qt::UTC:
- case Qt::LocalTime:
- offsetSeconds = 0;
- break;
- }
-
- status = mergeSpec(status, spec);
- if (d.isShort() && offsetSeconds == 0) {
- d.data.status = status;
- } else {
- d.detach();
- d->m_status = status & ~QDateTimePrivate::ShortData;
- d->m_offsetFromUtc = offsetSeconds;
-#if QT_CONFIG(timezone)
- d->m_timeZone = QTimeZone();
-#endif // timezone
- }
-}
-
-static void setDateTime(QDateTimeData &d, const QDate &date, const QTime &time)
-{
- // If the date is valid and the time is not we set time to 00:00:00
- QTime useTime = time;
- if (!useTime.isValid() && date.isValid())
- useTime = QTime::fromMSecsSinceStartOfDay(0);
-
- QDateTimePrivate::StatusFlags newStatus = 0;
-
- // Set date value and status
- qint64 days = 0;
- if (date.isValid()) {
- days = date.toJulianDay() - JULIAN_DAY_FOR_EPOCH;
- newStatus = QDateTimePrivate::ValidDate;
- }
-
- // Set time value and status
- int ds = 0;
- if (useTime.isValid()) {
- ds = useTime.msecsSinceStartOfDay();
- newStatus |= QDateTimePrivate::ValidTime;
- }
-
- // Set msecs serial value
- qint64 msecs = (days * MSECS_PER_DAY) + ds;
- if (d.isShort()) {
- // let's see if we can keep this short
- if (msecsCanBeSmall(msecs)) {
- // yes, we can
- d.data.msecs = qintptr(msecs);
- d.data.status &= ~(QDateTimePrivate::ValidityMask | QDateTimePrivate::DaylightMask);
- d.data.status |= newStatus;
- } else {
- // nope...
- d.detach();
- }
- }
- if (!d.isShort()) {
- d.detach();
- d->m_msecs = msecs;
- d->m_status &= ~(QDateTimePrivate::ValidityMask | QDateTimePrivate::DaylightMask);
- d->m_status |= newStatus;
- }
-
- // Set if date and time are valid
- checkValidDateTime(d);
-}
-
-static QPair<QDate, QTime> getDateTime(const QDateTimeData &d)
-{
- QPair<QDate, QTime> result;
- qint64 msecs = getMSecs(d);
- auto status = getStatus(d);
- msecsToTime(msecs, &result.first, &result.second);
-
- if (!status.testFlag(QDateTimePrivate::ValidDate))
- result.first = QDate();
-
- if (!status.testFlag(QDateTimePrivate::ValidTime))
- result.second = QTime();
-
- return result;
-}
-
-/*****************************************************************************
- QDateTime::Data member functions
- *****************************************************************************/
-
-inline QDateTime::Data::Data()
-{
- // default-constructed data has a special exception:
- // it can be small even if CanBeSmall == false
- // (optimization so we don't allocate memory in the default constructor)
- quintptr value = quintptr(mergeSpec(QDateTimePrivate::ShortData, Qt::LocalTime));
- d = reinterpret_cast<QDateTimePrivate *>(value);
-}
-
-inline QDateTime::Data::Data(Qt::TimeSpec spec)
-{
- if (CanBeSmall && Q_LIKELY(specCanBeSmall(spec))) {
- d = reinterpret_cast<QDateTimePrivate *>(quintptr(mergeSpec(QDateTimePrivate::ShortData, spec)));
- } else {
- // the structure is too small, we need to detach
- d = new QDateTimePrivate;
- d->ref.ref();
- d->m_status = mergeSpec(0, spec);
- }
-}
-
-inline QDateTime::Data::Data(const Data &other)
- : d(other.d)
-{
- if (!isShort()) {
- // check if we could shrink
- if (specCanBeSmall(extractSpec(d->m_status)) && msecsCanBeSmall(d->m_msecs)) {
- ShortData sd;
- sd.msecs = qintptr(d->m_msecs);
- sd.status = d->m_status | QDateTimePrivate::ShortData;
- data = sd;
- } else {
- // no, have to keep it big
- d->ref.ref();
- }
- }
-}
-
-inline QDateTime::Data::Data(Data &&other)
- : d(other.d)
-{
- // reset the other to a short state
- Data dummy;
- Q_ASSERT(dummy.isShort());
- other.d = dummy.d;
-}
-
-inline QDateTime::Data &QDateTime::Data::operator=(const Data &other)
-{
- if (d == other.d)
- return *this;
-
- auto x = d;
- d = other.d;
- if (!other.isShort()) {
- // check if we could shrink
- if (specCanBeSmall(extractSpec(other.d->m_status)) && msecsCanBeSmall(other.d->m_msecs)) {
- ShortData sd;
- sd.msecs = qintptr(other.d->m_msecs);
- sd.status = other.d->m_status | QDateTimePrivate::ShortData;
- data = sd;
- } else {
- // no, have to keep it big
- other.d->ref.ref();
- }
- }
-
- if (!(quintptr(x) & QDateTimePrivate::ShortData) && !x->ref.deref())
- delete x;
- return *this;
-}
-
-inline QDateTime::Data::~Data()
-{
- if (!isShort() && !d->ref.deref())
- delete d;
-}
-
-inline bool QDateTime::Data::isShort() const
-{
- bool b = quintptr(d) & QDateTimePrivate::ShortData;
-
- // sanity check:
- Q_ASSERT(b || (d->m_status & QDateTimePrivate::ShortData) == 0);
-
- // even if CanBeSmall = false, we have short data for a default-constructed
- // QDateTime object. But it's unlikely.
- if (CanBeSmall)
- return Q_LIKELY(b);
- return Q_UNLIKELY(b);
-}
-
-inline void QDateTime::Data::detach()
-{
- QDateTimePrivate *x;
- bool wasShort = isShort();
- if (wasShort) {
- // force enlarging
- x = new QDateTimePrivate;
- x->m_status = QDateTimePrivate::StatusFlag(data.status & ~QDateTimePrivate::ShortData);
- x->m_msecs = data.msecs;
- } else {
- if (d->ref.load() == 1)
- return;
-
- x = new QDateTimePrivate(*d);
- }
-
- x->ref.store(1);
- if (!wasShort && !d->ref.deref())
- delete d;
- d = x;
-}
-
-inline const QDateTimePrivate *QDateTime::Data::operator->() const
-{
- Q_ASSERT(!isShort());
- return d;
-}
-
-inline QDateTimePrivate *QDateTime::Data::operator->()
-{
- // should we attempt to detach here?
- Q_ASSERT(!isShort());
- Q_ASSERT(d->ref.load() == 1);
- return d;
-}
-
-/*****************************************************************************
- QDateTimePrivate member functions
- *****************************************************************************/
-
-Q_NEVER_INLINE
-QDateTime::Data QDateTimePrivate::create(const QDate &toDate, const QTime &toTime, Qt::TimeSpec toSpec,
- int offsetSeconds)
-{
- QDateTime::Data result(toSpec);
- setTimeSpec(result, toSpec, offsetSeconds);
- setDateTime(result, toDate, toTime);
- return result;
-}
-
-#if QT_CONFIG(timezone)
-inline QDateTime::Data QDateTimePrivate::create(const QDate &toDate, const QTime &toTime,
- const QTimeZone &toTimeZone)
-{
- QDateTime::Data result(Qt::TimeZone);
- Q_ASSERT(!result.isShort());
-
- result.d->m_status = mergeSpec(result.d->m_status, Qt::TimeZone);
- result.d->m_timeZone = toTimeZone;
- setDateTime(result, toDate, toTime);
- return result;
-}
-
-// Convert a TimeZone time expressed in zone msecs encoding into a UTC epoch msecs
-// DST transitions are disambiguated by hint.
-inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QTimeZone &zone,
- DaylightStatus hint,
- QDate *zoneDate, QTime *zoneTime)
-{
- // Get the effective data from QTimeZone
- QTimeZonePrivate::Data data = zone.d->dataForLocalTime(zoneMSecs, int(hint));
- // Docs state any time before 1970-01-01 will *not* have any DST applied
- // but all affected times afterwards will have DST applied.
- if (data.atMSecsSinceEpoch < 0) {
- msecsToTime(zoneMSecs, zoneDate, zoneTime);
- return zoneMSecs - data.standardTimeOffset * 1000;
- } else {
- msecsToTime(data.atMSecsSinceEpoch + data.offsetFromUtc * 1000, zoneDate, zoneTime);
- return data.atMSecsSinceEpoch;
- }
-}
-#endif // timezone
-
-/*****************************************************************************
- QDateTime member functions
- *****************************************************************************/
-
-/*!
- \class QDateTime
- \inmodule QtCore
- \ingroup shared
- \reentrant
- \brief The QDateTime class provides date and time functions.
-
-
- A QDateTime object encodes a calendar date and a clock time (a
- "datetime"). It combines features of the QDate and QTime classes.
- It can read the current datetime from the system clock. It
- provides functions for comparing datetimes and for manipulating a
- datetime by adding a number of seconds, days, months, or years.
-
- A QDateTime object is typically created either by giving a date
- and time explicitly in the constructor, or by using the static
- function currentDateTime() that returns a QDateTime object set
- to the system clock's time. The date and time can be changed with
- setDate() and setTime(). A datetime can also be set using the
- setTime_t() function that takes a POSIX-standard "number of
- seconds since 00:00:00 on January 1, 1970" value. The fromString()
- function returns a QDateTime, given a string and a date format
- used to interpret the date within the string.
-
- The date() and time() functions provide access to the date and
- time parts of the datetime. The same information is provided in
- textual format by the toString() function.
-
- QDateTime provides a full set of operators to compare two
- QDateTime objects, where smaller means earlier and larger means
- later.
-
- You can increment (or decrement) a datetime by a given number of
- milliseconds using addMSecs(), seconds using addSecs(), or days
- using addDays(). Similarly, you can use addMonths() and addYears().
- The daysTo() function returns the number of days between two datetimes,
- secsTo() returns the number of seconds between two datetimes, and
- msecsTo() returns the number of milliseconds between two datetimes.
-
- QDateTime can store datetimes as \l{Qt::LocalTime}{local time} or
- as \l{Qt::UTC}{UTC}. QDateTime::currentDateTime() returns a
- QDateTime expressed as local time; use toUTC() to convert it to
- UTC. You can also use timeSpec() to find out if a QDateTime
- object stores a UTC time or a local time. Operations such as
- addSecs() and secsTo() are aware of daylight-saving time (DST).
-
- \note QDateTime does not account for leap seconds.
-
- \section1 Remarks
-
- \section2 No Year 0
-
- There is no year 0. Dates in that year are considered invalid. The
- year -1 is the year "1 before Christ" or "1 before current era."
- The day before 1 January 1 CE is 31 December 1 BCE.
-
- \section2 Range of Valid Dates
-
- The range of valid values able to be stored in QDateTime is dependent on
- the internal storage implementation. QDateTime is currently stored in a
- qint64 as a serial msecs value encoding the date and time. This restricts
- the date range to about +/- 292 million years, compared to the QDate range
- of +/- 2 billion years. Care must be taken when creating a QDateTime with
- extreme values that you do not overflow the storage. The exact range of
- supported values varies depending on the Qt::TimeSpec and time zone.
-
- \section2 Use of System Timezone
-
- QDateTime uses the system's time zone information to determine the
- offset of local time from UTC. If the system is not configured
- correctly or not up-to-date, QDateTime will give wrong results as
- well.
-
- \section2 Daylight-Saving Time (DST)
-
- QDateTime takes into account the system's time zone information
- when dealing with DST. On modern Unix systems, this means it
- applies the correct historical DST data whenever possible. On
- Windows, where the system doesn't support historical DST data,
- historical accuracy is not maintained with respect to DST.
-
- The range of valid dates taking DST into account is 1970-01-01 to
- the present, and rules are in place for handling DST correctly
- until 2037-12-31, but these could change. For dates falling
- outside that range, QDateTime makes a \e{best guess} using the
- rules for year 1970 or 2037, but we can't guarantee accuracy. This
- means QDateTime doesn't take into account changes in a locale's
- time zone before 1970, even if the system's time zone database
- supports that information.
-
- QDateTime takes into consideration the Standard Time to Daylight-Saving Time
- transition. For example if the transition is at 2am and the clock goes
- forward to 3am, then there is a "missing" hour from 02:00:00 to 02:59:59.999
- which QDateTime considers to be invalid. Any date maths performed
- will take this missing hour into account and return a valid result.
-
- \section2 Offset From UTC
-
- A Qt::TimeSpec of Qt::OffsetFromUTC is also supported. This allows you
- to define a QDateTime relative to UTC at a fixed offset of a given number
- of seconds from UTC. For example, an offset of +3600 seconds is one hour
- ahead of UTC and is usually written in ISO standard notation as
- "UTC+01:00". Daylight-Saving Time never applies with this TimeSpec.
-
- There is no explicit size restriction to the offset seconds, but there is
- an implicit limit imposed when using the toString() and fromString()
- methods which use a format of [+|-]hh:mm, effectively limiting the range
- to +/- 99 hours and 59 minutes and whole minutes only. Note that currently
- no time zone lies outside the range of +/- 14 hours.
-
- \section2 Time Zone Support
-
- A Qt::TimeSpec of Qt::TimeZone is also supported in conjunction with the
- QTimeZone class. This allows you to define a datetime in a named time zone
- adhering to a consistent set of daylight-saving transition rules. For
- example a time zone of "Europe/Berlin" will apply the daylight-saving
- rules as used in Germany since 1970. Note that the transition rules
- applied depend on the platform support. See the QTimeZone documentation
- for more details.
-
- \sa QDate, QTime, QDateTimeEdit, QTimeZone
-*/
-
-/*!
- Constructs a null datetime (i.e. null date and null time). A null
- datetime is invalid, since the date is invalid.
-
- \sa isValid()
-*/
-QDateTime::QDateTime() noexcept(Data::CanBeSmall)
-{
-}
-
-
-/*!
- Constructs a datetime with the given \a date, a valid
- time(00:00:00.000), and sets the timeSpec() to Qt::LocalTime.
-*/
-
-QDateTime::QDateTime(const QDate &date)
- : d(QDateTimePrivate::create(date, QTime(0, 0), Qt::LocalTime, 0))
-{
-}
-
-/*!
- Constructs a datetime with the given \a date and \a time, using
- the time specification defined by \a spec.
-
- If \a date is valid and \a time is not, the time will be set to midnight.
-
- If \a spec is Qt::OffsetFromUTC then it will be set to Qt::UTC, i.e. an
- offset of 0 seconds. To create a Qt::OffsetFromUTC datetime use the
- correct constructor.
-
- If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
- i.e. the current system time zone. To create a Qt::TimeZone datetime
- use the correct constructor.
-*/
-
-QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec)
- : d(QDateTimePrivate::create(date, time, spec, 0))
-{
-}
-
-/*!
- \since 5.2
-
- Constructs a datetime with the given \a date and \a time, using
- the time specification defined by \a spec and \a offsetSeconds seconds.
-
- If \a date is valid and \a time is not, the time will be set to midnight.
-
- If the \a spec is not Qt::OffsetFromUTC then \a offsetSeconds will be ignored.
-
- If the \a spec is Qt::OffsetFromUTC and \a offsetSeconds is 0 then the
- timeSpec() will be set to Qt::UTC, i.e. an offset of 0 seconds.
-
- If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
- i.e. the current system time zone. To create a Qt::TimeZone datetime
- use the correct constructor.
-*/
-
-QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec, int offsetSeconds)
- : d(QDateTimePrivate::create(date, time, spec, offsetSeconds))
-{
-}
-
-#if QT_CONFIG(timezone)
-/*!
- \since 5.2
-
- Constructs a datetime with the given \a date and \a time, using
- the Time Zone specified by \a timeZone.
-
- If \a date is valid and \a time is not, the time will be set to 00:00:00.
-
- If \a timeZone is invalid then the datetime will be invalid.
-*/
-
-QDateTime::QDateTime(const QDate &date, const QTime &time, const QTimeZone &timeZone)
- : d(QDateTimePrivate::create(date, time, timeZone))
-{
-}
-#endif // timezone
-
-/*!
- Constructs a copy of the \a other datetime.
-*/
-QDateTime::QDateTime(const QDateTime &other) noexcept
- : d(other.d)
-{
-}
-
-/*!
- \since 5.8
- Moves the content of the temporary \a other datetime to this object and
- leaves \a other in an unspecified (but proper) state.
-*/
-QDateTime::QDateTime(QDateTime &&other) noexcept
- : d(std::move(other.d))
-{
-}
-
-/*!
- Destroys the datetime.
-*/
-QDateTime::~QDateTime()
-{
-}
-
-/*!
- Makes a copy of the \a other datetime and returns a reference to the
- copy.
-*/
-
-QDateTime &QDateTime::operator=(const QDateTime &other) noexcept
-{
- d = other.d;
- return *this;
-}
-/*!
- \fn void QDateTime::swap(QDateTime &other)
- \since 5.0
-
- Swaps this datetime with \a other. This operation is very fast
- and never fails.
-*/
-
-/*!
- Returns \c true if both the date and the time are null; otherwise
- returns \c false. A null datetime is invalid.
-
- \sa QDate::isNull(), QTime::isNull(), isValid()
-*/
-
-bool QDateTime::isNull() const
-{
- auto status = getStatus(d);
- return !status.testFlag(QDateTimePrivate::ValidDate) &&
- !status.testFlag(QDateTimePrivate::ValidTime);
-}
-
-/*!
- Returns \c true if both the date and the time are valid and they are valid in
- the current Qt::TimeSpec, otherwise returns \c false.
-
- If the timeSpec() is Qt::LocalTime or Qt::TimeZone then the date and time are
- checked to see if they fall in the Standard Time to Daylight-Saving Time transition
- hour, i.e. if the transition is at 2am and the clock goes forward to 3am
- then the time from 02:00:00 to 02:59:59.999 is considered to be invalid.
-
- \sa QDate::isValid(), QTime::isValid()
-*/
-
-bool QDateTime::isValid() const
-{
- auto status = getStatus(d);
- return status & QDateTimePrivate::ValidDateTime;
-}
-
-/*!
- Returns the date part of the datetime.
-
- \sa setDate(), time(), timeSpec()
-*/
-
-QDate QDateTime::date() const
-{
- auto status = getStatus(d);
- if (!status.testFlag(QDateTimePrivate::ValidDate))
- return QDate();
- QDate dt;
- msecsToTime(getMSecs(d), &dt, 0);
- return dt;
-}
-
-/*!
- Returns the time part of the datetime.
-
- \sa setTime(), date(), timeSpec()
-*/
-
-QTime QDateTime::time() const
-{
- auto status = getStatus(d);
- if (!status.testFlag(QDateTimePrivate::ValidTime))
- return QTime();
- QTime tm;
- msecsToTime(getMSecs(d), 0, &tm);
- return tm;
-}
-
-/*!
- Returns the time specification of the datetime.
-
- \sa setTimeSpec(), date(), time(), Qt::TimeSpec
-*/
-
-Qt::TimeSpec QDateTime::timeSpec() const
-{
- return getSpec(d);
-}
-
-#if QT_CONFIG(timezone)
-/*!
- \since 5.2
-
- Returns the time zone of the datetime.
-
- If the timeSpec() is Qt::LocalTime then an instance of the current system
- time zone will be returned. Note however that if you copy this time zone
- the instance will not remain in sync if the system time zone changes.
-
- \sa setTimeZone(), Qt::TimeSpec
-*/
-
-QTimeZone QDateTime::timeZone() const
-{
- switch (getSpec(d)) {
- case Qt::UTC:
- return QTimeZone::utc();
- case Qt::OffsetFromUTC:
- return QTimeZone(d->m_offsetFromUtc);
- case Qt::TimeZone:
- Q_ASSERT(d->m_timeZone.isValid());
- return d->m_timeZone;
- case Qt::LocalTime:
- return QTimeZone::systemTimeZone();
- }
- return QTimeZone();
-}
-#endif // timezone
-
-/*!
- \since 5.2
-
- Returns the current Offset From UTC in seconds.
-
- If the timeSpec() is Qt::OffsetFromUTC this will be the value originally set.
-
- If the timeSpec() is Qt::TimeZone this will be the offset effective in the
- Time Zone including any Daylight-Saving Offset.
-
- If the timeSpec() is Qt::LocalTime this will be the difference between the
- Local Time and UTC including any Daylight-Saving Offset.
-
- If the timeSpec() is Qt::UTC this will be 0.
-
- \sa setOffsetFromUtc()
-*/
-
-int QDateTime::offsetFromUtc() const
-{
- if (!d.isShort())
- return d->m_offsetFromUtc;
- if (!isValid())
- return 0;
-
- auto spec = getSpec(d);
- if (spec == Qt::LocalTime) {
- // we didn't cache the value, so we need to calculate it now...
- qint64 msecs = getMSecs(d);
- return (msecs - toMSecsSinceEpoch()) / 1000;
- }
-
- Q_ASSERT(spec == Qt::UTC);
- return 0;
-}
-
-/*!
- \since 5.2
-
- Returns the Time Zone Abbreviation for the datetime.
-
- If the timeSpec() is Qt::UTC this will be "UTC".
-
- If the timeSpec() is Qt::OffsetFromUTC this will be in the format
- "UTC[+-]00:00".
-
- If the timeSpec() is Qt::LocalTime then the host system is queried for the
- correct abbreviation.
-
- Note that abbreviations may or may not be localized.
-
- Note too that the abbreviation is not guaranteed to be a unique value,
- i.e. different time zones may have the same abbreviation.
-
- \sa timeSpec()
-*/
-
-QString QDateTime::timeZoneAbbreviation() const
-{
- switch (getSpec(d)) {
- case Qt::UTC:
- return QLatin1String("UTC");
- case Qt::OffsetFromUTC:
- return QLatin1String("UTC") + toOffsetString(Qt::ISODate, d->m_offsetFromUtc);
- case Qt::TimeZone:
-#if !QT_CONFIG(timezone)
- break;
-#else
- return d->m_timeZone.d->abbreviation(toMSecsSinceEpoch());
-#endif // timezone
- case Qt::LocalTime: {
- QString abbrev;
- auto status = extractDaylightStatus(getStatus(d));
- localMSecsToEpochMSecs(getMSecs(d), &status, 0, 0, &abbrev);
- return abbrev;
- }
- }
- return QString();
-}
-
-/*!
- \since 5.2
-
- Returns if this datetime falls in Daylight-Saving Time.
-
- If the Qt::TimeSpec is not Qt::LocalTime or Qt::TimeZone then will always
- return false.
-
- \sa timeSpec()
-*/
-
-bool QDateTime::isDaylightTime() const
-{
- switch (getSpec(d)) {
- case Qt::UTC:
- case Qt::OffsetFromUTC:
- return false;
- case Qt::TimeZone:
-#if !QT_CONFIG(timezone)
- break;
-#else
- return d->m_timeZone.d->isDaylightTime(toMSecsSinceEpoch());
-#endif // timezone
- case Qt::LocalTime: {
- auto status = extractDaylightStatus(getStatus(d));
- if (status == QDateTimePrivate::UnknownDaylightTime)
- localMSecsToEpochMSecs(getMSecs(d), &status);
- return (status == QDateTimePrivate::DaylightTime);
- }
- }
- return false;
-}
-
-/*!
- Sets the date part of this datetime to \a date. If no time is set yet, it
- is set to midnight. If \a date is invalid, this QDateTime becomes invalid.
-
- \sa date(), setTime(), setTimeSpec()
-*/
-
-void QDateTime::setDate(const QDate &date)
-{
- setDateTime(d, date, time());
-}
-
-/*!
- Sets the time part of this datetime to \a time. If \a time is not valid,
- this function sets it to midnight. Therefore, it's possible to clear any
- set time in a QDateTime by setting it to a default QTime:
-
- \code
- QDateTime dt = QDateTime::currentDateTime();
- dt.setTime(QTime());
- \endcode
-
- \sa time(), setDate(), setTimeSpec()
-*/
-
-void QDateTime::setTime(const QTime &time)
-{
- setDateTime(d, date(), time);
-}
-
-/*!
- Sets the time specification used in this datetime to \a spec.
- The datetime will refer to a different point in time.
-
- If \a spec is Qt::OffsetFromUTC then the timeSpec() will be set
- to Qt::UTC, i.e. an effective offset of 0.
-
- If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
- i.e. the current system time zone.
-
- Example:
- \snippet code/src_corelib_tools_qdatetime.cpp 19
-
- \sa timeSpec(), setDate(), setTime(), setTimeZone(), Qt::TimeSpec
-*/
-
-void QDateTime::setTimeSpec(Qt::TimeSpec spec)
-{
- QT_PREPEND_NAMESPACE(setTimeSpec(d, spec, 0));
- checkValidDateTime(d);
-}
-
-/*!
- \since 5.2
-
- Sets the timeSpec() to Qt::OffsetFromUTC and the offset to \a offsetSeconds.
- The datetime will refer to a different point in time.
-
- The maximum and minimum offset is 14 positive or negative hours. If
- \a offsetSeconds is larger or smaller than that, then the result is
- undefined.
-
- If \a offsetSeconds is 0 then the timeSpec() will be set to Qt::UTC.
-
- \sa isValid(), offsetFromUtc()
-*/
-
-void QDateTime::setOffsetFromUtc(int offsetSeconds)
-{
- QT_PREPEND_NAMESPACE(setTimeSpec(d, Qt::OffsetFromUTC, offsetSeconds));
- checkValidDateTime(d);
-}
-
-#if QT_CONFIG(timezone)
-/*!
- \since 5.2
-
- Sets the time zone used in this datetime to \a toZone.
- The datetime will refer to a different point in time.
-
- If \a toZone is invalid then the datetime will be invalid.
-
- \sa timeZone(), Qt::TimeSpec
-*/
-
-void QDateTime::setTimeZone(const QTimeZone &toZone)
-{
- d.detach(); // always detach
- d->m_status = mergeSpec(d->m_status, Qt::TimeZone);
- d->m_offsetFromUtc = 0;
- d->m_timeZone = toZone;
- refreshDateTime(d);
-}
-#endif // timezone
-
-/*!
- \since 4.7
-
- Returns the datetime as the number of milliseconds that have passed
- since 1970-01-01T00:00:00.000, Coordinated Universal Time (Qt::UTC).
-
- On systems that do not support time zones, this function will
- behave as if local time were Qt::UTC.
-
- The behavior for this function is undefined if the datetime stored in
- this object is not valid. However, for all valid dates, this function
- returns a unique value.
-
- \sa toSecsSinceEpoch(), setMSecsSinceEpoch()
-*/
-qint64 QDateTime::toMSecsSinceEpoch() const
-{
- switch (getSpec(d)) {
- case Qt::UTC:
- return getMSecs(d);
-
- case Qt::OffsetFromUTC:
- return d->m_msecs - (d->m_offsetFromUtc * 1000);
-
- case Qt::LocalTime: {
- // recalculate the local timezone
- auto status = extractDaylightStatus(getStatus(d));
- return localMSecsToEpochMSecs(getMSecs(d), &status);
- }
-
- case Qt::TimeZone:
-#if !QT_CONFIG(timezone)
- return 0;
-#else
- return QDateTimePrivate::zoneMSecsToEpochMSecs(d->m_msecs, d->m_timeZone,
- extractDaylightStatus(getStatus(d)));
-#endif
- }
- Q_UNREACHABLE();
- return 0;
-}
-
-/*!
- \since 5.8
-
- Returns the datetime as the number of seconds that have passed since
- 1970-01-01T00:00:00.000, Coordinated Universal Time (Qt::UTC).
-
- On systems that do not support time zones, this function will
- behave as if local time were Qt::UTC.
-
- The behavior for this function is undefined if the datetime stored in
- this object is not valid. However, for all valid dates, this function
- returns a unique value.
-
- \sa toMSecsSinceEpoch(), setSecsSinceEpoch()
-*/
-qint64 QDateTime::toSecsSinceEpoch() const
-{
- return toMSecsSinceEpoch() / 1000;
-}
-
-#if QT_DEPRECATED_SINCE(5, 8)
-/*!
- \deprecated
-
- Returns the datetime as the number of seconds that have passed
- since 1970-01-01T00:00:00, Coordinated Universal Time (Qt::UTC).
-
- On systems that do not support time zones, this function will
- behave as if local time were Qt::UTC.
-
- \note This function returns a 32-bit unsigned integer and is deprecated.
-
- If the date is outside the range 1970-01-01T00:00:00 to
- 2106-02-07T06:28:14, this function returns -1 cast to an unsigned integer
- (i.e., 0xFFFFFFFF).
-
- To get an extended range, use toMSecsSinceEpoch() or toSecsSinceEpoch().
-
- \sa toSecsSinceEpoch(), toMSecsSinceEpoch(), setTime_t()
-*/
-
-uint QDateTime::toTime_t() const
-{
- if (!isValid())
- return uint(-1);
- qint64 retval = toMSecsSinceEpoch() / 1000;
- if (quint64(retval) >= Q_UINT64_C(0xFFFFFFFF))
- return uint(-1);
- return uint(retval);
-}
-#endif
-
-/*!
- \since 4.7
-
- Sets the date and time given the number of milliseconds \a msecs that have
- passed since 1970-01-01T00:00:00.000, Coordinated Universal Time
- (Qt::UTC). On systems that do not support time zones this function
- will behave as if local time were Qt::UTC.
-
- Note that passing the minimum of \c qint64
- (\c{std::numeric_limits<qint64>::min()}) to \a msecs will result in
- undefined behavior.
-
- \sa toMSecsSinceEpoch(), setSecsSinceEpoch()
-*/
-void QDateTime::setMSecsSinceEpoch(qint64 msecs)
-{
- const auto spec = getSpec(d);
- auto status = getStatus(d);
-
- status &= ~QDateTimePrivate::ValidityMask;
- switch (spec) {
- case Qt::UTC:
- status = status
- | QDateTimePrivate::ValidDate
- | QDateTimePrivate::ValidTime
- | QDateTimePrivate::ValidDateTime;
- break;
- case Qt::OffsetFromUTC:
- msecs = msecs + (d->m_offsetFromUtc * 1000);
- status = status
- | QDateTimePrivate::ValidDate
- | QDateTimePrivate::ValidTime
- | QDateTimePrivate::ValidDateTime;
- break;
- case Qt::TimeZone:
- Q_ASSERT(!d.isShort());
-#if QT_CONFIG(timezone)
- // Docs state any LocalTime before 1970-01-01 will *not* have any DST applied
- // but all affected times afterwards will have DST applied.
- d.detach();
- if (msecs >= 0) {
- status = mergeDaylightStatus(status,
- d->m_timeZone.d->isDaylightTime(msecs)
- ? QDateTimePrivate::DaylightTime
- : QDateTimePrivate::StandardTime);
- d->m_offsetFromUtc = d->m_timeZone.d->offsetFromUtc(msecs);
- } else {
- status = mergeDaylightStatus(status, QDateTimePrivate::StandardTime);
- d->m_offsetFromUtc = d->m_timeZone.d->standardTimeOffset(msecs);
- }
- msecs = msecs + (d->m_offsetFromUtc * 1000);
- status = status
- | QDateTimePrivate::ValidDate
- | QDateTimePrivate::ValidTime
- | QDateTimePrivate::ValidDateTime;
-#endif // timezone
- break;
- case Qt::LocalTime: {
- QDate dt;
- QTime tm;
- QDateTimePrivate::DaylightStatus dstStatus;
- epochMSecsToLocalTime(msecs, &dt, &tm, &dstStatus);
- setDateTime(d, dt, tm);
- msecs = getMSecs(d);
- status = mergeDaylightStatus(getStatus(d), dstStatus);
- break;
- }
- }
-
- if (msecsCanBeSmall(msecs) && d.isShort()) {
- // we can keep short
- d.data.msecs = qintptr(msecs);
- d.data.status = status;
- } else {
- d.detach();
- d->m_status = status & ~QDateTimePrivate::ShortData;
- d->m_msecs = msecs;
- }
-
- if (spec == Qt::LocalTime || spec == Qt::TimeZone)
- refreshDateTime(d);
-}
-
-/*!
- \since 5.8
-
- Sets the date and time given the number of seconds \a secs that have
- passed since 1970-01-01T00:00:00.000, Coordinated Universal Time
- (Qt::UTC). On systems that do not support time zones this function
- will behave as if local time were Qt::UTC.
-
- \sa toSecsSinceEpoch(), setMSecsSinceEpoch()
-*/
-void QDateTime::setSecsSinceEpoch(qint64 secs)
-{
- setMSecsSinceEpoch(secs * 1000);
-}
-
-#if QT_DEPRECATED_SINCE(5, 8)
-/*!
- \fn void QDateTime::setTime_t(uint seconds)
- \deprecated
-
- Sets the date and time given the number of \a seconds that have
- passed since 1970-01-01T00:00:00, Coordinated Universal Time
- (Qt::UTC). On systems that do not support time zones this function
- will behave as if local time were Qt::UTC.
-
- \note This function is deprecated. For new code, use setSecsSinceEpoch().
-
- \sa toTime_t()
-*/
-
-void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
-{
- setMSecsSinceEpoch((qint64)secsSince1Jan1970UTC * 1000);
-}
-#endif
-
-#if QT_CONFIG(datestring)
-/*!
- \fn QString QDateTime::toString(Qt::DateFormat format) const
-
- \overload
-
- Returns the datetime as a string in the \a format given.
-
- If the \a format is Qt::TextDate, the string is formatted in
- the default way. QDate::shortDayName(), QDate::shortMonthName(),
- and QTime::toString() are used to generate the string, so the
- day and month names will be localized names using the system locale,
- i.e. QLocale::system(). An example of this formatting is
- "Wed May 20 03:40:13 1998".
-
- If the \a format is Qt::ISODate, the string format corresponds
- to the ISO 8601 extended specification for representations of
- dates and times, taking the form yyyy-MM-ddTHH:mm:ss[Z|[+|-]HH:mm],
- depending on the timeSpec() of the QDateTime. If the timeSpec()
- is Qt::UTC, Z will be appended to the string; if the timeSpec() is
- Qt::OffsetFromUTC, the offset in hours and minutes from UTC will
- be appended to the string. To include milliseconds in the ISO 8601
- date, use the \a format Qt::ISODateWithMs, which corresponds to
- yyyy-MM-ddTHH:mm:ss.zzz[Z|[+|-]HH:mm].
-
- If the \a format is Qt::SystemLocaleShortDate or
- Qt::SystemLocaleLongDate, the string format depends on the locale
- settings of the system. Identical to calling
- QLocale::system().toString(datetime, QLocale::ShortFormat) or
- QLocale::system().toString(datetime, QLocale::LongFormat).
-
- If the \a format is Qt::DefaultLocaleShortDate or
- Qt::DefaultLocaleLongDate, the string format depends on the
- default application locale. This is the locale set with
- QLocale::setDefault(), or the system locale if no default locale
- has been set. Identical to calling QLocale().toString(datetime,
- QLocale::ShortFormat) or QLocale().toString(datetime,
- QLocale::LongFormat).
-
- If the \a format is Qt::RFC2822Date, the string is formatted
- following \l{RFC 2822}.
-
- If the datetime is invalid, an empty string will be returned.
-
- \warning The Qt::ISODate format is only valid for years in the
- range 0 to 9999. This restriction may apply to locale-aware
- formats as well, depending on the locale settings.
-
- \sa fromString(), QDate::toString(), QTime::toString(),
- QLocale::toString()
-*/
-
-QString QDateTime::toString(Qt::DateFormat format) const
-{
- QString buf;
- if (!isValid())
- return buf;
-
- switch (format) {
- case Qt::SystemLocaleDate:
- case Qt::SystemLocaleShortDate:
- return QLocale::system().toString(*this, QLocale::ShortFormat);
- case Qt::SystemLocaleLongDate:
- return QLocale::system().toString(*this, QLocale::LongFormat);
- case Qt::LocaleDate:
- case Qt::DefaultLocaleShortDate:
- return QLocale().toString(*this, QLocale::ShortFormat);
- case Qt::DefaultLocaleLongDate:
- return QLocale().toString(*this, QLocale::LongFormat);
- case Qt::RFC2822Date: {
- buf = QLocale::c().toString(*this, QStringViewLiteral("dd MMM yyyy hh:mm:ss "));
- buf += toOffsetString(Qt::TextDate, offsetFromUtc());
- return buf;
- }
- default:
-#if QT_CONFIG(textdate)
- case Qt::TextDate: {
- const QPair<QDate, QTime> p = getDateTime(d);
- buf = p.first.toString(Qt::TextDate);
- // Insert time between date's day and year:
- buf.insert(buf.lastIndexOf(QLatin1Char(' ')),
- QLatin1Char(' ') + p.second.toString(Qt::TextDate));
- // Append zone/offset indicator, as appropriate:
- switch (timeSpec()) {
- case Qt::LocalTime:
- break;
-# if QT_CONFIG(timezone)
- case Qt::TimeZone:
- buf += QLatin1Char(' ') + d->m_timeZone.abbreviation(*this);
- break;
-# endif
- default:
- buf += QLatin1String(" GMT");
- if (getSpec(d) == Qt::OffsetFromUTC)
- buf += toOffsetString(Qt::TextDate, offsetFromUtc());
- }
- return buf;
- }
-#endif
- case Qt::ISODate:
- case Qt::ISODateWithMs: {
- const QPair<QDate, QTime> p = getDateTime(d);
- const QDate &dt = p.first;
- const QTime &tm = p.second;
- buf = dt.toString(Qt::ISODate);
- if (buf.isEmpty())
- return QString(); // failed to convert
- buf += QLatin1Char('T');
- buf += tm.toString(format);
- switch (getSpec(d)) {
- case Qt::UTC:
- buf += QLatin1Char('Z');
- break;
- case Qt::OffsetFromUTC:
-#if QT_CONFIG(timezone)
- case Qt::TimeZone:
-#endif
- buf += toOffsetString(Qt::ISODate, offsetFromUtc());
- break;
- default:
- break;
- }
- return buf;
- }
- }
-}
-
-/*!
- \fn QString QDateTime::toString(const QString &format) const
- \fn QString QDateTime::toString(QStringView format) const
-
- Returns the datetime as a string. The \a format parameter
- determines the format of the result string.
-
- These expressions may be used for the date:
-
- \table
- \header \li Expression \li Output
- \row \li d \li the day as number without a leading zero (1 to 31)
- \row \li dd \li the day as number with a leading zero (01 to 31)
- \row \li ddd
- \li the abbreviated localized day name (e.g. 'Mon' to 'Sun').
- Uses the system locale to localize the name, i.e. QLocale::system().
- \row \li dddd
- \li the long localized day name (e.g. 'Monday' to 'Sunday').
- Uses the system locale to localize the name, i.e. QLocale::system().
- \row \li M \li the month as number without a leading zero (1-12)
- \row \li MM \li the month as number with a leading zero (01-12)
- \row \li MMM
- \li the abbreviated localized month name (e.g. 'Jan' to 'Dec').
- Uses the system locale to localize the name, i.e. QLocale::system().
- \row \li MMMM
- \li the long localized month name (e.g. 'January' to 'December').
- Uses the system locale to localize the name, i.e. QLocale::system().
- \row \li yy \li the year as two digit number (00-99)
- \row \li yyyy \li the year as four digit number
- \endtable
-
- These expressions may be used for the time:
-
- \table
- \header \li Expression \li Output
- \row \li h
- \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
- \row \li hh
- \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
- \row \li H
- \li the hour without a leading zero (0 to 23, even with AM/PM display)
- \row \li HH
- \li the hour with a leading zero (00 to 23, even with AM/PM display)
- \row \li m \li the minute without a leading zero (0 to 59)
- \row \li mm \li the minute with a leading zero (00 to 59)
- \row \li s \li the whole second without a leading zero (0 to 59)
- \row \li ss \li the whole second with a leading zero where applicable (00 to 59)
- \row \li z \li the fractional part of the second, to go after a decimal
- point, without trailing zeroes (0 to 999). Thus "\c{s.z}"
- reports the seconds to full available (millisecond) precision
- without trailing zeroes.
- \row \li zzz \li the fractional part of the second, to millisecond
- precision, including trailing zeroes where applicable (000 to 999).
- \row \li AP or A
- \li use AM/PM display. \e A/AP will be replaced by either "AM" or "PM".
- \row \li ap or a
- \li use am/pm display. \e a/ap will be replaced by either "am" or "pm".
- \row \li t \li the timezone (for example "CEST")
- \endtable
-
- Any sequence of characters enclosed in single quotes will be included
- verbatim in the output string (stripped of the quotes), even if it contains
- formatting characters. Two consecutive single quotes ("''") are replaced by
- a single quote in the output. All other characters in the format string are
- included verbatim in the output string.
-
- Formats without separators (e.g. "ddMM") are supported but must be used with
- care, as the resulting strings aren't always reliably readable (e.g. if "dM"
- produces "212" it could mean either the 2nd of December or the 21st of
- February).
-
- Example format strings (assumed that the QDateTime is 21 May 2001
- 14:13:09.120):
-
- \table
- \header \li Format \li Result
- \row \li dd.MM.yyyy \li 21.05.2001
- \row \li ddd MMMM d yy \li Tue May 21 01
- \row \li hh:mm:ss.zzz \li 14:13:09.120
- \row \li hh:mm:ss.z \li 14:13:09.12
- \row \li h:m:s ap \li 2:13:9 pm
- \endtable
-
- If the datetime is invalid, an empty string will be returned.
-
- \sa fromString(), QDate::toString(), QTime::toString(), QLocale::toString()
-*/
-QString QDateTime::toString(QStringView format) const
-{
- return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
-}
-
-#if QT_STRINGVIEW_LEVEL < 2
-QString QDateTime::toString(const QString &format) const
-{
- return toString(qToStringViewIgnoringNull(format));
-}
-#endif
-
-#endif // datestring
-
-static inline void massageAdjustedDateTime(const QDateTimeData &d, QDate *date, QTime *time)
-{
- /*
- If we have just adjusted to a day with a DST transition, our given time
- may lie in the transition hour (either missing or duplicated). For any
- other time, telling mktime (deep in the bowels of localMSecsToEpochMSecs)
- we don't know its DST-ness will produce no adjustment (just a decision as
- to its DST-ness); but for a time in spring's missing hour it'll adjust the
- time while picking a DST-ness. (Handling of autumn is trickier, as either
- DST-ness is valid, without adjusting the time. We might want to propagate
- the daylight status in that case, but it's hard to do so without breaking
- (far more common) other cases; and it makes little difference, as the two
- answers do then differ only in DST-ness.)
- */
- auto spec = getSpec(d);
- if (spec == Qt::LocalTime) {
- QDateTimePrivate::DaylightStatus status = QDateTimePrivate::UnknownDaylightTime;
- localMSecsToEpochMSecs(timeToMSecs(*date, *time), &status, date, time);
-#if QT_CONFIG(timezone)
- } else if (spec == Qt::TimeZone) {
- QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(*date, *time),
- d->m_timeZone,
- QDateTimePrivate::UnknownDaylightTime,
- date, time);
-#endif // timezone
- }
-}
-
-/*!
- Returns a QDateTime object containing a datetime \a ndays days
- later than the datetime of this object (or earlier if \a ndays is
- negative).
-
- If the timeSpec() is Qt::LocalTime and the resulting
- date and time fall in the Standard Time to Daylight-Saving Time transition
- hour then the result will be adjusted accordingly, i.e. if the transition
- is at 2am and the clock goes forward to 3am and the result falls between
- 2am and 3am then the result will be adjusted to fall after 3am.
-
- \sa daysTo(), addMonths(), addYears(), addSecs()
-*/
-
-QDateTime QDateTime::addDays(qint64 ndays) const
-{
- QDateTime dt(*this);
- QPair<QDate, QTime> p = getDateTime(d);
- QDate &date = p.first;
- QTime &time = p.second;
- date = date.addDays(ndays);
- massageAdjustedDateTime(dt.d, &date, &time);
- setDateTime(dt.d, date, time);
- return dt;
-}
-
-/*!
- Returns a QDateTime object containing a datetime \a nmonths months
- later than the datetime of this object (or earlier if \a nmonths
- is negative).
-
- If the timeSpec() is Qt::LocalTime and the resulting
- date and time fall in the Standard Time to Daylight-Saving Time transition
- hour then the result will be adjusted accordingly, i.e. if the transition
- is at 2am and the clock goes forward to 3am and the result falls between
- 2am and 3am then the result will be adjusted to fall after 3am.
-
- \sa daysTo(), addDays(), addYears(), addSecs()
-*/
-
-QDateTime QDateTime::addMonths(int nmonths) const
-{
- QDateTime dt(*this);
- QPair<QDate, QTime> p = getDateTime(d);
- QDate &date = p.first;
- QTime &time = p.second;
- date = date.addMonths(nmonths);
- massageAdjustedDateTime(dt.d, &date, &time);
- setDateTime(dt.d, date, time);
- return dt;
-}
-
-/*!
- Returns a QDateTime object containing a datetime \a nyears years
- later than the datetime of this object (or earlier if \a nyears is
- negative).
-
- If the timeSpec() is Qt::LocalTime and the resulting
- date and time fall in the Standard Time to Daylight-Saving Time transition
- hour then the result will be adjusted accordingly, i.e. if the transition
- is at 2am and the clock goes forward to 3am and the result falls between
- 2am and 3am then the result will be adjusted to fall after 3am.
-
- \sa daysTo(), addDays(), addMonths(), addSecs()
-*/
-
-QDateTime QDateTime::addYears(int nyears) const
-{
- QDateTime dt(*this);
- QPair<QDate, QTime> p = getDateTime(d);
- QDate &date = p.first;
- QTime &time = p.second;
- date = date.addYears(nyears);
- massageAdjustedDateTime(dt.d, &date, &time);
- setDateTime(dt.d, date, time);
- return dt;
-}
-
-/*!
- Returns a QDateTime object containing a datetime \a s seconds
- later than the datetime of this object (or earlier if \a s is
- negative).
-
- If this datetime is invalid, an invalid datetime will be returned.
-
- \sa addMSecs(), secsTo(), addDays(), addMonths(), addYears()
-*/
-
-QDateTime QDateTime::addSecs(qint64 s) const
-{
- return addMSecs(s * 1000);
-}
-
-/*!
- Returns a QDateTime object containing a datetime \a msecs miliseconds
- later than the datetime of this object (or earlier if \a msecs is
- negative).
-
- If this datetime is invalid, an invalid datetime will be returned.
-
- \sa addSecs(), msecsTo(), addDays(), addMonths(), addYears()
-*/
-QDateTime QDateTime::addMSecs(qint64 msecs) const
-{
- if (!isValid())
- return QDateTime();
-
- QDateTime dt(*this);
- auto spec = getSpec(d);
- if (spec == Qt::LocalTime || spec == Qt::TimeZone) {
- // Convert to real UTC first in case crosses DST transition
- dt.setMSecsSinceEpoch(toMSecsSinceEpoch() + msecs);
- } else {
- // No need to convert, just add on
- if (d.isShort()) {
- // need to check if we need to enlarge first
- msecs += dt.d.data.msecs;
- if (msecsCanBeSmall(msecs)) {
- dt.d.data.msecs = qintptr(msecs);
- } else {
- dt.d.detach();
- dt.d->m_msecs = msecs;
- }
- } else {
- dt.d.detach();
- dt.d->m_msecs += msecs;
- }
- }
- return dt;
-}
-
-/*!
- Returns the number of days from this datetime to the \a other
- datetime. The number of days is counted as the number of times
- midnight is reached between this datetime to the \a other
- datetime. This means that a 10 minute difference from 23:55 to
- 0:05 the next day counts as one day.
-
- If the \a other datetime is earlier than this datetime,
- the value returned is negative.
-
- Example:
- \snippet code/src_corelib_tools_qdatetime.cpp 15
-
- \sa addDays(), secsTo(), msecsTo()
-*/
-
-qint64 QDateTime::daysTo(const QDateTime &other) const
-{
- return date().daysTo(other.date());
-}
-
-/*!
- Returns the number of seconds from this datetime to the \a other
- datetime. If the \a other datetime is earlier than this datetime,
- the value returned is negative.
-
- Before performing the comparison, the two datetimes are converted
- to Qt::UTC to ensure that the result is correct if daylight-saving
- (DST) applies to one of the two datetimes but not the other.
-
- Returns 0 if either datetime is invalid.
-
- Example:
- \snippet code/src_corelib_tools_qdatetime.cpp 11
-
- \sa addSecs(), daysTo(), QTime::secsTo()
-*/
-
-qint64 QDateTime::secsTo(const QDateTime &other) const
-{
- return (msecsTo(other) / 1000);
-}
-
-/*!
- Returns the number of milliseconds from this datetime to the \a other
- datetime. If the \a other datetime is earlier than this datetime,
- the value returned is negative.
-
- Before performing the comparison, the two datetimes are converted
- to Qt::UTC to ensure that the result is correct if daylight-saving
- (DST) applies to one of the two datetimes and but not the other.
-
- Returns 0 if either datetime is invalid.
-
- \sa addMSecs(), daysTo(), QTime::msecsTo()
-*/
-
-qint64 QDateTime::msecsTo(const QDateTime &other) const
-{
- if (!isValid() || !other.isValid())
- return 0;
-
- return other.toMSecsSinceEpoch() - toMSecsSinceEpoch();
-}
-
-/*!
- \fn QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
-
- Returns a copy of this datetime converted to the given time
- \a spec.
-
- If \a spec is Qt::OffsetFromUTC then it is set to Qt::UTC. To set to a
- spec of Qt::OffsetFromUTC use toOffsetFromUtc().
-
- If \a spec is Qt::TimeZone then it is set to Qt::LocalTime,
- i.e. the local Time Zone.
-
- Example:
- \snippet code/src_corelib_tools_qdatetime.cpp 16
-
- \sa timeSpec(), toTimeZone(), toUTC(), toLocalTime()
-*/
-
-QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
-{
- if (getSpec(d) == spec && (spec == Qt::UTC || spec == Qt::LocalTime))
- return *this;
-
- if (!isValid()) {
- QDateTime ret = *this;
- ret.setTimeSpec(spec);
- return ret;
- }
-
- return fromMSecsSinceEpoch(toMSecsSinceEpoch(), spec, 0);
-}
-
-/*!
- \since 5.2
-
- \fn QDateTime QDateTime::toOffsetFromUtc(int offsetSeconds) const
-
- Returns a copy of this datetime converted to a spec of Qt::OffsetFromUTC
- with the given \a offsetSeconds.
-
- If the \a offsetSeconds equals 0 then a UTC datetime will be returned
-
- \sa setOffsetFromUtc(), offsetFromUtc(), toTimeSpec()
-*/
-
-QDateTime QDateTime::toOffsetFromUtc(int offsetSeconds) const
-{
- if (getSpec(d) == Qt::OffsetFromUTC
- && d->m_offsetFromUtc == offsetSeconds)
- return *this;
-
- if (!isValid()) {
- QDateTime ret = *this;
- ret.setOffsetFromUtc(offsetSeconds);
- return ret;
- }
-
- return fromMSecsSinceEpoch(toMSecsSinceEpoch(), Qt::OffsetFromUTC, offsetSeconds);
-}
-
-#if QT_CONFIG(timezone)
-/*!
- \since 5.2
-
- Returns a copy of this datetime converted to the given \a timeZone
-
- \sa timeZone(), toTimeSpec()
-*/
-
-QDateTime QDateTime::toTimeZone(const QTimeZone &timeZone) const
-{
- if (getSpec(d) == Qt::TimeZone && d->m_timeZone == timeZone)
- return *this;
-
- if (!isValid()) {
- QDateTime ret = *this;
- ret.setTimeZone(timeZone);
- return ret;
- }
-
- return fromMSecsSinceEpoch(toMSecsSinceEpoch(), timeZone);
-}
-#endif // timezone
-
-/*!
- Returns \c true if this datetime is equal to the \a other datetime;
- otherwise returns \c false.
-
- \sa operator!=()
-*/
-
-bool QDateTime::operator==(const QDateTime &other) const
-{
- if (getSpec(d) == Qt::LocalTime
- && getStatus(d) == getStatus(other.d)) {
- return getMSecs(d) == getMSecs(other.d);
- }
- // Convert to UTC and compare
- return (toMSecsSinceEpoch() == other.toMSecsSinceEpoch());
-}
-
-/*!
- \fn bool QDateTime::operator!=(const QDateTime &other) const
-
- Returns \c true if this datetime is different from the \a other
- datetime; otherwise returns \c false.
-
- Two datetimes are different if either the date, the time, or the
- time zone components are different.
-
- \sa operator==()
-*/
-
-/*!
- Returns \c true if this datetime is earlier than the \a other
- datetime; otherwise returns \c false.
-*/
-
-bool QDateTime::operator<(const QDateTime &other) const
-{
- if (getSpec(d) == Qt::LocalTime
- && getStatus(d) == getStatus(other.d)) {
- return getMSecs(d) < getMSecs(other.d);
- }
- // Convert to UTC and compare
- return (toMSecsSinceEpoch() < other.toMSecsSinceEpoch());
-}
-
-/*!
- \fn bool QDateTime::operator<=(const QDateTime &other) const
-
- Returns \c true if this datetime is earlier than or equal to the
- \a other datetime; otherwise returns \c false.
-*/
-
-/*!
- \fn bool QDateTime::operator>(const QDateTime &other) const
-
- Returns \c true if this datetime is later than the \a other datetime;
- otherwise returns \c false.
-*/
-
-/*!
- \fn bool QDateTime::operator>=(const QDateTime &other) const
-
- Returns \c true if this datetime is later than or equal to the
- \a other datetime; otherwise returns \c false.
-*/
-
-/*!
- \fn QDateTime QDateTime::currentDateTime()
- Returns the current datetime, as reported by the system clock, in
- the local time zone.
-
- \sa currentDateTimeUtc(), QDate::currentDate(), QTime::currentTime(), toTimeSpec()
-*/
-
-/*!
- \fn QDateTime QDateTime::currentDateTimeUtc()
- \since 4.7
- Returns the current datetime, as reported by the system clock, in
- UTC.
-
- \sa currentDateTime(), QDate::currentDate(), QTime::currentTime(), toTimeSpec()
-*/
-
-/*!
- \fn qint64 QDateTime::currentMSecsSinceEpoch()
- \since 4.7
-
- Returns the number of milliseconds since 1970-01-01T00:00:00 Universal
- Coordinated Time. This number is like the POSIX time_t variable, but
- expressed in milliseconds instead.
-
- \sa currentDateTime(), currentDateTimeUtc(), toTime_t(), toTimeSpec()
-*/
-
-/*!
- \fn qint64 QDateTime::currentSecsSinceEpoch()
- \since 5.8
-
- Returns the number of seconds since 1970-01-01T00:00:00 Universal
- Coordinated Time.
-
- \sa currentMSecsSinceEpoch()
-*/
-
-#if defined(Q_OS_WIN)
-static inline uint msecsFromDecomposed(int hour, int minute, int sec, int msec = 0)
-{
- return MSECS_PER_HOUR * hour + MSECS_PER_MIN * minute + 1000 * sec + msec;
-}
-
-QDate QDate::currentDate()
-{
- QDate d;
- SYSTEMTIME st;
- memset(&st, 0, sizeof(SYSTEMTIME));
- GetLocalTime(&st);
- d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
- return d;
-}
-
-QTime QTime::currentTime()
-{
- QTime ct;
- SYSTEMTIME st;
- memset(&st, 0, sizeof(SYSTEMTIME));
- GetLocalTime(&st);
- ct.setHMS(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
- return ct;
-}
-
-QDateTime QDateTime::currentDateTime()
-{
- QDate d;
- QTime t;
- SYSTEMTIME st;
- memset(&st, 0, sizeof(SYSTEMTIME));
- GetLocalTime(&st);
- d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
- t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
- return QDateTime(d, t);
-}
-
-QDateTime QDateTime::currentDateTimeUtc()
-{
- QDate d;
- QTime t;
- SYSTEMTIME st;
- memset(&st, 0, sizeof(SYSTEMTIME));
- GetSystemTime(&st);
- d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
- t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
- return QDateTime(d, t, Qt::UTC);
-}
-
-qint64 QDateTime::currentMSecsSinceEpoch() noexcept
-{
- SYSTEMTIME st;
- memset(&st, 0, sizeof(SYSTEMTIME));
- GetSystemTime(&st);
-
- return msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds) +
- qint64(julianDayFromDate(st.wYear, st.wMonth, st.wDay)
- - julianDayFromDate(1970, 1, 1)) * Q_INT64_C(86400000);
-}
-
-qint64 QDateTime::currentSecsSinceEpoch() noexcept
-{
- SYSTEMTIME st;
- memset(&st, 0, sizeof(SYSTEMTIME));
- GetSystemTime(&st);
-
- return st.wHour * SECS_PER_HOUR + st.wMinute * SECS_PER_MIN + st.wSecond +
- qint64(julianDayFromDate(st.wYear, st.wMonth, st.wDay)
- - julianDayFromDate(1970, 1, 1)) * Q_INT64_C(86400);
-}
-
-#elif defined(Q_OS_UNIX)
-QDate QDate::currentDate()
-{
- return QDateTime::currentDateTime().date();
-}
-
-QTime QTime::currentTime()
-{
- return QDateTime::currentDateTime().time();
-}
-
-QDateTime QDateTime::currentDateTime()
-{
- return fromMSecsSinceEpoch(currentMSecsSinceEpoch(), Qt::LocalTime);
-}
-
-QDateTime QDateTime::currentDateTimeUtc()
-{
- return fromMSecsSinceEpoch(currentMSecsSinceEpoch(), Qt::UTC);
-}
-
-qint64 QDateTime::currentMSecsSinceEpoch() noexcept
-{
- // posix compliant system
- // we have milliseconds
- struct timeval tv;
- gettimeofday(&tv, 0);
- return qint64(tv.tv_sec) * Q_INT64_C(1000) + tv.tv_usec / 1000;
-}
-
-qint64 QDateTime::currentSecsSinceEpoch() noexcept
-{
- struct timeval tv;
- gettimeofday(&tv, 0);
- return qint64(tv.tv_sec);
-}
-#else
-#error "What system is this?"
-#endif
-
-#if QT_DEPRECATED_SINCE(5, 8)
-/*!
- \since 4.2
- \deprecated
-
- Returns a datetime whose date and time are the number of \a seconds
- that have passed since 1970-01-01T00:00:00, Coordinated Universal
- Time (Qt::UTC) and converted to Qt::LocalTime. On systems that do not
- support time zones, the time will be set as if local time were Qt::UTC.
-
- \note This function is deprecated. Please use fromSecsSinceEpoch() in new
- code.
-
- \sa toTime_t(), setTime_t()
-*/
-QDateTime QDateTime::fromTime_t(uint seconds)
-{
- return fromMSecsSinceEpoch((qint64)seconds * 1000, Qt::LocalTime);
-}
-
-/*!
- \since 5.2
- \deprecated
-
- Returns a datetime whose date and time are the number of \a seconds
- that have passed since 1970-01-01T00:00:00, Coordinated Universal
- Time (Qt::UTC) and converted to the given \a spec.
-
- If the \a spec is not Qt::OffsetFromUTC then the \a offsetSeconds will be
- ignored. If the \a spec is Qt::OffsetFromUTC and the \a offsetSeconds is 0
- then the spec will be set to Qt::UTC, i.e. an offset of 0 seconds.
-
- \note This function is deprecated. Please use fromSecsSinceEpoch() in new
- code.
-
- \sa toTime_t(), setTime_t()
-*/
-QDateTime QDateTime::fromTime_t(uint seconds, Qt::TimeSpec spec, int offsetSeconds)
-{
- return fromMSecsSinceEpoch((qint64)seconds * 1000, spec, offsetSeconds);
-}
-
-#if QT_CONFIG(timezone)
-/*!
- \since 5.2
- \deprecated
-
- Returns a datetime whose date and time are the number of \a seconds
- that have passed since 1970-01-01T00:00:00, Coordinated Universal
- Time (Qt::UTC) and with the given \a timeZone.
-
- \note This function is deprecated. Please use fromSecsSinceEpoch() in new
- code.
-
- \sa toTime_t(), setTime_t()
-*/
-QDateTime QDateTime::fromTime_t(uint seconds, const QTimeZone &timeZone)
-{
- return fromMSecsSinceEpoch((qint64)seconds * 1000, timeZone);
-}
-#endif
-#endif // QT_DEPRECATED_SINCE(5, 8)
-
-/*!
- \since 4.7
-
- Returns a datetime whose date and time are the number of milliseconds, \a msecs,
- that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
- Time (Qt::UTC), and converted to Qt::LocalTime. On systems that do not
- support time zones, the time will be set as if local time were Qt::UTC.
-
- Note that there are possible values for \a msecs that lie outside the valid
- range of QDateTime, both negative and positive. The behavior of this
- function is undefined for those values.
-
- \sa toMSecsSinceEpoch(), setMSecsSinceEpoch()
-*/
-QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
-{
- return fromMSecsSinceEpoch(msecs, Qt::LocalTime);
-}
-
-/*!
- \since 5.2
-
- Returns a datetime whose date and time are the number of milliseconds \a msecs
- that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
- Time (Qt::UTC) and converted to the given \a spec.
-
- Note that there are possible values for \a msecs that lie outside the valid
- range of QDateTime, both negative and positive. The behavior of this
- function is undefined for those values.
-
- If the \a spec is not Qt::OffsetFromUTC then the \a offsetSeconds will be
- ignored. If the \a spec is Qt::OffsetFromUTC and the \a offsetSeconds is 0
- then the spec will be set to Qt::UTC, i.e. an offset of 0 seconds.
-
- If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
- i.e. the current system time zone.
-
- \sa toMSecsSinceEpoch(), setMSecsSinceEpoch()
-*/
-QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec, int offsetSeconds)
-{
- QDateTime dt;
- QT_PREPEND_NAMESPACE(setTimeSpec(dt.d, spec, offsetSeconds));
- dt.setMSecsSinceEpoch(msecs);
- return dt;
-}
-
-/*!
- \since 5.8
-
- Returns a datetime whose date and time are the number of seconds \a secs
- that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
- Time (Qt::UTC) and converted to the given \a spec.
-
- Note that there are possible values for \a secs that lie outside the valid
- range of QDateTime, both negative and positive. The behavior of this
- function is undefined for those values.
-
- If the \a spec is not Qt::OffsetFromUTC then the \a offsetSeconds will be
- ignored. If the \a spec is Qt::OffsetFromUTC and the \a offsetSeconds is 0
- then the spec will be set to Qt::UTC, i.e. an offset of 0 seconds.
-
- If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
- i.e. the current system time zone.
-
- \sa toSecsSinceEpoch(), setSecsSinceEpoch()
-*/
-QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, Qt::TimeSpec spec, int offsetSeconds)
-{
- return fromMSecsSinceEpoch(secs * 1000, spec, offsetSeconds);
-}
-
-#if QT_CONFIG(timezone)
-/*!
- \since 5.2
-
- Returns a datetime whose date and time are the number of milliseconds \a msecs
- that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
- Time (Qt::UTC) and with the given \a timeZone.
-
- \sa fromSecsSinceEpoch()
-*/
-QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone)
-{
- QDateTime dt;
- dt.setTimeZone(timeZone);
- dt.setMSecsSinceEpoch(msecs);
- return dt;
-}
-
-/*!
- \since 5.8
-
- Returns a datetime whose date and time are the number of seconds \a secs
- that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
- Time (Qt::UTC) and with the given \a timeZone.
-
- \sa fromMSecsSinceEpoch()
-*/
-QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, const QTimeZone &timeZone)
-{
- return fromMSecsSinceEpoch(secs * 1000, timeZone);
-}
-#endif
-
-#if QT_DEPRECATED_SINCE(5, 2)
-/*!
- \since 4.4
- \internal
- \obsolete
-
- This method was added in 4.4 but never documented as public. It was replaced
- in 5.2 with public method setOffsetFromUtc() for consistency with QTimeZone.
-
- This method should never be made public.
-
- \sa setOffsetFromUtc()
- */
-void QDateTime::setUtcOffset(int seconds)
-{
- setOffsetFromUtc(seconds);
-}
-
-/*!
- \since 4.4
- \internal
- \obsolete
-
- This method was added in 4.4 but never documented as public. It was replaced
- in 5.1 with public method offsetFromUTC() for consistency with QTimeZone.
-
- This method should never be made public.
-
- \sa offsetFromUTC()
-*/
-int QDateTime::utcOffset() const
-{
- return offsetFromUtc();
-}
-#endif // QT_DEPRECATED_SINCE
-
-#if QT_CONFIG(datestring)
-
-/*!
- Returns the QDateTime represented by the \a string, using the
- \a format given, or an invalid datetime if this is not possible.
-
- Note for Qt::TextDate: It is recommended that you use the
- English short month names (e.g. "Jan"). Although localized month
- names can also be used, they depend on the user's locale settings.
-
- \sa toString(), QLocale::toDateTime()
-*/
-QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
-{
- if (string.isEmpty())
- return QDateTime();
-
- switch (format) {
- case Qt::SystemLocaleDate:
- case Qt::SystemLocaleShortDate:
- return QLocale::system().toDateTime(string, QLocale::ShortFormat);
- case Qt::SystemLocaleLongDate:
- return QLocale::system().toDateTime(string, QLocale::LongFormat);
- case Qt::LocaleDate:
- case Qt::DefaultLocaleShortDate:
- return QLocale().toDateTime(string, QLocale::ShortFormat);
- case Qt::DefaultLocaleLongDate:
- return QLocale().toDateTime(string, QLocale::LongFormat);
- case Qt::RFC2822Date: {
- const ParsedRfcDateTime rfc = rfcDateImpl(string);
-
- if (!rfc.date.isValid() || !rfc.time.isValid())
- return QDateTime();
-
- QDateTime dateTime(rfc.date, rfc.time, Qt::UTC);
- dateTime.setOffsetFromUtc(rfc.utcOffset);
- return dateTime;
- }
- case Qt::ISODate:
- case Qt::ISODateWithMs: {
- const int size = string.size();
- if (size < 10)
- return QDateTime();
-
- QDate date = QDate::fromString(string.left(10), Qt::ISODate);
- if (!date.isValid())
- return QDateTime();
- if (size == 10)
- return QDateTime(date);
-
- Qt::TimeSpec spec = Qt::LocalTime;
- QStringRef isoString(&string);
- isoString = isoString.mid(10); // trim "yyyy-MM-dd"
-
- // Must be left with T and at least one digit for the hour:
- if (isoString.size() < 2
- || !(isoString.startsWith(QLatin1Char('T'))
- // FIXME: QSql relies on QVariant::toDateTime() accepting a space here:
- || isoString.startsWith(QLatin1Char(' ')))) {
- return QDateTime();
- }
- isoString = isoString.mid(1); // trim 'T' (or space)
-
- int offset = 0;
- // Check end of string for Time Zone definition, either Z for UTC or [+-]HH:mm for Offset
- if (isoString.endsWith(QLatin1Char('Z'))) {
- spec = Qt::UTC;
- isoString.chop(1); // trim 'Z'
- } else {
- // the loop below is faster but functionally equal to:
- // const int signIndex = isoString.indexOf(QRegExp(QStringLiteral("[+-]")));
- int signIndex = isoString.size() - 1;
- Q_ASSERT(signIndex >= 0);
- bool found = false;
- {
- const QChar plus = QLatin1Char('+');
- const QChar minus = QLatin1Char('-');
- do {
- QChar character(isoString.at(signIndex));
- found = character == plus || character == minus;
- } while (!found && --signIndex >= 0);
- }
-
- if (found) {
- bool ok;
- offset = fromOffsetString(isoString.mid(signIndex), &ok);
- if (!ok)
- return QDateTime();
- isoString = isoString.left(signIndex);
- spec = Qt::OffsetFromUTC;
- }
- }
-
- // Might be end of day (24:00, including variants), which QTime considers invalid.
- // ISO 8601 (section 4.2.3) says that 24:00 is equivalent to 00:00 the next day.
- bool isMidnight24 = false;
- QTime time = fromIsoTimeString(isoString, format, &isMidnight24);
- if (!time.isValid())
- return QDateTime();
- if (isMidnight24)
- date = date.addDays(1);
- return QDateTime(date, time, spec, offset);
- }
-#if QT_CONFIG(textdate)
- case Qt::TextDate: {
- QVector<QStringRef> parts = string.splitRef(QLatin1Char(' '), QString::SkipEmptyParts);
-
- if ((parts.count() < 5) || (parts.count() > 6))
- return QDateTime();
-
- // Accept "Sun Dec 1 13:02:00 1974" and "Sun 1. Dec 13:02:00 1974"
- int month = 0;
- int day = 0;
- bool ok = false;
-
- // First try month then day
- month = fromShortMonthName(parts.at(1));
- if (month)
- day = parts.at(2).toInt();
-
- // If failed try day then month
- if (!month || !day) {
- month = fromShortMonthName(parts.at(2));
- if (month) {
- QStringRef dayStr = parts.at(1);
- if (dayStr.endsWith(QLatin1Char('.'))) {
- dayStr = dayStr.left(dayStr.size() - 1);
- day = dayStr.toInt();
- }
- }
- }
-
- // If both failed, give up
- if (!month || !day)
- return QDateTime();
-
- // Year can be before or after time, "Sun Dec 1 1974 13:02:00" or "Sun Dec 1 13:02:00 1974"
- // Guess which by looking for ':' in the time
- int year = 0;
- int yearPart = 0;
- int timePart = 0;
- if (parts.at(3).contains(QLatin1Char(':'))) {
- yearPart = 4;
- timePart = 3;
- } else if (parts.at(4).contains(QLatin1Char(':'))) {
- yearPart = 3;
- timePart = 4;
- } else {
- return QDateTime();
- }
-
- year = parts.at(yearPart).toInt(&ok);
- if (!ok)
- return QDateTime();
-
- QDate date(year, month, day);
- if (!date.isValid())
- return QDateTime();
-
- QVector<QStringRef> timeParts = parts.at(timePart).split(QLatin1Char(':'));
- if (timeParts.count() < 2 || timeParts.count() > 3)
- return QDateTime();
-
- int hour = timeParts.at(0).toInt(&ok);
- if (!ok)
- return QDateTime();
-
- int minute = timeParts.at(1).toInt(&ok);
- if (!ok)
- return QDateTime();
-
- int second = 0;
- int millisecond = 0;
- if (timeParts.count() > 2) {
- const QVector<QStringRef> secondParts = timeParts.at(2).split(QLatin1Char('.'));
- if (secondParts.size() > 2) {
- return QDateTime();
- }
-
- second = secondParts.first().toInt(&ok);
- if (!ok) {
- return QDateTime();
- }
-
- if (secondParts.size() > 1) {
- millisecond = secondParts.last().toInt(&ok);
- if (!ok) {
- return QDateTime();
- }
- }
- }
-
- QTime time(hour, minute, second, millisecond);
- if (!time.isValid())
- return QDateTime();
-
- if (parts.count() == 5)
- return QDateTime(date, time, Qt::LocalTime);
-
- QStringRef tz = parts.at(5);
- if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive))
- return QDateTime();
- tz = tz.mid(3);
- if (!tz.isEmpty()) {
- int offset = fromOffsetString(tz, &ok);
- if (!ok)
- return QDateTime();
- return QDateTime(date, time, Qt::OffsetFromUTC, offset);
- } else {
- return QDateTime(date, time, Qt::UTC);
- }
- }
-#endif // textdate
- }
-
- return QDateTime();
-}
-
-/*!
- Returns the QDateTime represented by the \a string, using the \a
- format given, or an invalid datetime if the string cannot be parsed.
-
- These expressions may be used for the date part of the format string:
-
- \table
- \header \li Expression \li Output
- \row \li d \li the day as number without a leading zero (1 to 31)
- \row \li dd \li the day as number with a leading zero (01 to 31)
- \row \li ddd
- \li the abbreviated localized day name (e.g. 'Mon' to 'Sun').
- Uses QDate::shortDayName().
- \row \li dddd
- \li the long localized day name (e.g. 'Monday' to 'Sunday').
- Uses QDate::longDayName().
- \row \li M \li the month as number without a leading zero (1-12)
- \row \li MM \li the month as number with a leading zero (01-12)
- \row \li MMM
- \li the abbreviated localized month name (e.g. 'Jan' to 'Dec').
- Uses QDate::shortMonthName().
- \row \li MMMM
- \li the long localized month name (e.g. 'January' to 'December').
- Uses QDate::longMonthName().
- \row \li yy \li the year as two digit number (00-99)
- \row \li yyyy \li the year as four digit number
- \endtable
-
- \note Unlike the other version of this function, day and month names must
- be given in the user's local language. It is only possible to use the English
- names if the user's language is English.
-
- These expressions may be used for the time part of the format string:
-
- \table
- \header \li Expression \li Output
- \row \li h
- \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
- \row \li hh
- \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
- \row \li H
- \li the hour without a leading zero (0 to 23, even with AM/PM display)
- \row \li HH
- \li the hour with a leading zero (00 to 23, even with AM/PM display)
- \row \li m \li the minute without a leading zero (0 to 59)
- \row \li mm \li the minute with a leading zero (00 to 59)
- \row \li s \li the whole second without a leading zero (0 to 59)
- \row \li ss \li the whole second with a leading zero where applicable (00 to 59)
- \row \li z \li the fractional part of the second, to go after a decimal
- point, without trailing zeroes (0 to 999). Thus "\c{s.z}"
- reports the seconds to full available (millisecond) precision
- without trailing zeroes.
- \row \li zzz \li the fractional part of the second, to millisecond
- precision, including trailing zeroes where applicable (000 to 999).
- \row \li AP or A
- \li interpret as an AM/PM time. \e AP must be either "AM" or "PM".
- \row \li ap or a
- \li Interpret as an AM/PM time. \e ap must be either "am" or "pm".
- \endtable
-
- All other input characters will be treated as text. Any sequence
- of characters that are enclosed in single quotes will also be
- treated as text and not be used as an expression.
-
- \snippet code/src_corelib_tools_qdatetime.cpp 12
-
- If the format is not satisfied, an invalid QDateTime is returned.
- The expressions that don't have leading zeroes (d, M, h, m, s, z) will be
- greedy. This means that they will use two digits even if this will
- put them outside the range and/or leave too few digits for other
- sections.
-
- \snippet code/src_corelib_tools_qdatetime.cpp 13
-
- This could have meant 1 January 00:30.00 but the M will grab
- two digits.
-
- Incorrectly specified fields of the \a string will cause an invalid
- QDateTime to be returned. For example, consider the following code,
- where the two digit year 12 is read as 1912 (see the table below for all
- field defaults); the resulting datetime is invalid because 23 April 1912
- was a Tuesday, not a Monday:
-
- \snippet code/src_corelib_tools_qdatetime.cpp 20
-
- The correct code is:
-
- \snippet code/src_corelib_tools_qdatetime.cpp 21
-
- For any field that is not represented in the format, the following
- defaults are used:
-
- \table
- \header \li Field \li Default value
- \row \li Year \li 1900
- \row \li Month \li 1 (January)
- \row \li Day \li 1
- \row \li Hour \li 0
- \row \li Minute \li 0
- \row \li Second \li 0
- \endtable
-
- For example:
-
- \snippet code/src_corelib_tools_qdatetime.cpp 14
-
- \sa toString(), QDate::fromString(), QTime::fromString(),
- QLocale::toDateTime()
-*/
-
-QDateTime QDateTime::fromString(const QString &string, const QString &format)
-{
-#if QT_CONFIG(datetimeparser)
- QTime time;
- QDate date;
-
- QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString);
- // dt.setDefaultLocale(QLocale::c()); ### Qt 6
- if (dt.parseFormat(format) && dt.fromString(string, &date, &time))
- return QDateTime(date, time);
-#else
- Q_UNUSED(string);
- Q_UNUSED(format);
-#endif
- return QDateTime();
-}
-
-#endif // datestring
-/*!
- \fn QDateTime QDateTime::toLocalTime() const
-
- Returns a datetime containing the date and time information in
- this datetime, but specified using the Qt::LocalTime definition.
-
- Example:
-
- \snippet code/src_corelib_tools_qdatetime.cpp 17
-
- \sa toTimeSpec()
-*/
-
-/*!
- \fn QDateTime QDateTime::toUTC() const
-
- Returns a datetime containing the date and time information in
- this datetime, but specified using the Qt::UTC definition.
-
- Example:
-
- \snippet code/src_corelib_tools_qdatetime.cpp 18
-
- \sa toTimeSpec()
-*/
-
-/*****************************************************************************
- Date/time stream functions
- *****************************************************************************/
-
-#ifndef QT_NO_DATASTREAM
-/*!
- \relates QDate
-
- Writes the \a date to stream \a out.
-
- \sa {Serializing Qt Data Types}
-*/
-
-QDataStream &operator<<(QDataStream &out, const QDate &date)
-{
- if (out.version() < QDataStream::Qt_5_0)
- return out << quint32(date.jd);
- else
- return out << qint64(date.jd);
-}
-
-/*!
- \relates QDate
-
- Reads a date from stream \a in into the \a date.
-
- \sa {Serializing Qt Data Types}
-*/
-
-QDataStream &operator>>(QDataStream &in, QDate &date)
-{
- if (in.version() < QDataStream::Qt_5_0) {
- quint32 jd;
- in >> jd;
- // Older versions consider 0 an invalid jd.
- date.jd = (jd != 0 ? jd : QDate::nullJd());
- } else {
- qint64 jd;
- in >> jd;
- date.jd = jd;
- }
-
- return in;
-}
-
-/*!
- \relates QTime
-
- Writes \a time to stream \a out.
-
- \sa {Serializing Qt Data Types}
-*/
-
-QDataStream &operator<<(QDataStream &out, const QTime &time)
-{
- if (out.version() >= QDataStream::Qt_4_0) {
- return out << quint32(time.mds);
- } else {
- // Qt3 had no support for reading -1, QTime() was valid and serialized as 0
- return out << quint32(time.isNull() ? 0 : time.mds);
- }
-}
-
-/*!
- \relates QTime
-
- Reads a time from stream \a in into the given \a time.
-
- \sa {Serializing Qt Data Types}
-*/
-
-QDataStream &operator>>(QDataStream &in, QTime &time)
-{
- quint32 ds;
- in >> ds;
- if (in.version() >= QDataStream::Qt_4_0) {
- time.mds = int(ds);
- } else {
- // Qt3 would write 0 for a null time
- time.mds = (ds == 0) ? QTime::NullTime : int(ds);
- }
- return in;
-}
-
-/*!
- \relates QDateTime
-
- Writes \a dateTime to the \a out stream.
-
- \sa {Serializing Qt Data Types}
-*/
-QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
-{
- QPair<QDate, QTime> dateAndTime;
-
- if (out.version() >= QDataStream::Qt_5_2) {
-
- // In 5.2 we switched to using Qt::TimeSpec and added offset support
- dateAndTime = getDateTime(dateTime.d);
- out << dateAndTime << qint8(dateTime.timeSpec());
- if (dateTime.timeSpec() == Qt::OffsetFromUTC)
- out << qint32(dateTime.offsetFromUtc());
-#if QT_CONFIG(timezone)
- else if (dateTime.timeSpec() == Qt::TimeZone)
- out << dateTime.timeZone();
-#endif // timezone
-
- } else if (out.version() == QDataStream::Qt_5_0) {
-
- // In Qt 5.0 we incorrectly serialised all datetimes as UTC.
- // This approach is wrong and should not be used again; it breaks
- // the guarantee that a deserialised local datetime is the same time
- // of day, regardless of which timezone it was serialised in.
- dateAndTime = getDateTime((dateTime.isValid() ? dateTime.toUTC() : dateTime).d);
- out << dateAndTime << qint8(dateTime.timeSpec());
-
- } else if (out.version() >= QDataStream::Qt_4_0) {
-
- // From 4.0 to 5.1 (except 5.0) we used QDateTimePrivate::Spec
- dateAndTime = getDateTime(dateTime.d);
- out << dateAndTime;
- switch (dateTime.timeSpec()) {
- case Qt::UTC:
- out << (qint8)QDateTimePrivate::UTC;
- break;
- case Qt::OffsetFromUTC:
- out << (qint8)QDateTimePrivate::OffsetFromUTC;
- break;
- case Qt::TimeZone:
- out << (qint8)QDateTimePrivate::TimeZone;
- break;
- case Qt::LocalTime:
- out << (qint8)QDateTimePrivate::LocalUnknown;
- break;
- }
-
- } else { // version < QDataStream::Qt_4_0
-
- // Before 4.0 there was no TimeSpec, only Qt::LocalTime was supported
- dateAndTime = getDateTime(dateTime.d);
- out << dateAndTime;
-
- }
-
- return out;
-}
-
-/*!
- \relates QDateTime
-
- Reads a datetime from the stream \a in into \a dateTime.
-
- \sa {Serializing Qt Data Types}
-*/
-
-QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
-{
- QDate dt;
- QTime tm;
- qint8 ts = 0;
- Qt::TimeSpec spec = Qt::LocalTime;
- qint32 offset = 0;
-#if QT_CONFIG(timezone)
- QTimeZone tz;
-#endif // timezone
-
- if (in.version() >= QDataStream::Qt_5_2) {
-
- // In 5.2 we switched to using Qt::TimeSpec and added offset support
- in >> dt >> tm >> ts;
- spec = static_cast<Qt::TimeSpec>(ts);
- if (spec == Qt::OffsetFromUTC) {
- in >> offset;
- dateTime = QDateTime(dt, tm, spec, offset);
-#if QT_CONFIG(timezone)
- } else if (spec == Qt::TimeZone) {
- in >> tz;
- dateTime = QDateTime(dt, tm, tz);
-#endif // timezone
- } else {
- dateTime = QDateTime(dt, tm, spec);
- }
-
- } else if (in.version() == QDataStream::Qt_5_0) {
-
- // In Qt 5.0 we incorrectly serialised all datetimes as UTC
- in >> dt >> tm >> ts;
- spec = static_cast<Qt::TimeSpec>(ts);
- dateTime = QDateTime(dt, tm, Qt::UTC);
- dateTime = dateTime.toTimeSpec(spec);
-
- } else if (in.version() >= QDataStream::Qt_4_0) {
-
- // From 4.0 to 5.1 (except 5.0) we used QDateTimePrivate::Spec
- in >> dt >> tm >> ts;
- switch ((QDateTimePrivate::Spec)ts) {
- case QDateTimePrivate::UTC:
- spec = Qt::UTC;
- break;
- case QDateTimePrivate::OffsetFromUTC:
- spec = Qt::OffsetFromUTC;
- break;
- case QDateTimePrivate::TimeZone:
- spec = Qt::TimeZone;
-#if QT_CONFIG(timezone)
- // FIXME: need to use a different constructor !
-#endif
- break;
- case QDateTimePrivate::LocalUnknown:
- case QDateTimePrivate::LocalStandard:
- case QDateTimePrivate::LocalDST:
- spec = Qt::LocalTime;
- break;
- }
- dateTime = QDateTime(dt, tm, spec, offset);
-
- } else { // version < QDataStream::Qt_4_0
-
- // Before 4.0 there was no TimeSpec, only Qt::LocalTime was supported
- in >> dt >> tm;
- dateTime = QDateTime(dt, tm, spec, offset);
-
- }
-
- return in;
-}
-#endif // QT_NO_DATASTREAM
-
-/*****************************************************************************
- Date / Time Debug Streams
-*****************************************************************************/
-
-#if !defined(QT_NO_DEBUG_STREAM) && QT_CONFIG(datestring)
-QDebug operator<<(QDebug dbg, const QDate &date)
-{
- QDebugStateSaver saver(dbg);
- dbg.nospace() << "QDate(";
- if (date.isValid())
- dbg.nospace() << date.toString(Qt::ISODate);
- else
- dbg.nospace() << "Invalid";
- dbg.nospace() << ')';
- return dbg;
-}
-
-QDebug operator<<(QDebug dbg, const QTime &time)
-{
- QDebugStateSaver saver(dbg);
- dbg.nospace() << "QTime(";
- if (time.isValid())
- dbg.nospace() << time.toString(QStringViewLiteral("HH:mm:ss.zzz"));
- else
- dbg.nospace() << "Invalid";
- dbg.nospace() << ')';
- return dbg;
-}
-
-QDebug operator<<(QDebug dbg, const QDateTime &date)
-{
- QDebugStateSaver saver(dbg);
- dbg.nospace() << "QDateTime(";
- if (date.isValid()) {
- const Qt::TimeSpec ts = date.timeSpec();
- dbg.noquote() << date.toString(QStringViewLiteral("yyyy-MM-dd HH:mm:ss.zzz t"))
- << ' ' << ts;
- switch (ts) {
- case Qt::UTC:
- break;
- case Qt::OffsetFromUTC:
- dbg.space() << date.offsetFromUtc() << 's';
- break;
- case Qt::TimeZone:
-#if QT_CONFIG(timezone)
- dbg.space() << date.timeZone().id();
-#endif // timezone
- break;
- case Qt::LocalTime:
- break;
- }
- } else {
- dbg.nospace() << "Invalid";
- }
- return dbg.nospace() << ')';
-}
-#endif // debug_stream && datestring
-
-/*! \fn uint qHash(const QDateTime &key, uint seed = 0)
- \relates QHash
- \since 5.0
-
- Returns the hash value for the \a key, using \a seed to seed the calculation.
-*/
-uint qHash(const QDateTime &key, uint seed)
-{
- // Use to toMSecsSinceEpoch instead of individual qHash functions for
- // QDate/QTime/spec/offset because QDateTime::operator== converts both arguments
- // to the same timezone. If we don't, qHash would return different hashes for
- // two QDateTimes that are equivalent once converted to the same timezone.
- return qHash(key.toMSecsSinceEpoch(), seed);
-}
-
-/*! \fn uint qHash(const QDate &key, uint seed = 0)
- \relates QHash
- \since 5.0
-
- Returns the hash value for the \a key, using \a seed to seed the calculation.
-*/
-uint qHash(const QDate &key, uint seed) noexcept
-{
- return qHash(key.toJulianDay(), seed);
-}
-
-/*! \fn uint qHash(const QTime &key, uint seed = 0)
- \relates QHash
- \since 5.0
-
- Returns the hash value for the \a key, using \a seed to seed the calculation.
-*/
-uint qHash(const QTime &key, uint seed) noexcept
-{
- return qHash(key.msecsSinceStartOfDay(), seed);
-}
-
-QT_END_NAMESPACE