diff options
Diffstat (limited to 'src/corelib/time/qdatetime.cpp')
-rw-r--r-- | src/corelib/time/qdatetime.cpp | 145 |
1 files changed, 83 insertions, 62 deletions
diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index a2816e87f4..f881d47284 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -75,6 +75,7 @@ #include "qcalendar.h" #include "qgregoriancalendar_p.h" +#include "private/qnumeric_p.h" QT_BEGIN_NAMESPACE @@ -1429,9 +1430,11 @@ 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); + qint64 r; + if (Q_UNLIKELY(add_overflow(jd, ndays, &r))) + return QDate(); + else + return fromJulianDay(r); } /*! @@ -1701,22 +1704,25 @@ QT_WARNING_POP return rfcDateImpl(string).date; default: case Qt::TextDate: { + // Accept only "ddd MMM d yyyy" form (in contrast with QDateTime), e.g. "Sun Dec 1 1974" QVector<QStringRef> parts = string.splitRef(QLatin1Char(' '), Qt::SkipEmptyParts); - - if (parts.count() != 4) + const int count = parts.count(); + bool ok = count > 3; + int year = ok ? parts.at(count - 1).toInt(&ok) : 0; + int day = ok ? parts.at(count - 2).toInt(&ok) : 0; + if (!ok || !day || !year) return QDate(); - bool ok = false; - int year = parts.at(3).toInt(&ok); - int day = ok ? parts.at(2).toInt(&ok) : 0; - if (!ok || !day) - return QDate(); - - const int month = fromShortMonthName(parts.at(1), year); - if (month == -1) // Month name matches no English or localised name. - return QDate(); - - return QDate(year, month, day); + // Some locales have multi-word month names: + int i = count - 3; + QString monthName = parts.at(i).toString(); + while (i > 0) { + const int month = fromShortMonthName(monthName, year); + if (month > 0) // Month name matches an English or localised name. + return QDate(year, month, day); + monthName = parts.at(--i) + QLatin1Char(' ') + monthName; + } + return QDate(); } case Qt::ISODate: // Semi-strict parsing, must be long enough and have punctuators as separators @@ -2612,6 +2618,8 @@ bool QTime::isValid(int h, int m, int s, int ms) #if QT_DEPRECATED_SINCE(5, 14) // ### Qt 6: remove /*! + \deprecated + Sets this time to the current time. This is practical for timing: \snippet code/src_corelib_tools_qdatetime.cpp 10 @@ -2655,6 +2663,8 @@ int QTime::restart() } /*! + \deprecated + Returns the number of milliseconds that have elapsed since the last time start() or restart() was called. @@ -4541,9 +4551,9 @@ static inline void massageAdjustedDateTime(const QDateTimeData &d, QDate *date, QDateTimePrivate::DaylightStatus status = QDateTimePrivate::UnknownDaylightTime; localMSecsToEpochMSecs(timeToMSecs(*date, *time), &status, date, time); #if QT_CONFIG(timezone) - } else if (spec == Qt::TimeZone && d->m_timeZone.isValid()) { + } else if (spec == Qt::TimeZone && d.d->m_timeZone.isValid()) { QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(*date, *time), - d->m_timeZone, + d.d->m_timeZone, QDateTimePrivate::UnknownDaylightTime, date, time); #endif // timezone @@ -4644,7 +4654,7 @@ QDateTime QDateTime::addSecs(qint64 s) const } /*! - Returns a QDateTime object containing a datetime \a msecs miliseconds + Returns a QDateTime object containing a datetime \a msecs milliseconds later than the datetime of this object (or earlier if \a msecs is negative). @@ -5374,49 +5384,66 @@ QT_WARNING_POP case Qt::TextDate: { QVector<QStringRef> parts = string.splitRef(QLatin1Char(' '), Qt::SkipEmptyParts); - if ((parts.count() < 5) || (parts.count() > 6)) + const int count = parts.count(); + if (count < 5) return QDateTime(); - // Accept "Sun Dec 1 13:02:00 1974" and "Sun 1. Dec 13:02:00 1974" + // Accept "Sun Dec 1 13:02:00 1974" and "Sun 1. Dec 13:02:00 1974" with + // optional GMT-based zone-suffix, with time and year in either order; + // and some locales have spaces even in short names of months and days. + int tail = count - 1, zonePart = 0; + if (parts.at(tail).startsWith(QLatin1String("GMT"), Qt::CaseInsensitive)) + zonePart = tail--; // Year and time can be in either order. // Guess which by looking for ':' in the time - int yearPart = 3; - int timePart = 3; - if (parts.at(3).contains(QLatin1Char(':'))) - yearPart = 4; - else if (parts.at(4).contains(QLatin1Char(':'))) - timePart = 4; + int yearPart = tail; + int timePart = tail; + if (parts.at(timePart).contains(QLatin1Char(':'))) + yearPart--; + else if (parts.at(timePart - 1).contains(QLatin1Char(':'))) + timePart--; else return QDateTime(); - int month = 0; - int day = 0; - bool ok = false; + int dayPart = tail - 2; // but may be earlier, with a comma after: + for (int i = 1; i < dayPart; i++) { + if (parts.at(i).endsWith(QLatin1Char('.'))) + dayPart = i; // exits the loop + } + bool ok = false; int year = parts.at(yearPart).toInt(&ok); - if (!ok || year == 0) + int day = 0; + + if (ok && year) { + QStringRef dayStr = parts.at(dayPart); + if (dayStr.endsWith(QLatin1Char('.'))) + dayStr.chop(1); + day = dayStr.toInt(&ok); + } + if (!ok || !year || !day) return QDateTime(); - // Next try month then day - month = fromShortMonthName(parts.at(1), year); - if (month) - day = parts.at(2).toInt(&ok); - - // If failed, try day then month - if (!ok || !month || !day) { - month = fromShortMonthName(parts.at(2), year); - if (month) { - QStringRef dayStr = parts.at(1); - if (dayStr.endsWith(QLatin1Char('.'))) { - dayStr = dayStr.left(dayStr.size() - 1); - day = dayStr.toInt(&ok); - } + int month = 0; + if (dayPart < tail - 2) { + // Easy case, month is the parts from dayPart + 1 to count - 3 + int i = dayPart + 1; + QString monthName = parts.at(i).toString(); + while (++i < tail - 1) + monthName += QLatin1Char(' ') + parts.at(i); + month = fromShortMonthName(monthName, year); + } else { + int i = dayPart - 1; + QString monthName = parts.at(i).toString(); + while (i > 0) { + month = fromShortMonthName(monthName, year); + if (month > 0) + break; + monthName = parts.at(--i) + QLatin1Char(' ') + monthName; } } - - // If both failed, give up - if (!ok || !month || !day) + if (month <= 0) return QDateTime(); QDate date(year, month, day); @@ -5460,21 +5487,15 @@ QT_WARNING_POP if (!time.isValid()) return QDateTime(); - if (parts.count() == 5) + if (!zonePart) return QDateTime(date, time, Qt::LocalTime); - QStringView 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 { + const QStringView tz = parts.at(zonePart).mid(3); + if (tz.isEmpty()) return QDateTime(date, time, Qt::UTC); - } + + int offset = fromOffsetString(tz, &ok); + return ok ? QDateTime(date, time, Qt::OffsetFromUTC, offset) : QDateTime(); } } @@ -5573,7 +5594,7 @@ QDateTime QDateTime::fromString(const QString &string, const QString &format, QC return QDateTime(); } -/* +/*! \overload */ |