Implement some TODOs: make use of GLibc's tm_gmtoff and tm_zone
Save some complicated computations using struct tm and (effectively) time_t used in working out local-time's UTC offset and updating the local time's representation in terms of seconds (since a nominal local epoch). GLibc gives us the offset for free, making computation of the seconds easy. Use the same extension to catch an opportunity for a seldom-needed early return in one more case. When determining a zone's abbreviation, we can use tm_zone as a short-cut to save some mutex-locking. Change-Id: Id2958f75c1d49ad4aed8f9c483ec13f4fe3a86c2 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
b6761d098b
commit
781042efcb
@ -20,6 +20,11 @@
|
|||||||
# include <qt_windows.h>
|
# include <qt_windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GLIBC__ // Extends struct tm with some extra fields:
|
||||||
|
#define HAVE_TM_GMTOFF // tm_gmtoff is the UTC offset.
|
||||||
|
#define HAVE_TM_ZONE // tm_zone is the zone abbreviation.
|
||||||
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace QtPrivate::DateTimeConstants;
|
using namespace QtPrivate::DateTimeConstants;
|
||||||
@ -80,10 +85,12 @@ public:
|
|||||||
|
|
||||||
We can assume time-zone offsets are less than a day, so this can only arise
|
We can assume time-zone offsets are less than a day, so this can only arise
|
||||||
if the struct tm describes either the last day of 1969 or the first day of
|
if the struct tm describes either the last day of 1969 or the first day of
|
||||||
1970. That makes for a cheap pre-test; if it holds, we can ask mktime about
|
1970. When we do know the offset (a glibc extension supplies it as a member
|
||||||
the preceding second; if it gives us -2, then the -1 we originally saw is not
|
of struct tm), we can determine whether we're on the last second of the day,
|
||||||
an error (or was an error, but needn't have been). We can then synthesize a
|
refining that check. That makes for a cheap pre-test; if it holds, we can ask
|
||||||
corrected value for local using the -2 result.
|
mktime() about the preceding second; if it gives us -2, then the -1 we
|
||||||
|
originally saw is not (or at least didn't need to be) an error. We can then
|
||||||
|
synthesize a corrected value for local using the -2 result.
|
||||||
*/
|
*/
|
||||||
inline bool MkTimeResult::meansEnd1969()
|
inline bool MkTimeResult::meansEnd1969()
|
||||||
{
|
{
|
||||||
@ -91,6 +98,12 @@ inline bool MkTimeResult::meansEnd1969()
|
|||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
if (local.tm_year < 69 || local.tm_year > 70
|
if (local.tm_year < 69 || local.tm_year > 70
|
||||||
|
# ifdef HAVE_TM_GMTOFF
|
||||||
|
// Africa/Monrovia had offset 00:44:30 at the epoch, so (although all
|
||||||
|
// other zones' offsets were round multiples of five minutes) we need
|
||||||
|
// the offset to determine whether the time might match:
|
||||||
|
|| (tmSecsWithinDay(local) - local.tm_gmtoff + 1) % SECS_PER_DAY
|
||||||
|
# endif
|
||||||
|| (local.tm_year == 69 // ... and less than a day:
|
|| (local.tm_year == 69 // ... and less than a day:
|
||||||
? local.tm_mon < 11 || local.tm_mday < 31
|
? local.tm_mon < 11 || local.tm_mday < 31
|
||||||
: local.tm_mon > 0 || local.tm_mday > 1)) {
|
: local.tm_mon > 0 || local.tm_mday > 1)) {
|
||||||
@ -555,7 +568,10 @@ QString localTimeAbbbreviationAt(qint64 local, QDateTimePrivate::DaylightStatus
|
|||||||
auto use = resolveLocalTime(QRoundingDown::qDiv<MSECS_PER_SEC>(local), dst);
|
auto use = resolveLocalTime(QRoundingDown::qDiv<MSECS_PER_SEC>(local), dst);
|
||||||
if (!use.good)
|
if (!use.good)
|
||||||
return {};
|
return {};
|
||||||
// TODO: for glibc, use.local.tm_zone is the zone abbreviation.
|
#ifdef HAVE_TM_ZONE
|
||||||
|
if (use.local.tm_zone)
|
||||||
|
return QString::fromLocal8Bit(use.local.tm_zone);
|
||||||
|
#endif
|
||||||
return qTzName(use.local.tm_isdst > 0 ? 1 : 0);
|
return qTzName(use.local.tm_isdst > 0 ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -572,12 +588,14 @@ QDateTimePrivate::ZoneState mapLocalTime(qint64 local, QDateTimePrivate::Dayligh
|
|||||||
Q_ASSERT(local < 0 ? (millis <= 0 && millis > -MSECS_PER_SEC)
|
Q_ASSERT(local < 0 ? (millis <= 0 && millis > -MSECS_PER_SEC)
|
||||||
: (millis >= 0 && millis < MSECS_PER_SEC));
|
: (millis >= 0 && millis < MSECS_PER_SEC));
|
||||||
|
|
||||||
// TODO: for glibc, use.local.tm_gmtoff is the offset
|
|
||||||
// That would give us offset directly, hence localSecs = offset + use.utcSecs
|
|
||||||
// Provisional offset, until we have a revised localSecs:
|
|
||||||
int offset = localSecs - use.utcSecs;
|
|
||||||
// Revise our original hint-dst to what it resolved to:
|
// Revise our original hint-dst to what it resolved to:
|
||||||
dst = use.local.tm_isdst > 0 ? QDateTimePrivate::DaylightTime : QDateTimePrivate::StandardTime;
|
dst = use.local.tm_isdst > 0 ? QDateTimePrivate::DaylightTime : QDateTimePrivate::StandardTime;
|
||||||
|
#ifdef HAVE_TM_GMTOFF
|
||||||
|
const int offset = use.local.tm_gmtoff;
|
||||||
|
localSecs = offset + use.utcSecs;
|
||||||
|
#else
|
||||||
|
// Provisional offset, until we have a revised localSecs:
|
||||||
|
int offset = localSecs - use.utcSecs;
|
||||||
auto jd = tmToJd(use.local);
|
auto jd = tmToJd(use.local);
|
||||||
if (Q_UNLIKELY(!jd))
|
if (Q_UNLIKELY(!jd))
|
||||||
return {local, offset, dst, false};
|
return {local, offset, dst, false};
|
||||||
@ -593,6 +611,7 @@ QDateTimePrivate::ZoneState mapLocalTime(qint64 local, QDateTimePrivate::Dayligh
|
|||||||
|
|
||||||
// Use revised localSecs to refine offset:
|
// Use revised localSecs to refine offset:
|
||||||
offset = localSecs - use.utcSecs;
|
offset = localSecs - use.utcSecs;
|
||||||
|
#endif // HAVE_TM_GMTOFF
|
||||||
|
|
||||||
// The only way localSecs and millis can now have opposite sign is for
|
// The only way localSecs and millis can now have opposite sign is for
|
||||||
// resolution of the local time to have kicked us across the epoch, in which
|
// resolution of the local time to have kicked us across the epoch, in which
|
||||||
|
Loading…
x
Reference in New Issue
Block a user