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.cpp1051
1 files changed, 644 insertions, 407 deletions
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index bfc7e1ca0e..f8611b3e68 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -57,9 +57,6 @@
#include <time.h>
#ifdef Q_OS_WIN
# include <qt_windows.h>
-# ifdef Q_OS_WINCE
-# include "qfunctions_wince.h"
-# endif
# ifdef Q_OS_WINRT
# include "qfunctions_winrt.h"
# endif
@@ -71,8 +68,6 @@
QT_BEGIN_NAMESPACE
-Q_GLOBAL_STATIC_WITH_ARGS(QSharedDataPointer<QDateTimePrivate>, defaultDateTimePrivate, (new QDateTimePrivate()))
-
/*****************************************************************************
Date/Time Constants
*****************************************************************************/
@@ -1687,9 +1682,6 @@ QString QTime::toString(const QString& format) const
bool QTime::setHMS(int h, int m, int s, int ms)
{
-#if defined(Q_OS_WINCE)
- startTick = NullTime;
-#endif
if (!isValid(h,m,s,ms)) {
mds = NullTime; // make this invalid
return false;
@@ -1769,10 +1761,6 @@ QTime QTime::addMSecs(int ms) const
t.mds = (ds() + ms) % MSECS_PER_DAY;
}
}
-#if defined(Q_OS_WINCE)
- if (startTick > NullTime)
- t.startTick = (startTick + ms) % MSECS_PER_DAY;
-#endif
return t;
}
@@ -1794,13 +1782,7 @@ int QTime::msecsTo(const QTime &t) const
{
if (!isValid() || !t.isValid())
return 0;
-#if defined(Q_OS_WINCE)
- // GetLocalTime() for Windows CE has no milliseconds resolution
- if (t.startTick > NullTime && startTick > NullTime)
- return t.startTick - startTick;
- else
-#endif
- return t.ds() - ds();
+ return t.ds() - ds();
}
@@ -2141,13 +2123,14 @@ int QTime::elapsed() const
QDateTime static helper functions
*****************************************************************************/
+// get the types from QDateTime (through QDateTimePrivate)
+typedef QDateTimePrivate::QDateTimeShortData ShortData;
+typedef QDateTimePrivate::QDateTimeData QDateTimeData;
+
// Calls the platform variant of tzset
static void qt_tzset()
{
-#if defined(Q_OS_WINCE)
- // WinCE doesn't use tzset
- return;
-#elif defined(Q_OS_WIN)
+#if defined(Q_OS_WIN)
_tzset();
#else
tzset();
@@ -2161,12 +2144,7 @@ static void qt_tzset()
// Relies on tzset, mktime, or localtime having been called to populate timezone
static int qt_timezone()
{
-#if defined(Q_OS_WINCE)
- TIME_ZONE_INFORMATION tzi;
- GetTimeZoneInformation(&tzi);
- // Expressed in minutes, convert to seconds
- return (tzi.Bias + tzi.StandardBias) * 60;
-#elif defined(_MSC_VER) && _MSC_VER >= 1400
+#if defined(_MSC_VER)
long offset;
_get_timezone(&offset);
return offset;
@@ -2195,16 +2173,6 @@ static int qt_timezone()
// Returns the tzname, assume tzset has been called already
static QString qt_tzname(QDateTimePrivate::DaylightStatus daylightStatus)
{
-#if defined(Q_OS_WINCE)
- TIME_ZONE_INFORMATION tzi;
- DWORD res = GetTimeZoneInformation(&tzi);
- if (res == TIME_ZONE_ID_UNKNOWN)
- return QString();
- else if (daylightStatus == QDateTimePrivate::DaylightTime)
- return QString::fromWCharArray(tzi.DaylightName);
- else
- return QString::fromWCharArray(tzi.StandardName);
-#else
int isDst = (daylightStatus == QDateTimePrivate::DaylightTime) ? 1 : 0;
#if defined(_MSC_VER) && _MSC_VER >= 1400
size_t s = 0;
@@ -2215,7 +2183,6 @@ static QString qt_tzname(QDateTimePrivate::DaylightStatus daylightStatus)
#else
return QString::fromLocal8Bit(tzname[isDst]);
#endif // Q_OS_WIN
-#endif // Q_OS_WINCE
}
// Calls the platform variant of mktime for the given date, time and daylightStatus,
@@ -2230,48 +2197,6 @@ static qint64 qt_mktime(QDate *date, QTime *time, QDateTimePrivate::DaylightStat
int yy, mm, dd;
date->getDate(&yy, &mm, &dd);
-#if defined(Q_OS_WINCE)
- // WinCE doesn't provide standard C library time functions
- SYSTEMTIME st;
- memset(&st, 0, sizeof(SYSTEMTIME));
- st.wSecond = time->second();
- st.wMinute = time->minute();
- st.wHour = time->hour();
- st.wDay = dd;
- st.wMonth = mm;
- st.wYear = yy;
- FILETIME lft;
- bool valid = SystemTimeToFileTime(&st, &lft);
- FILETIME ft;
- if (valid)
- valid = LocalFileTimeToFileTime(&lft, &ft);
- const time_t secsSinceEpoch = ftToTime_t(ft);
- const time_t localSecs = ftToTime_t(lft);
- TIME_ZONE_INFORMATION tzi;
- GetTimeZoneInformation(&tzi);
- bool isDaylight = false;
- // Check for overflow
- qint64 localDiff = qAbs(localSecs - secsSinceEpoch);
- int daylightOffset = qAbs(tzi.Bias + tzi.DaylightBias) * 60;
- if (localDiff > daylightOffset)
- valid = false;
- else
- isDaylight = (localDiff == daylightOffset);
- if (daylightStatus) {
- if (isDaylight)
- *daylightStatus = QDateTimePrivate::DaylightTime;
- else
- *daylightStatus = QDateTimePrivate::StandardTime;
- }
- if (abbreviation) {
- if (isDaylight)
- *abbreviation = QString::fromWCharArray(tzi.DaylightName);
- else
- *abbreviation = QString::fromWCharArray(tzi.StandardName);
- }
- if (ok)
- *ok = valid;
-#else
// All other platforms provide standard C library time functions
tm local;
memset(&local, 0, sizeof(local)); // tm_[wy]day plus any non-standard fields
@@ -2333,7 +2258,6 @@ static qint64 qt_mktime(QDate *date, QTime *time, QDateTimePrivate::DaylightStat
if (ok)
*ok = false;
}
-#endif // Q_OS_WINCE
return ((qint64)secsSinceEpoch * 1000) + msec;
}
@@ -2349,23 +2273,7 @@ static bool qt_localtime(qint64 msecsSinceEpoch, QDate *localDate, QTime *localT
tm local;
bool valid = false;
-#if defined(Q_OS_WINCE)
- FILETIME utcTime = time_tToFt(secsSinceEpoch);
- FILETIME resultTime;
- valid = FileTimeToLocalFileTime(&utcTime , &resultTime);
- SYSTEMTIME sysTime;
- if (valid)
- valid = FileTimeToSystemTime(&resultTime , &sysTime);
-
- if (valid) {
- local.tm_sec = sysTime.wSecond;
- local.tm_min = sysTime.wMinute;
- local.tm_hour = sysTime.wHour;
- local.tm_mday = sysTime.wDay;
- local.tm_mon = sysTime.wMonth - 1;
- local.tm_year = sysTime.wYear - 1900;
- }
-#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
// localtime() is required to work as if tzset() was called before it.
// localtime_r() does not have this requirement, so make an explicit call.
qt_tzset();
@@ -2578,240 +2486,423 @@ static qint64 localMSecsToEpochMSecs(qint64 localMsecs,
}
}
-/*****************************************************************************
- QDateTimePrivate member functions
- *****************************************************************************/
+static inline bool specCanBeSmall(Qt::TimeSpec spec)
+{
+ return spec == Qt::LocalTime || spec == Qt::UTC;
+}
-QDateTimePrivate::QDateTimePrivate(const QDate &toDate, const QTime &toTime, Qt::TimeSpec toSpec,
- int offsetSeconds)
- : m_msecs(0),
- m_spec(Qt::LocalTime),
- m_offsetFromUtc(0),
- m_status(0)
+static inline bool msecsCanBeSmall(qint64 msecs)
{
- setTimeSpec(toSpec, offsetSeconds);
- setDateTime(toDate, toTime);
+ if (!QDateTimeData::CanBeSmall)
+ return false;
+
+ ShortData sd;
+ sd.msecs = qintptr(msecs);
+ return sd.msecs == msecs;
}
-#ifndef QT_BOOTSTRAPPED
-QDateTimePrivate::QDateTimePrivate(const QDate &toDate, const QTime &toTime,
- const QTimeZone &toTimeZone)
- : m_spec(Qt::TimeZone),
- m_offsetFromUtc(0),
- m_timeZone(toTimeZone),
- m_status(0)
+static Q_DECL_CONSTEXPR inline
+QDateTimePrivate::StatusFlags mergeSpec(QDateTimePrivate::StatusFlags status, Qt::TimeSpec spec)
{
- setDateTime(toDate, toTime);
+ 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;
}
-#endif // QT_BOOTSTRAPPED
-void QDateTimePrivate::setTimeSpec(Qt::TimeSpec spec, int offsetSeconds)
+static inline qint64 getMSecs(const QDateTimeData &d)
{
- clearValidDateTime();
- clearSetToDaylightStatus();
+ 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));
+}
+
+// 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);
#ifndef QT_BOOTSTRAPPED
- m_timeZone = QTimeZone();
+ // 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, &testDate, &testTime);
+ }
#endif // QT_BOOTSTRAPPED
- switch (spec) {
- case Qt::OffsetFromUTC:
- if (offsetSeconds == 0) {
- m_spec = Qt::UTC;
- m_offsetFromUtc = 0;
+ // 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 {
- m_spec = Qt::OffsetFromUTC;
- m_offsetFromUtc = offsetSeconds;
+ 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:
- // Use system time zone instead
- m_spec = Qt::LocalTime;
- m_offsetFromUtc = 0;
+ 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:
- m_spec = spec;
- m_offsetFromUtc = 0;
+ 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;
+#ifndef QT_BOOTSTRAPPED
+ d->m_timeZone = QTimeZone();
+#endif // QT_BOOTSTRAPPED
+ }
}
-void QDateTimePrivate::setDateTime(const QDate &date, const QTime &time)
+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);
- StatusFlags newStatus;
+ QDateTimePrivate::StatusFlags newStatus = 0;
// Set date value and status
qint64 days = 0;
if (date.isValid()) {
days = date.toJulianDay() - JULIAN_DAY_FOR_EPOCH;
- newStatus = ValidDate;
- } else if (date.isNull()) {
- newStatus = NullDate;
+ newStatus = QDateTimePrivate::ValidDate;
}
// Set time value and status
int ds = 0;
if (useTime.isValid()) {
ds = useTime.msecsSinceStartOfDay();
- newStatus |= ValidTime;
- } else if (time.isNull()) {
- newStatus |= NullTime;
+ newStatus |= QDateTimePrivate::ValidTime;
}
// Set msecs serial value
- m_msecs = (days * MSECS_PER_DAY) + ds;
- m_status = newStatus;
+ 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();
+ checkValidDateTime(d);
}
-QPair<QDate, QTime> QDateTimePrivate::getDateTime() const
+static QPair<QDate, QTime> getDateTime(const QDateTimeData &d)
{
QPair<QDate, QTime> result;
- msecsToTime(m_msecs, &result.first, &result.second);
+ qint64 msecs = getMSecs(d);
+ auto status = getStatus(d);
+ msecsToTime(msecs, &result.first, &result.second);
- if (isNullDate())
+ if (!status.testFlag(QDateTimePrivate::ValidDate))
result.first = QDate();
- if (isNullTime())
+ if (!status.testFlag(QDateTimePrivate::ValidTime))
result.second = QTime();
return result;
}
-// Set the Daylight Status if LocalTime set via msecs
-void QDateTimePrivate::setDaylightStatus(QDateTimePrivate::DaylightStatus status)
-{
- if (status == DaylightTime) {
- m_status = m_status & ~SetToStandardTime;
- m_status = m_status | SetToDaylightTime;
- } else if (status == StandardTime) {
- m_status = m_status & ~SetToDaylightTime;
- m_status = m_status | SetToStandardTime;
+/*****************************************************************************
+ 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 {
- clearSetToDaylightStatus();
+ // the structure is too small, we need to detach
+ d = new QDateTimePrivate;
+ d->ref.ref();
+ d->m_status = mergeSpec(0, spec);
}
}
-// Get the DST Status if LocalTime set via msecs
-QDateTimePrivate::DaylightStatus QDateTimePrivate::daylightStatus() const
+inline QDateTime::Data::Data(const Data &other)
+ : d(other.d)
{
- if ((m_status & SetToDaylightTime) == SetToDaylightTime)
- return DaylightTime;
- if ((m_status & SetToStandardTime) == SetToStandardTime)
- return StandardTime;
- return UnknownDaylightTime;
+ 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();
+ }
+ }
}
-qint64 QDateTimePrivate::toMSecsSinceEpoch() const
+inline QDateTime::Data::Data(Data &&other)
+ : d(other.d)
{
- switch (m_spec) {
- case Qt::OffsetFromUTC:
- case Qt::UTC:
- return (m_msecs - (m_offsetFromUtc * 1000));
+ // reset the other to a short state
+ Data dummy;
+ Q_ASSERT(dummy.isShort());
+ other.d = dummy.d;
+}
- case Qt::LocalTime: {
- // recalculate the local timezone
- DaylightStatus status = daylightStatus();
- return localMSecsToEpochMSecs(m_msecs, &status);
- }
+inline QDateTime::Data &QDateTime::Data::operator=(const Data &other)
+{
+ if (d == other.d)
+ return *this;
- case Qt::TimeZone:
-#ifdef QT_BOOTSTRAPPED
- return 0;
-#else
- return zoneMSecsToEpochMSecs(m_msecs, m_timeZone);
-#endif
+ 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();
+ }
}
- Q_UNREACHABLE();
- return 0;
+
+ if (!(quintptr(x) & QDateTimePrivate::ShortData) && !x->ref.deref())
+ delete x;
+ return *this;
}
-// Check the UTC / offsetFromUTC validity
-void QDateTimePrivate::checkValidDateTime()
+inline QDateTime::Data::~Data()
{
- switch (m_spec) {
- case Qt::OffsetFromUTC:
- case Qt::UTC:
- // for these, a valid date and a valid time imply a valid QDateTime
- if (isValidDate() && isValidTime())
- setValidDateTime();
- else
- clearValidDateTime();
- 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();
- break;
- }
+ if (!isShort() && !d->ref.deref())
+ delete d;
}
-// Refresh the LocalTime validity and offset
-void QDateTimePrivate::refreshDateTime()
+inline bool QDateTime::Data::isShort() const
{
- switch (m_spec) {
- case Qt::OffsetFromUTC:
- case Qt::UTC:
- // Always set by setDateTime so just return
- return;
- case Qt::TimeZone:
- case Qt::LocalTime:
- break;
- }
-
- // If not valid date and time then is invalid
- if (!isValidDate() || !isValidTime()) {
- clearValidDateTime();
- m_offsetFromUtc = 0;
- return;
- }
+ bool b = quintptr(d) & QDateTimePrivate::ShortData;
-#ifndef QT_BOOTSTRAPPED
- // If not valid time zone then is invalid
- if (m_spec == Qt::TimeZone && !m_timeZone.isValid()) {
- clearValidDateTime();
- m_offsetFromUtc = 0;
- return;
- }
-#endif // QT_BOOTSTRAPPED
+ // 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);
+}
- // 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
- QDate testDate;
- QTime testTime;
- qint64 epochMSecs = 0;
- if (m_spec == Qt::LocalTime) {
- DaylightStatus status = daylightStatus();
- epochMSecs = localMSecsToEpochMSecs(m_msecs, &status, &testDate, &testTime);
-#ifndef QT_BOOTSTRAPPED
- } else {
- epochMSecs = zoneMSecsToEpochMSecs(m_msecs, m_timeZone, &testDate, &testTime);
-#endif // QT_BOOTSTRAPPED
- }
- if (timeToMSecs(testDate, testTime) == m_msecs) {
- setValidDateTime();
- // Cache the offset to use in toMSecsSinceEpoch()
- m_offsetFromUtc = (m_msecs - epochMSecs) / 1000;
+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 {
- clearValidDateTime();
- m_offsetFromUtc = 0;
+ 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;
}
#ifndef QT_BOOTSTRAPPED
+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
-qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QTimeZone &zone,
- QDate *localDate, QTime *localTime)
+inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QTimeZone &zone,
+ QDate *localDate, QTime *localTime)
{
// Get the effective data from QTimeZone
QTimeZonePrivate::Data data = zone.d->dataForLocalTime(zoneMSecs);
@@ -2961,8 +3052,7 @@ qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QTimeZone
\sa isValid()
*/
-QDateTime::QDateTime()
- : d(*defaultDateTimePrivate())
+QDateTime::QDateTime() Q_DECL_NOEXCEPT_EXPR(Data::CanBeSmall)
{
}
@@ -2973,7 +3063,7 @@ QDateTime::QDateTime()
*/
QDateTime::QDateTime(const QDate &date)
- : d(new QDateTimePrivate(date, QTime(0, 0, 0), Qt::LocalTime, 0))
+ : d(QDateTimePrivate::create(date, QTime(0, 0, 0), Qt::LocalTime, 0))
{
}
@@ -2993,7 +3083,7 @@ QDateTime::QDateTime(const QDate &date)
*/
QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec)
- : d(new QDateTimePrivate(date, time, spec, 0))
+ : d(QDateTimePrivate::create(date, time, spec, 0))
{
}
@@ -3016,7 +3106,7 @@ QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec)
*/
QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec, int offsetSeconds)
- : d(new QDateTimePrivate(date, time, spec, offsetSeconds))
+ : d(QDateTimePrivate::create(date, time, spec, offsetSeconds))
{
}
@@ -3033,7 +3123,7 @@ QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec, in
*/
QDateTime::QDateTime(const QDate &date, const QTime &time, const QTimeZone &timeZone)
- : d(new QDateTimePrivate(date, time, timeZone))
+ : d(QDateTimePrivate::create(date, time, timeZone))
{
}
#endif // QT_BOOTSTRAPPED
@@ -3041,13 +3131,22 @@ QDateTime::QDateTime(const QDate &date, const QTime &time, const QTimeZone &time
/*!
Constructs a copy of the \a other datetime.
*/
-
-QDateTime::QDateTime(const QDateTime &other)
+QDateTime::QDateTime(const QDateTime &other) Q_DECL_NOTHROW
: 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) Q_DECL_NOTHROW
+ : d(std::move(other.d))
+{
+}
+
+/*!
Destroys the datetime.
*/
QDateTime::~QDateTime()
@@ -3059,7 +3158,7 @@ QDateTime::~QDateTime()
copy.
*/
-QDateTime &QDateTime::operator=(const QDateTime &other)
+QDateTime &QDateTime::operator=(const QDateTime &other) Q_DECL_NOTHROW
{
d = other.d;
return *this;
@@ -3081,7 +3180,9 @@ QDateTime &QDateTime::operator=(const QDateTime &other)
bool QDateTime::isNull() const
{
- return d->isNullDate() && d->isNullTime();
+ auto status = getStatus(d);
+ return !status.testFlag(QDateTimePrivate::ValidDate) &&
+ !status.testFlag(QDateTimePrivate::ValidTime);
}
/*!
@@ -3098,7 +3199,8 @@ bool QDateTime::isNull() const
bool QDateTime::isValid() const
{
- return (d->isValidDateTime());
+ auto status = getStatus(d);
+ return status & QDateTimePrivate::ValidDateTime;
}
/*!
@@ -3109,10 +3211,11 @@ bool QDateTime::isValid() const
QDate QDateTime::date() const
{
- if (d->isNullDate())
+ auto status = getStatus(d);
+ if (!status.testFlag(QDateTimePrivate::ValidDate))
return QDate();
QDate dt;
- msecsToTime(d->m_msecs, &dt, 0);
+ msecsToTime(getMSecs(d), &dt, 0);
return dt;
}
@@ -3124,10 +3227,11 @@ QDate QDateTime::date() const
QTime QDateTime::time() const
{
- if (d->isNullTime())
+ auto status = getStatus(d);
+ if (!status.testFlag(QDateTimePrivate::ValidTime))
return QTime();
QTime tm;
- msecsToTime(d->m_msecs, 0, &tm);
+ msecsToTime(getMSecs(d), 0, &tm);
return tm;
}
@@ -3139,7 +3243,7 @@ QTime QDateTime::time() const
Qt::TimeSpec QDateTime::timeSpec() const
{
- return d->m_spec;
+ return getSpec(d);
}
#ifndef QT_BOOTSTRAPPED
@@ -3157,7 +3261,7 @@ Qt::TimeSpec QDateTime::timeSpec() const
QTimeZone QDateTime::timeZone() const
{
- switch (d->m_spec) {
+ switch (getSpec(d)) {
case Qt::UTC:
return QTimeZone::utc();
case Qt::OffsetFromUTC:
@@ -3192,7 +3296,20 @@ QTimeZone QDateTime::timeZone() const
int QDateTime::offsetFromUtc() const
{
- return d->m_offsetFromUtc;
+ 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;
}
/*!
@@ -3218,7 +3335,7 @@ int QDateTime::offsetFromUtc() const
QString QDateTime::timeZoneAbbreviation() const
{
- switch (d->m_spec) {
+ switch (getSpec(d)) {
case Qt::UTC:
return QTimeZonePrivate::utcQString();
case Qt::OffsetFromUTC:
@@ -3227,12 +3344,12 @@ QString QDateTime::timeZoneAbbreviation() const
#ifdef QT_BOOTSTRAPPED
break;
#else
- return d->m_timeZone.d->abbreviation(d->toMSecsSinceEpoch());
+ return d->m_timeZone.d->abbreviation(toMSecsSinceEpoch());
#endif // QT_BOOTSTRAPPED
case Qt::LocalTime: {
QString abbrev;
- QDateTimePrivate::DaylightStatus status = d->daylightStatus();
- localMSecsToEpochMSecs(d->m_msecs, &status, 0, 0, &abbrev);
+ auto status = extractDaylightStatus(getStatus(d));
+ localMSecsToEpochMSecs(getMSecs(d), &status, 0, 0, &abbrev);
return abbrev;
}
}
@@ -3252,7 +3369,7 @@ QString QDateTime::timeZoneAbbreviation() const
bool QDateTime::isDaylightTime() const
{
- switch (d->m_spec) {
+ switch (getSpec(d)) {
case Qt::UTC:
case Qt::OffsetFromUTC:
return false;
@@ -3263,9 +3380,9 @@ bool QDateTime::isDaylightTime() const
return d->m_timeZone.d->isDaylightTime(toMSecsSinceEpoch());
#endif // QT_BOOTSTRAPPED
case Qt::LocalTime: {
- QDateTimePrivate::DaylightStatus status = d->daylightStatus();
+ auto status = extractDaylightStatus(getStatus(d));
if (status == QDateTimePrivate::UnknownDaylightTime)
- localMSecsToEpochMSecs(d->m_msecs, &status);
+ localMSecsToEpochMSecs(getMSecs(d), &status);
return (status == QDateTimePrivate::DaylightTime);
}
}
@@ -3281,7 +3398,7 @@ bool QDateTime::isDaylightTime() const
void QDateTime::setDate(const QDate &date)
{
- d->setDateTime(date, time());
+ setDateTime(d, date, time());
}
/*!
@@ -3299,7 +3416,7 @@ void QDateTime::setDate(const QDate &date)
void QDateTime::setTime(const QTime &time)
{
- d->setDateTime(date(), time);
+ setDateTime(d, date(), time);
}
/*!
@@ -3320,9 +3437,8 @@ void QDateTime::setTime(const QTime &time)
void QDateTime::setTimeSpec(Qt::TimeSpec spec)
{
- QDateTimePrivate *d = this->d.data(); // detaches (and shadows d)
- d->setTimeSpec(spec, 0);
- d->checkValidDateTime();
+ QT_PREPEND_NAMESPACE(setTimeSpec(d, spec, 0));
+ checkValidDateTime(d);
}
/*!
@@ -3342,9 +3458,8 @@ void QDateTime::setTimeSpec(Qt::TimeSpec spec)
void QDateTime::setOffsetFromUtc(int offsetSeconds)
{
- QDateTimePrivate *d = this->d.data(); // detaches (and shadows d)
- d->setTimeSpec(Qt::OffsetFromUTC, offsetSeconds);
- d->checkValidDateTime();
+ QT_PREPEND_NAMESPACE(setTimeSpec(d, Qt::OffsetFromUTC, offsetSeconds));
+ checkValidDateTime(d);
}
#ifndef QT_BOOTSTRAPPED
@@ -3361,11 +3476,11 @@ void QDateTime::setOffsetFromUtc(int offsetSeconds)
void QDateTime::setTimeZone(const QTimeZone &toZone)
{
- QDateTimePrivate *d = this->d.data(); // detaches (and shadows d)
- d->m_spec = Qt::TimeZone;
+ d.detach(); // always detach
+ d->m_status = mergeSpec(d->m_status, Qt::TimeZone);
d->m_offsetFromUtc = 0;
d->m_timeZone = toZone;
- d->refreshDateTime();
+ refreshDateTime(d);
}
#endif // QT_BOOTSTRAPPED
@@ -3382,44 +3497,85 @@ void QDateTime::setTimeZone(const QTimeZone &toZone)
this object is not valid. However, for all valid dates, this function
returns a unique value.
- \sa toTime_t(), setMSecsSinceEpoch()
+ \sa toSecsSinceEpoch(), setMSecsSinceEpoch()
*/
qint64 QDateTime::toMSecsSinceEpoch() const
{
- return d->toMSecsSinceEpoch();
+ 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:
+#ifdef QT_BOOTSTRAPPED
+ return 0;
+#else
+ return QDateTimePrivate::zoneMSecsToEpochMSecs(d->m_msecs, d->m_timeZone);
+#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, so it does not
- support dates before 1970, but it does support dates after
- 2038-01-19T03:14:06, which may not be valid time_t values. Be careful
- when passing those time_t values to system functions, which could
- interpret them as negative dates.
+ \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().
+ To get an extended range, use toMSecsSinceEpoch() or toSecsSinceEpoch().
- \sa toMSecsSinceEpoch(), setTime_t()
+ \sa toSecsSinceEpoch(), toMSecsSinceEpoch(), setTime_t()
*/
uint QDateTime::toTime_t() const
{
if (!isValid())
return uint(-1);
- qint64 retval = d->toMSecsSinceEpoch() / 1000;
+ qint64 retval = toMSecsSinceEpoch() / 1000;
if (quint64(retval) >= Q_UINT64_C(0xFFFFFFFF))
return uint(-1);
return uint(retval);
}
+#endif
/*!
\since 4.7
@@ -3433,65 +3589,98 @@ uint QDateTime::toTime_t() const
(\c{std::numeric_limits<qint64>::min()}) to \a msecs will result in
undefined behavior.
- \sa toMSecsSinceEpoch(), setTime_t()
+ \sa toMSecsSinceEpoch(), setSecsSinceEpoch()
*/
void QDateTime::setMSecsSinceEpoch(qint64 msecs)
{
- QDateTimePrivate *d = this->d.data(); // detaches (and shadows d)
+ const auto spec = getSpec(d);
+ auto status = getStatus(d);
- d->m_status = 0;
- switch (d->m_spec) {
+ status &= ~QDateTimePrivate::ValidityMask;
+ switch (spec) {
case Qt::UTC:
- d->m_msecs = msecs;
- d->m_status = d->m_status
+ status = status
| QDateTimePrivate::ValidDate
| QDateTimePrivate::ValidTime
| QDateTimePrivate::ValidDateTime;
break;
case Qt::OffsetFromUTC:
- d->m_msecs = msecs + (d->m_offsetFromUtc * 1000);
- d->m_status = d->m_status
+ msecs = msecs + (d->m_offsetFromUtc * 1000);
+ status = status
| QDateTimePrivate::ValidDate
| QDateTimePrivate::ValidTime
| QDateTimePrivate::ValidDateTime;
break;
case Qt::TimeZone:
+ Q_ASSERT(!d.isShort());
#ifndef QT_BOOTSTRAPPED
// 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)
d->m_offsetFromUtc = d->m_timeZone.d->offsetFromUtc(msecs);
else
d->m_offsetFromUtc = d->m_timeZone.d->standardTimeOffset(msecs);
- d->m_msecs = msecs + (d->m_offsetFromUtc * 1000);
- d->m_status = d->m_status
+ msecs = msecs + (d->m_offsetFromUtc * 1000);
+ status = status
| QDateTimePrivate::ValidDate
| QDateTimePrivate::ValidTime
| QDateTimePrivate::ValidDateTime;
- d->refreshDateTime();
#endif // QT_BOOTSTRAPPED
break;
case Qt::LocalTime: {
QDate dt;
QTime tm;
- QDateTimePrivate::DaylightStatus status;
- epochMSecsToLocalTime(msecs, &dt, &tm, &status);
- d->setDateTime(dt, tm);
- d->setDaylightStatus(status);
- d->refreshDateTime();
+ 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;
+ 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()
*/
@@ -3499,6 +3688,7 @@ void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
{
setMSecsSinceEpoch((qint64)secsSince1Jan1970UTC * 1000);
}
+#endif
#ifndef QT_NO_DATESTRING
/*!
@@ -3569,13 +3759,13 @@ QString QDateTime::toString(Qt::DateFormat format) const
return QLocale().toString(*this, QLocale::LongFormat);
case Qt::RFC2822Date: {
buf = QLocale::c().toString(*this, QStringLiteral("dd MMM yyyy hh:mm:ss "));
- buf += toOffsetString(Qt::TextDate, d->m_offsetFromUtc);
+ buf += toOffsetString(Qt::TextDate, offsetFromUtc());
return buf;
}
default:
#ifndef QT_NO_TEXTDATE
case Qt::TextDate: {
- const QPair<QDate, QTime> p = d->getDateTime();
+ const QPair<QDate, QTime> p = getDateTime(d);
const QDate &dt = p.first;
const QTime &tm = p.second;
//We cant use date.toString(Qt::TextDate) as we need to insert the time before the year
@@ -3586,14 +3776,14 @@ QString QDateTime::toString(Qt::DateFormat format) const
.arg(dt.year());
if (timeSpec() != Qt::LocalTime) {
buf += QLatin1String(" GMT");
- if (d->m_spec == Qt::OffsetFromUTC)
- buf += toOffsetString(Qt::TextDate, d->m_offsetFromUtc);
+ if (getSpec(d) == Qt::OffsetFromUTC)
+ buf += toOffsetString(Qt::TextDate, offsetFromUtc());
}
return buf;
}
#endif
case Qt::ISODate: {
- const QPair<QDate, QTime> p = d->getDateTime();
+ const QPair<QDate, QTime> p = getDateTime(d);
const QDate &dt = p.first;
const QTime &tm = p.second;
buf = dt.toString(Qt::ISODate);
@@ -3601,12 +3791,12 @@ QString QDateTime::toString(Qt::DateFormat format) const
return QString(); // failed to convert
buf += QLatin1Char('T');
buf += tm.toString(Qt::ISODate);
- switch (d->m_spec) {
+ switch (getSpec(d)) {
case Qt::UTC:
buf += QLatin1Char('Z');
break;
case Qt::OffsetFromUTC:
- buf += toOffsetString(Qt::ISODate, d->m_offsetFromUtc);
+ buf += toOffsetString(Qt::ISODate, offsetFromUtc());
break;
default:
break;
@@ -3695,12 +3885,7 @@ QString QDateTime::toString(const QString& format) const
}
#endif //QT_NO_DATESTRING
-static void massageAdjustedDateTime(Qt::TimeSpec spec,
-#ifndef QT_BOOTSTRAPPED
- const QTimeZone &zone,
-#endif // QT_BOOTSTRAPPED
- QDate *date,
- QTime *time)
+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
@@ -3710,24 +3895,20 @@ static void massageAdjustedDateTime(Qt::TimeSpec spec,
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
- d->daylightStatus() in that case, but it's hard to do so without breaking
+ 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);
#ifndef QT_BOOTSTRAPPED
} else if (spec == Qt::TimeZone) {
- QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(*date, *time), zone, date, time);
+ QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(*date, *time), d->m_timeZone, date, time);
#endif // QT_BOOTSTRAPPED
}
}
-#ifdef QT_BOOTSTRAPPED // Avoid duplicate #if-ery in uses.
-#define MASSAGEADJUSTEDDATETIME(s, z, d, t) massageAdjustedDateTime(s, d, t)
-#else
-#define MASSAGEADJUSTEDDATETIME(s, z, d, t) massageAdjustedDateTime(s, z, d, t)
-#endif // QT_BOOTSTRAPPED
/*!
Returns a QDateTime object containing a datetime \a ndays days
@@ -3746,12 +3927,12 @@ static void massageAdjustedDateTime(Qt::TimeSpec spec,
QDateTime QDateTime::addDays(qint64 ndays) const
{
QDateTime dt(*this);
- QPair<QDate, QTime> p = d->getDateTime();
+ QPair<QDate, QTime> p = getDateTime(d);
QDate &date = p.first;
QTime &time = p.second;
date = date.addDays(ndays);
- MASSAGEADJUSTEDDATETIME(d->m_spec, d->m_timeZone, &date, &time);
- dt.d->setDateTime(date, time);
+ massageAdjustedDateTime(dt.d, &date, &time);
+ setDateTime(dt.d, date, time);
return dt;
}
@@ -3772,12 +3953,12 @@ QDateTime QDateTime::addDays(qint64 ndays) const
QDateTime QDateTime::addMonths(int nmonths) const
{
QDateTime dt(*this);
- QPair<QDate, QTime> p = d->getDateTime();
+ QPair<QDate, QTime> p = getDateTime(d);
QDate &date = p.first;
QTime &time = p.second;
date = date.addMonths(nmonths);
- MASSAGEADJUSTEDDATETIME(d->m_spec, d->m_timeZone, &date, &time);
- dt.d->setDateTime(date, time);
+ massageAdjustedDateTime(dt.d, &date, &time);
+ setDateTime(dt.d, date, time);
return dt;
}
@@ -3798,15 +3979,14 @@ QDateTime QDateTime::addMonths(int nmonths) const
QDateTime QDateTime::addYears(int nyears) const
{
QDateTime dt(*this);
- QPair<QDate, QTime> p = d->getDateTime();
+ QPair<QDate, QTime> p = getDateTime(d);
QDate &date = p.first;
QTime &time = p.second;
date = date.addYears(nyears);
- MASSAGEADJUSTEDDATETIME(d->m_spec, d->m_timeZone, &date, &time);
- dt.d->setDateTime(date, time);
+ massageAdjustedDateTime(dt.d, &date, &time);
+ setDateTime(dt.d, date, time);
return dt;
}
-#undef MASSAGEADJUSTEDDATETIME
/*!
Returns a QDateTime object containing a datetime \a s seconds
@@ -3838,12 +4018,26 @@ QDateTime QDateTime::addMSecs(qint64 msecs) const
return QDateTime();
QDateTime dt(*this);
- if (d->m_spec == Qt::LocalTime || d->m_spec == Qt::TimeZone)
+ auto spec = getSpec(d);
+ if (spec == Qt::LocalTime || spec == Qt::TimeZone) {
// Convert to real UTC first in case crosses DST transition
- dt.setMSecsSinceEpoch(d->toMSecsSinceEpoch() + msecs);
- else
+ dt.setMSecsSinceEpoch(toMSecsSinceEpoch() + msecs);
+ } else {
// No need to convert, just add on
- dt.d->m_msecs = dt.d->m_msecs + msecs;
+ 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;
}
@@ -3909,7 +4103,7 @@ qint64 QDateTime::msecsTo(const QDateTime &other) const
if (!isValid() || !other.isValid())
return 0;
- return other.d->toMSecsSinceEpoch() - d->toMSecsSinceEpoch();
+ return other.toMSecsSinceEpoch() - toMSecsSinceEpoch();
}
/*!
@@ -3932,7 +4126,7 @@ qint64 QDateTime::msecsTo(const QDateTime &other) const
QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
{
- if (d->m_spec == spec && (spec == Qt::UTC || spec == Qt::LocalTime))
+ if (getSpec(d) == spec && (spec == Qt::UTC || spec == Qt::LocalTime))
return *this;
if (!isValid()) {
@@ -3941,7 +4135,7 @@ QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
return ret;
}
- return fromMSecsSinceEpoch(d->toMSecsSinceEpoch(), spec, 0);
+ return fromMSecsSinceEpoch(toMSecsSinceEpoch(), spec, 0);
}
/*!
@@ -3959,7 +4153,8 @@ QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
QDateTime QDateTime::toOffsetFromUtc(int offsetSeconds) const
{
- if (d->m_spec == Qt::OffsetFromUTC && d->m_offsetFromUtc == offsetSeconds)
+ if (getSpec(d) == Qt::OffsetFromUTC
+ && d->m_offsetFromUtc == offsetSeconds)
return *this;
if (!isValid()) {
@@ -3968,7 +4163,7 @@ QDateTime QDateTime::toOffsetFromUtc(int offsetSeconds) const
return ret;
}
- return fromMSecsSinceEpoch(d->toMSecsSinceEpoch(), Qt::OffsetFromUTC, offsetSeconds);
+ return fromMSecsSinceEpoch(toMSecsSinceEpoch(), Qt::OffsetFromUTC, offsetSeconds);
}
#ifndef QT_BOOTSTRAPPED
@@ -3982,7 +4177,7 @@ QDateTime QDateTime::toOffsetFromUtc(int offsetSeconds) const
QDateTime QDateTime::toTimeZone(const QTimeZone &timeZone) const
{
- if (d->m_spec == Qt::TimeZone && d->m_timeZone == timeZone)
+ if (getSpec(d) == Qt::TimeZone && d->m_timeZone == timeZone)
return *this;
if (!isValid()) {
@@ -3991,7 +4186,7 @@ QDateTime QDateTime::toTimeZone(const QTimeZone &timeZone) const
return ret;
}
- return fromMSecsSinceEpoch(d->toMSecsSinceEpoch(), timeZone);
+ return fromMSecsSinceEpoch(toMSecsSinceEpoch(), timeZone);
}
#endif // QT_BOOTSTRAPPED
@@ -4004,10 +4199,9 @@ QDateTime QDateTime::toTimeZone(const QTimeZone &timeZone) const
bool QDateTime::operator==(const QDateTime &other) const
{
- if (d->m_spec == Qt::LocalTime
- && other.d->m_spec == Qt::LocalTime
- && d->m_status == other.d->m_status) {
- return (d->m_msecs == other.d->m_msecs);
+ 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());
@@ -4032,10 +4226,9 @@ bool QDateTime::operator==(const QDateTime &other) const
bool QDateTime::operator<(const QDateTime &other) const
{
- if (d->m_spec == Qt::LocalTime
- && other.d->m_spec == Qt::LocalTime
- && d->m_status == other.d->m_status) {
- return (d->m_msecs < other.d->m_msecs);
+ 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());
@@ -4090,6 +4283,16 @@ bool QDateTime::operator<(const QDateTime &other) const
\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)
{
@@ -4113,9 +4316,6 @@ QTime QTime::currentTime()
memset(&st, 0, sizeof(SYSTEMTIME));
GetLocalTime(&st);
ct.setHMS(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
-#if defined(Q_OS_WINCE)
- ct.startTick = GetTickCount() % MSECS_PER_DAY;
-#endif
return ct;
}
@@ -4154,6 +4354,17 @@ qint64 QDateTime::currentMSecsSinceEpoch() Q_DECL_NOTHROW
- julianDayFromDate(1970, 1, 1)) * Q_INT64_C(86400000);
}
+qint64 QDateTime::currentSecsSinceEpoch() Q_DECL_NOTHROW
+{
+ 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()
{
@@ -4184,51 +4395,29 @@ qint64 QDateTime::currentMSecsSinceEpoch() Q_DECL_NOTHROW
return qint64(tv.tv_sec) * Q_INT64_C(1000) + tv.tv_usec / 1000;
}
+qint64 QDateTime::currentSecsSinceEpoch() Q_DECL_NOTHROW
+{
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ return qint64(tv.tv_sec);
+}
#else
#error "What system is this?"
#endif
-/*! \fn QDateTime QDateTime::fromCFDate(CFDateRef date)
- \since 5.5
-
- Constructs a new QDateTime containing a copy of the CFDate \a date.
-
- \sa toCFDate()
-*/
-
-/*! \fn CFDateRef QDateTime::toCFDate() const
- \since 5.5
-
- Creates a CFDate from a QDateTime. The caller owns the CFDate object
- and is responsible for releasing it.
-
- \sa fromCFDate()
-*/
-
-/*! \fn QDateTime QDateTime::fromNSDate(const NSDate *date)
- \since 5.5
-
- Constructs a new QDateTime containing a copy of the NSDate \a date.
-
- \sa toNSDate()
-*/
-
-/*! \fn NSDate QDateTime::toNSDate() const
- \since 5.5
-
- Creates an NSDate from a QDateTime. The NSDate object is autoreleased.
-
- \sa fromNSDate()
-*/
-
+#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)
@@ -4238,6 +4427,7 @@ QDateTime QDateTime::fromTime_t(uint seconds)
/*!
\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
@@ -4247,6 +4437,9 @@ QDateTime QDateTime::fromTime_t(uint seconds)
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)
@@ -4257,11 +4450,15 @@ QDateTime QDateTime::fromTime_t(uint seconds, Qt::TimeSpec spec, int offsetSecon
#ifndef QT_BOOTSTRAPPED
/*!
\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)
@@ -4269,6 +4466,7 @@ 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
@@ -4282,7 +4480,7 @@ QDateTime QDateTime::fromTime_t(uint seconds, const QTimeZone &timeZone)
range of QDateTime, both negative and positive. The behavior of this
function is undefined for those values.
- \sa toTime_t(), setTime_t()
+ \sa toMSecsSinceEpoch(), setMSecsSinceEpoch()
*/
QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
{
@@ -4307,16 +4505,41 @@ QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
If \a spec is Qt::TimeZone then the spec will be set to Qt::LocalTime,
i.e. the current system time zone.
- \sa fromTime_t()
+ \sa toMSecsSinceEpoch(), setMSecsSinceEpoch()
*/
QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec, int offsetSeconds)
{
QDateTime dt;
- dt.d->setTimeSpec(spec, offsetSeconds);
+ 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);
+}
+
#ifndef QT_BOOTSTRAPPED
/*!
\since 5.2
@@ -4325,7 +4548,7 @@ QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec, int of
that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
Time (Qt::UTC) and with the given \a timeZone.
- \sa fromTime_t()
+ \sa fromSecsSinceEpoch()
*/
QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone)
{
@@ -4334,6 +4557,20 @@ QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &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)
@@ -4831,7 +5068,7 @@ QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
if (out.version() >= QDataStream::Qt_5_2) {
// In 5.2 we switched to using Qt::TimeSpec and added offset support
- dateAndTime = dateTime.d->getDateTime();
+ dateAndTime = getDateTime(dateTime.d);
out << dateAndTime << qint8(dateTime.timeSpec());
if (dateTime.timeSpec() == Qt::OffsetFromUTC)
out << qint32(dateTime.offsetFromUtc());
@@ -4846,13 +5083,13 @@ QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
// 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 = (dateTime.isValid() ? dateTime.toUTC() : dateTime).d->getDateTime();
+ 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 = dateTime.d->getDateTime();
+ dateAndTime = getDateTime(dateTime.d);
out << dateAndTime;
switch (dateTime.timeSpec()) {
case Qt::UTC:
@@ -4872,7 +5109,7 @@ QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
} else { // version < QDataStream::Qt_4_0
// Before 4.0 there was no TimeSpec, only Qt::LocalTime was supported
- dateAndTime = dateTime.d->getDateTime();
+ dateAndTime = getDateTime(dateTime.d);
out << dateAndTime;
}