QDateTime - Store Qt::TimeSpec, remove Daylight Status

Change storing the spec from QDateTimePrivate::Spec to Qt::TimeSpec.

Remove the storage and use of the Daylight Status as it is almost
never set or used, and would be inaccurate if the tz were to change.
It will be replaced later with proper daylight transition support.

This simplifies the code and makes the msecs storage change easier.

Change-Id: I78a70905025d7eddf1c2dc6001f6b490e5a2b3b8
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
John Layt 2013-08-12 14:20:56 +02:00 committed by The Qt Project
parent e76c312eb8
commit 6c3a9df3fe
2 changed files with 116 additions and 102 deletions

View File

@ -220,11 +220,11 @@ static int fromOffsetString(const QString &offsetString, bool *valid)
#if !defined(Q_OS_WINCE)
// Calls the platform variant of mktime for the given date and time,
// and updates the date, time, spec and abbreviation with the returned values
// 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 call adjustDate() first if
// you need a guaranteed result.
static time_t qt_mktime(QDate *date, QTime *time, QDateTimePrivate::Spec *spec,
static time_t qt_mktime(QDate *date, QTime *time, QDateTimePrivate::DaylightStatus *daylightStatus,
QString *abbreviation, bool *ok)
{
if (ok)
@ -251,18 +251,18 @@ static time_t qt_mktime(QDate *date, QTime *time, QDateTimePrivate::Spec *spec,
*date = QDate(local.tm_year + 1900, local.tm_mon + 1, local.tm_mday);
*time = QTime(local.tm_hour, local.tm_min, local.tm_sec, time->msec());
if (local.tm_isdst == 1) {
if (spec)
*spec = QDateTimePrivate::LocalDST;
if (daylightStatus)
*daylightStatus = QDateTimePrivate::DaylightTime;
if (abbreviation)
*abbreviation = QString::fromLocal8Bit(tzname[1]);
} else if (local.tm_isdst == 0) {
if (spec)
*spec = QDateTimePrivate::LocalStandard;
if (daylightStatus)
*daylightStatus = QDateTimePrivate::StandardTime;
if (abbreviation)
*abbreviation = QString::fromLocal8Bit(tzname[0]);
} else {
if (spec)
*spec = QDateTimePrivate::LocalUnknown;
if (daylightStatus)
*daylightStatus = QDateTimePrivate::UnknownDaylightTime;
if (abbreviation)
*abbreviation = QString::fromLocal8Bit(tzname[0]);
}
@ -271,8 +271,8 @@ static time_t qt_mktime(QDate *date, QTime *time, QDateTimePrivate::Spec *spec,
} else {
*date = QDate();
*time = QTime();
if (spec)
*spec = QDateTimePrivate::LocalUnknown;
if (daylightStatus)
*daylightStatus = QDateTimePrivate::UnknownDaylightTime;
if (abbreviation)
*abbreviation = QString();
}
@ -2153,6 +2153,29 @@ int QTime::elapsed() const
return n;
}
/*****************************************************************************
QDateTimePrivate member functions
*****************************************************************************/
void QDateTimePrivate::setTimeSpec(Qt::TimeSpec spec, int offsetSeconds)
{
switch (spec) {
case Qt::OffsetFromUTC:
if (offsetSeconds == 0) {
m_spec = Qt::UTC;
m_offsetFromUtc = 0;
} else {
m_spec = Qt::OffsetFromUTC;
m_offsetFromUtc = offsetSeconds;
}
break;
case Qt::UTC:
case Qt::LocalTime:
m_spec = spec;
m_offsetFromUtc = 0;
break;
}
}
/*****************************************************************************
QDateTime member functions
@ -2347,23 +2370,7 @@ QDateTimePrivate::QDateTimePrivate(const QDate &toDate, const QTime &toTime, Qt:
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;
}
setTimeSpec(toSpec, offsetSeconds);
}
/*!
@ -2454,15 +2461,7 @@ QTime QDateTime::time() const
Qt::TimeSpec QDateTime::timeSpec() const
{
switch(d->spec)
{
case QDateTimePrivate::UTC:
return Qt::UTC;
case QDateTimePrivate::OffsetFromUTC:
return Qt::OffsetFromUTC;
default:
return Qt::LocalTime;
}
return d->m_spec;
}
/*!
@ -2482,15 +2481,16 @@ Qt::TimeSpec QDateTime::timeSpec() const
int QDateTime::offsetFromUtc() const
{
switch (d->spec) {
case QDateTimePrivate::OffsetFromUTC:
switch (d->m_spec) {
case Qt::OffsetFromUTC:
return d->m_offsetFromUtc;
case QDateTimePrivate::UTC:
case Qt::UTC:
return 0;
default: // Any Qt::LocalTime
case Qt::LocalTime:
const QDateTime fakeDate(d->date, d->time, Qt::UTC);
return (fakeDate.toMSecsSinceEpoch() - toMSecsSinceEpoch()) / 1000;
}
return 0;
}
/*!
@ -2516,12 +2516,12 @@ int QDateTime::offsetFromUtc() const
QString QDateTime::timeZoneAbbreviation() const
{
switch (d->spec) {
case QDateTimePrivate::UTC:
switch (d->m_spec) {
case Qt::UTC:
return QStringLiteral("UTC");
case QDateTimePrivate::OffsetFromUTC:
case Qt::OffsetFromUTC:
return QLatin1String("UTC") + toOffsetString(Qt::ISODate, d->m_offsetFromUtc);
default: { // Any Qt::LocalTime
case Qt::LocalTime: {
#if defined(Q_OS_WINCE)
// TODO Stub to enable compilation on WinCE
return QString();
@ -2534,6 +2534,7 @@ QString QDateTime::timeZoneAbbreviation() const
#endif // !Q_OS_WINCE
}
}
return QString();
}
/*!
@ -2547,9 +2548,6 @@ void QDateTime::setDate(const QDate &date)
{
detach();
d->date = date;
if (d->spec == QDateTimePrivate::LocalStandard
|| d->spec == QDateTimePrivate::LocalDST)
d->spec = QDateTimePrivate::LocalUnknown;
if (date.isValid() && !d->time.isValid())
d->time = QTime(0, 0, 0);
}
@ -2563,9 +2561,6 @@ void QDateTime::setDate(const QDate &date)
void QDateTime::setTime(const QTime &time)
{
detach();
if (d->spec == QDateTimePrivate::LocalStandard
|| d->spec == QDateTimePrivate::LocalDST)
d->spec = QDateTimePrivate::LocalUnknown;
d->time = time;
}
@ -2585,17 +2580,7 @@ void QDateTime::setTime(const QTime &time)
void QDateTime::setTimeSpec(Qt::TimeSpec spec)
{
detach();
d->m_offsetFromUtc = 0;
switch (spec) {
case Qt::UTC:
case Qt::OffsetFromUTC:
d->spec = QDateTimePrivate::UTC;
break;
default:
d->spec = QDateTimePrivate::LocalUnknown;
break;
}
d->setTimeSpec(spec, 0);
}
/*!
@ -2616,14 +2601,7 @@ void QDateTime::setTimeSpec(Qt::TimeSpec spec)
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;
}
d->setTimeSpec(Qt::OffsetFromUTC, offsetSeconds);
}
qint64 toMSecsSinceEpoch_helper(qint64 jd, int msecs)
@ -2716,9 +2694,9 @@ void QDateTime::setMSecsSinceEpoch(qint64 msecs)
d->date = QDate(1970, 1, 1).addDays(ddays);
d->time = QTime::fromMSecsSinceStartOfDay(msecs);
if (d->spec == QDateTimePrivate::OffsetFromUTC)
if (d->m_spec == Qt::OffsetFromUTC)
utcToOffset(&d->date, &d->time, d->m_offsetFromUtc);
else if (d->spec != QDateTimePrivate::UTC)
else if (d->m_spec != Qt::UTC)
utcToLocal(d->date, d->time);
}
@ -2839,7 +2817,7 @@ QString QDateTime::toString(Qt::DateFormat format) const
.arg(d->date.year());
if (timeSpec() != Qt::LocalTime) {
buf += QStringLiteral(" GMT");
if (d->spec == QDateTimePrivate::OffsetFromUTC)
if (d->m_spec == Qt::OffsetFromUTC)
buf += toOffsetString(Qt::TextDate, d->m_offsetFromUtc);
}
return buf;
@ -2850,11 +2828,11 @@ QString QDateTime::toString(Qt::DateFormat format) const
return QString(); // failed to convert
buf += QLatin1Char('T');
buf += d->time.toString(Qt::ISODate);
switch (d->spec) {
case QDateTimePrivate::UTC:
switch (d->m_spec) {
case Qt::UTC:
buf += QLatin1Char('Z');
break;
case QDateTimePrivate::OffsetFromUTC:
case Qt::OffsetFromUTC:
buf += toOffsetString(Qt::ISODate, d->m_offsetFromUtc);
break;
default:
@ -3422,10 +3400,8 @@ QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec, int offsetSeconds)
{
QDateTime dt;
if (spec == Qt::OffsetFromUTC)
dt.setOffsetFromUtc(offsetSeconds);
else
dt.setTimeSpec(spec);
dt.detach();
dt.d->setTimeSpec(spec, offsetSeconds);
dt.setMSecsSinceEpoch(msecs);
return dt;
}
@ -3934,10 +3910,21 @@ QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
out << (qint8)dateTime.timeSpec();
} else {
out << dateTime.d->date << dateTime.d->time;
if (out.version() >= QDataStream::Qt_4_0)
out << (qint8)dateTime.d->spec;
if (out.version() >= QDataStream::Qt_4_0) {
switch (dateTime.d->m_spec) {
case Qt::UTC:
out << (qint8)QDateTimePrivate::UTC;
break;
case Qt::OffsetFromUTC:
out << (qint8)QDateTimePrivate::OffsetFromUTC;
break;
case Qt::LocalTime:
out << (qint8)QDateTimePrivate::LocalUnknown;
break;
}
}
if (out.version() >= QDataStream::Qt_5_2
&& dateTime.d->spec == QDateTimePrivate::OffsetFromUTC) {
&& dateTime.d->m_spec == Qt::OffsetFromUTC) {
out << qint32(dateTime.offsetFromUtc());
}
}
@ -3963,7 +3950,7 @@ QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
in >> ts;
if (dateTime.isValid()) {
// We incorrectly stored the datetime as UTC in Qt_5_0.
dateTime.d->spec = QDateTimePrivate::UTC;
dateTime.d->m_spec = Qt::UTC;
dateTime = dateTime.toTimeSpec(static_cast<Qt::TimeSpec>(ts));
}
} else {
@ -3973,14 +3960,25 @@ QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
qint32 offset = 0;
if (in.version() >= QDataStream::Qt_5_2 && ts == qint8(QDateTimePrivate::OffsetFromUTC))
in >> offset;
dateTime.d->spec = (QDateTimePrivate::Spec)ts;
switch ((QDateTimePrivate::Spec)ts) {
case QDateTimePrivate::UTC:
dateTime.d->m_spec = Qt::UTC;
break;
case QDateTimePrivate::OffsetFromUTC:
dateTime.d->m_spec = Qt::OffsetFromUTC;
break;
case QDateTimePrivate::LocalUnknown:
case QDateTimePrivate::LocalStandard:
case QDateTimePrivate::LocalDST:
dateTime.d->m_spec = Qt::LocalTime;
break;
}
dateTime.d->m_offsetFromUtc = offset;
}
return in;
}
#endif // QT_NO_DATASTREAM
/*****************************************************************************
Some static function used by QDate, QTime and QDateTime
*****************************************************************************/
@ -4224,13 +4222,13 @@ QDateTimePrivate::Spec QDateTimePrivate::getLocal(QDate &outDate, QTime &outTime
{
outDate = date;
outTime = time;
if (spec == QDateTimePrivate::UTC)
if (m_spec == Qt::UTC)
return utcToLocal(outDate, outTime);
if (spec == QDateTimePrivate::OffsetFromUTC) {
if (m_spec == Qt::OffsetFromUTC) {
offsetToUtc(&outDate, &outTime, m_offsetFromUtc);
return utcToLocal(outDate, outTime);
}
return spec;
return LocalUnknown;
}
// Get current date/time in UTC and put result in outDate and outTime
@ -4239,10 +4237,10 @@ void QDateTimePrivate::getUTC(QDate &outDate, QTime &outTime) const
outDate = date;
outTime = time;
if (spec == QDateTimePrivate::OffsetFromUTC)
if (m_spec == Qt::OffsetFromUTC)
offsetToUtc(&outDate, &outTime, m_offsetFromUtc);
else if (spec != QDateTimePrivate::UTC)
localToUtc(outDate, outTime, (int)spec);
else if (m_spec != Qt::UTC)
localToUtc(outDate, outTime, -1);
}
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING)
@ -4261,18 +4259,16 @@ QDebug operator<<(QDebug dbg, const QTime &time)
QDebug operator<<(QDebug dbg, const QDateTime &date)
{
QString spec;
switch (date.d->spec) {
case QDateTimePrivate::UTC :
switch (date.d->m_spec) {
case Qt::UTC:
spec = QStringLiteral(" Qt::UTC");
break;
case QDateTimePrivate::OffsetFromUTC :
case Qt::OffsetFromUTC:
spec = QString::fromUtf8(" Qt::OffsetFromUTC %1s").arg(date.offsetFromUtc());
break;
case QDateTimePrivate::LocalDST :
case QDateTimePrivate::LocalStandard :
case QDateTimePrivate::LocalUnknown :
default :
case Qt::LocalTime:
spec = QStringLiteral(" Qt::LocalTime");
break;
}
QString output = date.toString(QStringLiteral("yyyy-MM-dd HH:mm:ss.zzz t")) + spec;
dbg.nospace() << "QDateTime(" << output << ')';

View File

@ -62,19 +62,35 @@ QT_BEGIN_NAMESPACE
class QDateTimePrivate : public QSharedData
{
public:
enum Spec { LocalUnknown = -1, LocalStandard = 0, LocalDST = 1, UTC = 2, OffsetFromUTC = 3};
// Never change or delete this enum, it is required for backwards compatible
// serialization of QDateTime before 5.2, so is essentially public API
enum Spec {
LocalUnknown = -1,
LocalStandard = 0,
LocalDST = 1,
UTC = 2,
OffsetFromUTC = 3
};
QDateTimePrivate() : spec(LocalUnknown), m_offsetFromUtc(0) {}
// Daylight Time Status
enum DaylightStatus {
NoDaylightTime,
UnknownDaylightTime,
StandardTime,
DaylightTime
};
QDateTimePrivate() : m_spec(Qt::LocalTime), 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),
: QSharedData(other), date(other.date), time(other.time), m_spec(other.m_spec),
m_offsetFromUtc(other.m_offsetFromUtc)
{}
QDate date;
QTime time;
Spec spec;
Qt::TimeSpec m_spec;
int m_offsetFromUtc;
// Get current date/time in LocalTime and put result in outDate and outTime
@ -85,6 +101,8 @@ public:
// Add msecs to given datetime and put result in utcDate and utcTime
static void addMSecs(QDate &utcDate, QTime &utcTime, qint64 msecs);
void setTimeSpec(Qt::TimeSpec spec, int offsetSeconds);
static inline qint64 minJd() { return QDate::minJd(); }
static inline qint64 maxJd() { return QDate::maxJd(); }
};