Handle invalid system zone case when falling back from time_t functions

Ammends commit 530e0bd469e6859269c2d1a792b8ce819fbff389, in which I
added a QTimeZone-based fall-back for handling of conversions between
local time and UTC when outside the range supported by time_t-based
functions. That replaced prior kludges, when feature timezone is
enabled; however, even with feature timezone, it's possible for the
system zone to be invalid. So retain the old kludges also as fall-back
for when the system zone is invalid, as well as when we have no
timezones to fall back on.

Change-Id: Ie2b8af7f1a87d7b0e39cc5ac0c04b04d574f84b5
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Edward Welbourne 2021-04-28 15:08:50 +02:00
parent 8ec07b4afc
commit ae5d40e674

View File

@ -2657,19 +2657,22 @@ bool QDateTimePrivate::epochMSecsToLocalTime(qint64 msecs, QDate *localDate, QTi
#if QT_CONFIG(timezone) #if QT_CONFIG(timezone)
// Use the system time-zone. // Use the system time-zone.
const auto sys = QTimeZone::systemTimeZone(); const auto sys = QTimeZone::systemTimeZone();
if (daylightStatus) { if (sys.isValid()) {
*daylightStatus = sys.d->isDaylightTime(msecs) if (daylightStatus) {
? QDateTimePrivate::DaylightTime *daylightStatus = sys.d->isDaylightTime(msecs)
: QDateTimePrivate::StandardTime; ? QDateTimePrivate::DaylightTime
} : QDateTimePrivate::StandardTime;
}
// NB: cast to qint64 here is important to make sure a matching // NB: cast to qint64 here is important to make sure a matching
// add_overflow is found, GCC 7.5.0 fails without this cast // add_overflow is found, GCC 7.5.0 fails without this cast
if (add_overflow(msecs, qint64(sys.d->offsetFromUtc(msecs) * MSECS_PER_SEC), &msecs)) if (add_overflow(msecs, qint64(sys.d->offsetFromUtc(msecs)) * MSECS_PER_SEC, &msecs))
return false; return false;
msecsToTime(msecs, localDate, localTime); msecsToTime(msecs, localDate, localTime);
return true; return true;
#else // Kludge }
#endif // timezone
// Kludge
// Use existing method to fake the conversion (this is deeply flawed // Use existing method to fake the conversion (this is deeply flawed
// as it may apply the conversion from the wrong day number, e.g. if // as it may apply the conversion from the wrong day number, e.g. if
// rule is last Sunday of month). // rule is last Sunday of month).
@ -2686,7 +2689,6 @@ bool QDateTimePrivate::epochMSecsToLocalTime(qint64 msecs, QDate *localDate, QTi
bool res = qt_localtime(fakeMsecs, localDate, localTime, daylightStatus); bool res = qt_localtime(fakeMsecs, localDate, localTime, daylightStatus);
*localDate = localDate->addDays(fakeDate.daysTo(utcDate)); *localDate = localDate->addDays(fakeDate.daysTo(utcDate));
return res; return res;
#endif // timezone
} }
// Falls inside time_t supported range so can use localtime // Falls inside time_t supported range so can use localtime
@ -2743,19 +2745,22 @@ qint64 QDateTimePrivate::localMSecsToEpochMSecs(qint64 localMsecs,
#if QT_CONFIG(timezone) #if QT_CONFIG(timezone)
// Use the system zone: // Use the system zone:
const auto sys = QTimeZone::systemTimeZone(); const auto sys = QTimeZone::systemTimeZone();
const qint64 utcMsecs = if (sys.isValid()) {
QDateTimePrivate::zoneMSecsToEpochMSecs(localMsecs, sys, const qint64 utcMsecs =
QDateTimePrivate::UnknownDaylightTime, QDateTimePrivate::zoneMSecsToEpochMSecs(localMsecs, sys,
localDate, localTime); QDateTimePrivate::UnknownDaylightTime,
if (abbreviation) localDate, localTime);
*abbreviation = sys.d->abbreviation(utcMsecs); if (abbreviation && sys.isValid())
if (daylightStatus) { *abbreviation = sys.d->abbreviation(utcMsecs);
*daylightStatus = sys.d->isDaylightTime(utcMsecs) if (daylightStatus) {
? QDateTimePrivate::DaylightTime *daylightStatus = sys.isValid() && sys.d->isDaylightTime(utcMsecs)
: QDateTimePrivate::StandardTime; ? QDateTimePrivate::DaylightTime
: QDateTimePrivate::StandardTime;
}
return utcMsecs;
} }
return utcMsecs; #endif // timezone
#else // Kludge // Kludge
// Use existing method to fake the conversion (this is deeply flawed as it // Use existing method to fake the conversion (this is deeply flawed as it
// may apply the conversion from the wrong day number, e.g. if rule is last // may apply the conversion from the wrong day number, e.g. if rule is last
// Sunday of month). // Sunday of month).
@ -2777,7 +2782,6 @@ qint64 QDateTimePrivate::localMSecsToEpochMSecs(qint64 localMsecs,
QTime utcTime; QTime utcTime;
msecsToTime(utcMsecs, &utcDate, &utcTime); msecsToTime(utcMsecs, &utcDate, &utcTime);
return timeToMSecs(utcDate.addDays(fakeDiff), utcTime); return timeToMSecs(utcDate.addDays(fakeDiff), utcTime);
#endif
} }
static inline bool specCanBeSmall(Qt::TimeSpec spec) static inline bool specCanBeSmall(Qt::TimeSpec spec)