diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/io/qdatastream.cpp | 5 | ||||
-rw-r--r-- | src/corelib/io/qdatastream.h | 2 | ||||
-rw-r--r-- | src/corelib/tools/qdatetime.cpp | 457 | ||||
-rw-r--r-- | src/corelib/tools/qdatetime.h | 16 | ||||
-rw-r--r-- | src/corelib/tools/qdatetime_p.h | 20 |
5 files changed, 349 insertions, 151 deletions
diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index 52b80badb8..008460df5d 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -539,8 +539,8 @@ void QDataStream::setByteOrder(ByteOrder bo) \value Qt_4_8 Same as Qt_4_6. \value Qt_4_9 Same as Qt_4_6. \value Qt_5_0 Version 13 (Qt 5.0) - \value Qt_5_1 Version 14 (Qt 5.1, Qt 5.2) - \value Qt_5_2 Same as Qt_5_1. + \value Qt_5_1 Version 14 (Qt 5.1) + \value Qt_5_2 Version 15 (Qt 5.2) \sa setVersion(), version() */ @@ -572,6 +572,7 @@ void QDataStream::setByteOrder(ByteOrder bo) \table \header \li Qt Version \li QDataStream Version + \row \li Qt 5.2 \li 15 \row \li Qt 5.1 \li 14 \row \li Qt 5.0 \li 13 \row \li Qt 4.6 \li 12 diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h index eb064b3fe2..f107e801b6 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/io/qdatastream.h @@ -87,7 +87,7 @@ public: Qt_4_9 = Qt_4_8, Qt_5_0 = 13, Qt_5_1 = 14, - Qt_5_2 = Qt_5_1 + Qt_5_2 = 15 #if QT_VERSION >= 0x050300 #error Add the datastream version for this Qt version #endif diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index b47511c39c..da1f48a34c 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -172,6 +172,58 @@ int qt_monthNumberFromShortName(const QString &shortName) static QString fmtDateTime(const QString& f, const QTime* dt = 0, const QDate* dd = 0); static void rfcDateImpl(const QString &s, QDate *dd = 0, QTime *dt = 0, int *utfcOffset = 0); #endif +static QDateTimePrivate::Spec utcToLocal(QDate &date, QTime &time); +static void utcToOffset(QDate *date, QTime *time, qint32 offset); + +// Return offset in [+-]HH:MM format +// Qt::ISODate puts : between the hours and minutes, but Qt:TextDate does not +static QString toOffsetString(Qt::DateFormat format, int offset) +{ + QString result; + if (format == Qt::TextDate) + result = QStringLiteral("%1%2%3"); + else // Qt::ISODate + result = QStringLiteral("%1%2:%3"); + + return result.arg(offset >= 0 ? QLatin1Char('+') : QLatin1Char('-')) + .arg(qAbs(offset) / SECS_PER_HOUR, 2, 10, QLatin1Char('0')) + .arg((offset / 60) % 60, 2, 10, QLatin1Char('0')); +} + +// Parse offset in [+-]HH[:]MM format +static int fromOffsetString(const QString &offsetString, bool *valid) +{ + *valid = false; + + const int size = offsetString.size(); + if (size < 2 || size > 6) + return 0; + + // First char must be + or - + const QChar sign = offsetString.at(0); + if (sign != QLatin1Char('+') && sign != QLatin1Char('-')) + return 0; + + // Split the hour and minute parts + QStringList parts = offsetString.split(QLatin1Char(':')); + if (parts.count() == 1) { + // [+-]HHMM format + parts.append(parts.at(0).mid(3)); + parts[0] = parts.at(0).left(3); + } + + bool ok = false; + const int hour = parts.at(0).toInt(&ok); + if (!ok) + return 0; + + const int minute = parts.at(1).toInt(&ok); + if (!ok || minute < 0 || minute > 59) + return 0; + + *valid = true; + return ((hour * 60) + minute) * 60; +} /***************************************************************************** QDate member functions @@ -2165,6 +2217,20 @@ int QTime::elapsed() const time zone before 1970, even if the system's time zone database supports that information. + \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 Savings 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. + \sa QDate, QTime, QDateTimeEdit */ @@ -2186,10 +2252,8 @@ QDateTime::QDateTime() */ QDateTime::QDateTime(const QDate &date) - : d(new QDateTimePrivate) + : d(new QDateTimePrivate(date, QTime(0, 0, 0), Qt::LocalTime, 0)) { - d->date = date; - d->time = QTime(0, 0, 0); } /*! @@ -2197,14 +2261,72 @@ QDateTime::QDateTime(const QDate &date) 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. */ QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec) - : d(new QDateTimePrivate) + : d(new QDateTimePrivate(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. +*/ + +QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec, int offsetSeconds) + : d(new QDateTimePrivate(date, time, spec, offsetSeconds)) { - d->date = date; - d->time = date.isValid() && !time.isValid() ? QTime(0, 0, 0) : time; - d->spec = (spec == Qt::UTC) ? QDateTimePrivate::UTC : QDateTimePrivate::LocalUnknown; +} + +/*! + \internal + \since 5.2 + + Private. + + Create a datetime with the given \a date, \a time, \a spec and \a offsetSeconds +*/ + +QDateTimePrivate::QDateTimePrivate(const QDate &toDate, const QTime &toTime, Qt::TimeSpec toSpec, + int offsetSeconds) +{ + date = toDate; + + if (!toTime.isValid() && toDate.isValid()) + time = QTime(0, 0, 0); + else + time = toTime; + + m_offsetFromUtc = 0; + + switch (toSpec) { + case Qt::UTC : + spec = QDateTimePrivate::UTC; + break; + case Qt::OffsetFromUTC : + if (offsetSeconds == 0) { + spec = QDateTimePrivate::UTC; + } else { + spec = QDateTimePrivate::OffsetFromUTC; + m_offsetFromUtc = offsetSeconds; + } + break; + case Qt::LocalTime : + spec = QDateTimePrivate::LocalUnknown; + } } /*! @@ -2307,6 +2429,34 @@ Qt::TimeSpec QDateTime::timeSpec() const } /*! + \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::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 +{ + switch (d->spec) { + case QDateTimePrivate::OffsetFromUTC: + return d->m_offsetFromUtc; + case QDateTimePrivate::UTC: + return 0; + default: // Any Qt::LocalTime + const QDateTime fakeDate(d->date, d->time, Qt::UTC); + return (fakeDate.toMSecsSinceEpoch() - toMSecsSinceEpoch()) / 1000; + } +} + +/*! Sets the date part of this datetime to \a date. If no time is set, it is set to midnight. @@ -2343,6 +2493,9 @@ void QDateTime::setTime(const QTime &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. + Example: \snippet code/src_corelib_tools_qdatetime.cpp 19 @@ -2353,17 +2506,43 @@ void QDateTime::setTimeSpec(Qt::TimeSpec spec) { detach(); - switch(spec) - { - case Qt::UTC: - d->spec = QDateTimePrivate::UTC; - break; - case Qt::OffsetFromUTC: - d->spec = QDateTimePrivate::OffsetFromUTC; - break; - default: - d->spec = QDateTimePrivate::LocalUnknown; - break; + d->m_offsetFromUtc = 0; + switch (spec) { + case Qt::UTC: + case Qt::OffsetFromUTC: + d->spec = QDateTimePrivate::UTC; + break; + default: + d->spec = QDateTimePrivate::LocalUnknown; + break; + } +} + +/*! + \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) +{ + detach(); + + if (offsetSeconds == 0) { + d->spec = QDateTimePrivate::UTC; + d->m_offsetFromUtc = 0; + } else { + d->spec = QDateTimePrivate::OffsetFromUTC; + d->m_offsetFromUtc = offsetSeconds; } } @@ -2446,8 +2625,6 @@ void QDateTime::setMSecsSinceEpoch(qint64 msecs) { detach(); - QDateTimePrivate::Spec oldSpec = d->spec; - qint64 ddays = msecs / MSECS_PER_DAY; msecs %= MSECS_PER_DAY; if (msecs < 0) { @@ -2458,10 +2635,11 @@ void QDateTime::setMSecsSinceEpoch(qint64 msecs) d->date = QDate(1970, 1, 1).addDays(ddays); d->time = QTime(0, 0, 0).addMSecs(msecs); - d->spec = QDateTimePrivate::UTC; - if (oldSpec != QDateTimePrivate::UTC) - d->spec = d->getLocal(d->date, d->time); + if (d->spec == QDateTimePrivate::OffsetFromUTC) + utcToOffset(&d->date, &d->time, d->m_offsetFromUtc); + else if (d->spec != QDateTimePrivate::UTC) + utcToLocal(d->date, d->time); } /*! @@ -2479,14 +2657,13 @@ void QDateTime::setTime_t(uint secsSince1Jan1970UTC) { detach(); - QDateTimePrivate::Spec oldSpec = d->spec; - d->date = QDate(1970, 1, 1).addDays(secsSince1Jan1970UTC / SECS_PER_DAY); d->time = QTime(0, 0, 0).addSecs(secsSince1Jan1970UTC % SECS_PER_DAY); - d->spec = QDateTimePrivate::UTC; - if (oldSpec != QDateTimePrivate::UTC) - d->spec = d->getLocal(d->date, d->time); + if (d->spec == QDateTimePrivate::OffsetFromUTC) + utcToOffset(&d->date, &d->time, d->m_offsetFromUtc); + else if (d->spec != QDateTimePrivate::UTC) + utcToLocal(d->date, d->time); } #ifndef QT_NO_DATESTRING @@ -2554,11 +2731,7 @@ QString QDateTime::toString(Qt::DateFormat f) const buf += QLatin1Char('Z'); break; case QDateTimePrivate::OffsetFromUTC: { - int sign = d->utcOffset >= 0 ? 1: -1; - buf += QString::fromLatin1("%1%2:%3"). - arg(sign == 1 ? QLatin1Char('+') : QLatin1Char('-')). - arg(d->utcOffset * sign / SECS_PER_HOUR, 2, 10, QLatin1Char('0')). - arg((d->utcOffset / 60) % 60, 2, 10, QLatin1Char('0')); + buf += toOffsetString(Qt::ISODate, d->m_offsetFromUtc); break; } default: @@ -2567,7 +2740,7 @@ QString QDateTime::toString(Qt::DateFormat f) const } else if (f == Qt::RFC2822Date) { buf = toString(QStringLiteral("dd MMM yyyy hh:mm:ss ")); - int utcOffset = d->utcOffset; + int utcOffset = d->m_offsetFromUtc; if (timeSpec() == Qt::LocalTime) { QDateTime utc = toUTC(); utc.setTimeSpec(timeSpec()); @@ -2762,10 +2935,13 @@ QDateTime QDateTimePrivate::addMSecs(const QDateTime &dt, qint64 msecs) QDate utcDate; QTime utcTime; dt.d->getUTC(utcDate, utcTime); - addMSecs(utcDate, utcTime, msecs); + QDateTime utc(utcDate, utcTime, Qt::UTC); - return QDateTime(utcDate, utcTime, Qt::UTC).toTimeSpec(dt.timeSpec()); + if (dt.timeSpec() == Qt::OffsetFromUTC) + return utc.toOffsetFromUtc(dt.d->m_offsetFromUtc); + else + return utc.toTimeSpec(dt.timeSpec()); } /*! @@ -2916,12 +3092,14 @@ qint64 QDateTime::msecsTo(const QDateTime &other) const + static_cast<qint64>(selfTime.msecsTo(otherTime)); } - /*! - \fn QDateTime QDateTime::toTimeSpec(Qt::TimeSpec specification) const + \fn QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const Returns a copy of this datetime converted to the given time - \a specification. + \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(). Example: \snippet code/src_corelib_tools_qdatetime.cpp 16 @@ -2931,19 +3109,41 @@ qint64 QDateTime::msecsTo(const QDateTime &other) const QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const { - if ((d->spec == QDateTimePrivate::UTC) == (spec == Qt::UTC)) - return *this; + if (spec == Qt::UTC || spec == Qt::OffsetFromUTC) { + QDate date; + QTime time; + d->getUTC(date, time); + return QDateTime(date, time, Qt::UTC, 0); + } QDateTime ret; - if (spec == Qt::UTC) { - d->getUTC(ret.d->date, ret.d->time); - ret.d->spec = QDateTimePrivate::UTC; - } else { - ret.d->spec = d->getLocal(ret.d->date, ret.d->time); - } + ret.d->spec = d->getLocal(ret.d->date, ret.d->time); return ret; } + +/*! + \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 +{ + QDate date; + QTime time; + d->getUTC(date, time); + d->addMSecs(date, time, offsetSeconds * 1000); + return QDateTime(date, time, Qt::OffsetFromUTC, offsetSeconds); +} + /*! Returns true if this datetime is equal to the \a other datetime; otherwise returns false. @@ -2953,7 +3153,7 @@ QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const bool QDateTime::operator==(const QDateTime &other) const { - if (d->spec == other.d->spec && d->utcOffset == other.d->utcOffset) + if (d->spec == other.d->spec && d->m_offsetFromUtc == other.d->m_offsetFromUtc) return d->time == other.d->time && d->date == other.d->date; else { QDate date1, date2; @@ -3263,62 +3463,41 @@ QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs) return d; } +#if QT_DEPRECATED_SINCE(5, 2) /*! - \since 4.4 - \internal - - Sets the offset from UTC to \a seconds, and also sets timeSpec() to - Qt::OffsetFromUTC. + \since 4.4 + \internal + \obsolete - The maximum and minimum offset is 14 positive or negative hours. If - \a seconds is larger or smaller than that, the result is undefined. + 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. - 0 as offset is identical to UTC. Therefore, if \a seconds is 0, the - timeSpec() will be set to Qt::UTC. Hence the UTC offset always - relates to UTC, and can never relate to local time. + This method should never be made public. - \sa isValid(), utcOffset() + \sa setOffsetFromUtc() */ void QDateTime::setUtcOffset(int seconds) { - detach(); - - /* The motivation to also setting d->spec is to ensure that the QDateTime - * instance stays in well-defined states all the time; instead of that, - * we instruct the user to ensure it. */ - if(seconds == 0) - d->spec = QDateTimePrivate::UTC; - else - d->spec = QDateTimePrivate::OffsetFromUTC; - - /* Even if seconds is 0 we assign it to utcOffset. */ - d->utcOffset = seconds; + setOffsetFromUtc(seconds); } /*! - \since 4.4 - \internal - - Returns the UTC offset in seconds. If the timeSpec() isn't - Qt::OffsetFromUTC, 0 is returned. However, since 0 is a valid UTC - offset, the return value of this function cannot be used to determine - whether a utcOffset() is used or is valid; in that case, timeSpec() must be - checked. + \since 4.4 + \internal + \obsolete - Likewise, if this QDateTime() is invalid or if timeSpec() isn't - Qt::OffsetFromUTC, 0 is returned. + 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. - The UTC offset only applies if the timeSpec() is Qt::OffsetFromUTC. + This method should never be made public. - \sa isValid(), setUtcOffset() - */ + \sa offsetFromUTC() +*/ int QDateTime::utcOffset() const { - if(isValid() && d->spec == QDateTimePrivate::OffsetFromUTC) - return d->utcOffset; - else - return 0; + return offsetFromUtc(); } +#endif // QT_DEPRECATED_SINCE #ifndef QT_NO_DATESTRING @@ -3370,26 +3549,15 @@ QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f) } // Recognize timezone specifications - QRegExp rx(QLatin1String("[+-]")); - if (tmp.contains(rx)) { - int idx = tmp.indexOf(rx); - QString tmp2 = tmp.mid(idx); - tmp = tmp.left(idx); - bool ok = true; - int ntzhour = 1; - int ntzminute = 3; - if ( tmp2.indexOf(QLatin1Char(':')) == 3 ) - ntzminute = 4; - const int tzhour(tmp2.mid(ntzhour, 2).toInt(&ok)); - const int tzminute(tmp2.mid(ntzminute, 2).toInt(&ok)); - QTime tzt(tzhour, tzminute); - int utcOffset = (tzt.hour() * 60 + tzt.minute()) * 60; - if ( utcOffset != 0 ) { - ts = Qt::OffsetFromUTC; - QDateTime dt(date, QTime::fromString(tmp, Qt::ISODate), ts); - dt.setUtcOffset( utcOffset * (tmp2.startsWith(QLatin1Char('-')) ? -1 : 1) ); - return dt; - } + int offset = 0; + const int signIndex = tmp.indexOf(QRegExp(QStringLiteral("[+-]"))); + if (signIndex >= 0) { + bool ok; + offset = fromOffsetString(tmp.mid(signIndex), &ok); + if (!ok) + return QDateTime(); + tmp = tmp.left(signIndex); + ts = Qt::OffsetFromUTC; } bool isMidnight24 = false; @@ -3400,7 +3568,7 @@ QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f) date = date.addDays(1); } - return QDateTime(date, time, ts); + return QDateTime(date, time, ts, offset); } case Qt::RFC2822Date: { QDate date; @@ -3412,7 +3580,7 @@ QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f) return QDateTime(); QDateTime dateTime(date, time, Qt::UTC); - dateTime.setUtcOffset(utcOffset); + dateTime.setOffsetFromUtc(utcOffset); return dateTime; } case Qt::SystemLocaleDate: @@ -3521,26 +3689,15 @@ QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f) QString tz = parts.at(5); if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive)) return QDateTime(); - QDateTime dt(date, time, Qt::UTC); - if (tz.length() > 3) { - int tzoffset = 0; - QChar sign = tz.at(3); - if ((sign != QLatin1Char('+')) - && (sign != QLatin1Char('-'))) { - return QDateTime(); - } - int tzhour = tz.mid(4, 2).toInt(&ok); - if (!ok) - return QDateTime(); - int tzminute = tz.mid(6).toInt(&ok); + tz.remove(0, 3); + if (!tz.isEmpty()) { + int offset = fromOffsetString(tz, &ok); if (!ok) return QDateTime(); - tzoffset = (tzhour*60 + tzminute) * 60; - if (sign == QLatin1Char('-')) - tzoffset = -tzoffset; - dt.setUtcOffset(tzoffset); + return QDateTime(date, time, Qt::OffsetFromUTC, offset); + } else { + return QDateTime(date, time, Qt::UTC); } - return dt.toLocalTime(); } #endif //QT_NO_TEXTDATE } @@ -3790,7 +3947,7 @@ QDataStream &operator>>(QDataStream &in, QTime &time) */ QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime) { - if (out.version() == 13) { + if (out.version() == QDataStream::Qt_5_0) { if (dateTime.isValid()) { // This approach is wrong and should not be used again; it breaks // the guarantee that a deserialised local datetime is the same time @@ -3803,8 +3960,12 @@ QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime) out << (qint8)dateTime.timeSpec(); } else { out << dateTime.d->date << dateTime.d->time; - if (out.version() >= 7) + if (out.version() >= QDataStream::Qt_4_0) out << (qint8)dateTime.d->spec; + if (out.version() >= QDataStream::Qt_5_2 + && dateTime.d->spec == QDateTimePrivate::OffsetFromUTC) { + out << qint32(dateTime.offsetFromUtc()); + } } return out; } @@ -3823,19 +3984,23 @@ QDataStream &operator>>(QDataStream &in, QDateTime &dateTime) in >> dateTime.d->date >> dateTime.d->time; - if (in.version() == 13) { + if (in.version() == QDataStream::Qt_5_0) { qint8 ts = 0; in >> ts; if (dateTime.isValid()) { - // We always store the datetime as UTC in 13 onwards. + // We incorrectly stored the datetime as UTC in Qt_5_0. dateTime.d->spec = QDateTimePrivate::UTC; dateTime = dateTime.toTimeSpec(static_cast<Qt::TimeSpec>(ts)); } } else { qint8 ts = (qint8)QDateTimePrivate::LocalUnknown; - if (in.version() >= 7) + if (in.version() >= QDataStream::Qt_4_0) in >> ts; + qint32 offset = 0; + if (in.version() >= QDataStream::Qt_5_2 && ts == qint8(QDateTimePrivate::OffsetFromUTC)) + in >> offset; dateTime.d->spec = (QDateTimePrivate::Spec)ts; + dateTime.d->m_offsetFromUtc = offset; } return in; } @@ -4129,6 +4294,7 @@ static QDate adjustDate(QDate date) return date; } +// Convert passed in UTC datetime into LocalTime and return spec static QDateTimePrivate::Spec utcToLocal(QDate &date, QTime &time) { QDate fakeDate = adjustDate(date); @@ -4182,6 +4348,7 @@ static QDateTimePrivate::Spec utcToLocal(QDate &date, QTime &time) } } +// Convert passed in LocalTime datetime into UTC static void localToUtc(QDate &date, QTime &time, int isdst) { if (!date.isValid()) @@ -4254,26 +4421,42 @@ static void localToUtc(QDate &date, QTime &time, int isdst) } } +// Convert passed in OffsetFromUTC datetime and offset into UTC +static void offsetToUtc(QDate *outDate, QTime *outTime, qint32 offset) +{ + QDateTimePrivate::addMSecs(*outDate, *outTime, -(qint64(offset) * 1000)); +} + +// Convert passed in UTC datetime and offset into OffsetFromUTC +static void utcToOffset(QDate *outDate, QTime *outTime, qint32 offset) +{ + QDateTimePrivate::addMSecs(*outDate, *outTime, (qint64(offset) * 1000)); +} + +// Get current date/time in LocalTime and put result in outDate and outTime QDateTimePrivate::Spec QDateTimePrivate::getLocal(QDate &outDate, QTime &outTime) const { outDate = date; outTime = time; if (spec == QDateTimePrivate::UTC) return utcToLocal(outDate, outTime); + if (spec == QDateTimePrivate::OffsetFromUTC) { + offsetToUtc(&outDate, &outTime, m_offsetFromUtc); + return utcToLocal(outDate, outTime); + } return spec; } +// Get current date/time in UTC and put result in outDate and outTime void QDateTimePrivate::getUTC(QDate &outDate, QTime &outTime) const { outDate = date; outTime = time; - const bool isOffset = spec == QDateTimePrivate::OffsetFromUTC; - if (spec != QDateTimePrivate::UTC && !isOffset) + if (spec == QDateTimePrivate::OffsetFromUTC) + offsetToUtc(&outDate, &outTime, m_offsetFromUtc); + else if (spec != QDateTimePrivate::UTC) localToUtc(outDate, outTime, (int)spec); - - if (isOffset) - addMSecs(outDate, outTime, -(qint64(utcOffset) * 1000)); } #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING) diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h index e5c1e104a2..83c92858ee 100644 --- a/src/corelib/tools/qdatetime.h +++ b/src/corelib/tools/qdatetime.h @@ -203,6 +203,8 @@ public: QDateTime(); explicit QDateTime(const QDate &); QDateTime(const QDate &, const QTime &, Qt::TimeSpec spec = Qt::LocalTime); + // ### Qt 6: Merge with above with default offsetSeconds = 0 + QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec, int offsetSeconds); QDateTime(const QDateTime &other); ~QDateTime(); @@ -216,15 +218,20 @@ public: QDate date() const; QTime time() const; Qt::TimeSpec timeSpec() const; + int offsetFromUtc() const; + qint64 toMSecsSinceEpoch() const; // ### Qt 6: use quint64 instead of uint uint toTime_t() const; + void setDate(const QDate &date); void setTime(const QTime &time); void setTimeSpec(Qt::TimeSpec spec); + void setOffsetFromUtc(int offsetSeconds); void setMSecsSinceEpoch(qint64 msecs); // ### Qt 6: use quint64 instead of uint void setTime_t(uint secsSince1Jan1970UTC); + #ifndef QT_NO_DATESTRING QString toString(Qt::DateFormat f = Qt::TextDate) const; QString toString(const QString &format) const; @@ -234,9 +241,12 @@ public: QDateTime addYears(int years) const; QDateTime addSecs(qint64 secs) const; QDateTime addMSecs(qint64 msecs) const; + QDateTime toTimeSpec(Qt::TimeSpec spec) const; inline QDateTime toLocalTime() const { return toTimeSpec(Qt::LocalTime); } inline QDateTime toUTC() const { return toTimeSpec(Qt::UTC); } + QDateTime toOffsetFromUtc(int offsetSeconds) const; + qint64 daysTo(const QDateTime &) const; qint64 secsTo(const QDateTime &) const; qint64 msecsTo(const QDateTime &) const; @@ -248,8 +258,10 @@ public: inline bool operator>(const QDateTime &other) const { return other < *this; } inline bool operator>=(const QDateTime &other) const { return !(*this < other); } - void setUtcOffset(int seconds); - int utcOffset() const; +#if QT_DEPRECATED_SINCE(5, 2) + QT_DEPRECATED void setUtcOffset(int seconds); + QT_DEPRECATED int utcOffset() const; +#endif // QT_DEPRECATED_SINCE static QDateTime currentDateTime(); static QDateTime currentDateTimeUtc(); diff --git a/src/corelib/tools/qdatetime_p.h b/src/corelib/tools/qdatetime_p.h index c70571d509..f3abcf02d8 100644 --- a/src/corelib/tools/qdatetime_p.h +++ b/src/corelib/tools/qdatetime_p.h @@ -81,25 +81,27 @@ class QDateTimePrivate : public QSharedData public: enum Spec { LocalUnknown = -1, LocalStandard = 0, LocalDST = 1, UTC = 2, OffsetFromUTC = 3}; - QDateTimePrivate() : spec(LocalUnknown), utcOffset(0) {} + QDateTimePrivate() : spec(LocalUnknown), m_offsetFromUtc(0) {} + QDateTimePrivate(const QDate &toDate, const QTime &toTime, Qt::TimeSpec toSpec, + int offsetSeconds); QDateTimePrivate(const QDateTimePrivate &other) - : QSharedData(other), date(other.date), time(other.time), spec(other.spec), utcOffset(other.utcOffset) + : QSharedData(other), date(other.date), time(other.time), spec(other.spec), + m_offsetFromUtc(other.m_offsetFromUtc) {} QDate date; QTime time; Spec spec; - /*! - \internal - \since 4.4 - - The offset in seconds. Applies only when timeSpec() is OffsetFromUTC. - */ - int utcOffset; + int m_offsetFromUtc; + // Get current date/time in LocalTime and put result in outDate and outTime Spec getLocal(QDate &outDate, QTime &outTime) const; + // Get current date/time in UTC and put result in outDate and outTime void getUTC(QDate &outDate, QTime &outTime) const; + + // Add msecs to given datetime and return result static QDateTime addMSecs(const QDateTime &dt, qint64 msecs); + // Add msecs to given datetime and put result in utcDate and utcTime static void addMSecs(QDate &utcDate, QTime &utcTime, qint64 msecs); static inline qint64 minJd() { return QDate::minJd(); } |