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>
|
||||
#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
|
||||
|
||||
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
|
||||
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
|
||||
the preceding second; if it gives us -2, then the -1 we originally saw is not
|
||||
an error (or was an error, but needn't have been). We can then synthesize a
|
||||
corrected value for local using the -2 result.
|
||||
1970. When we do know the offset (a glibc extension supplies it as a member
|
||||
of struct tm), we can determine whether we're on the last second of the day,
|
||||
refining that check. That makes for a cheap pre-test; if it holds, we can ask
|
||||
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()
|
||||
{
|
||||
@ -91,6 +98,12 @@ inline bool MkTimeResult::meansEnd1969()
|
||||
return false;
|
||||
#else
|
||||
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_mon < 11 || local.tm_mday < 31
|
||||
: 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);
|
||||
if (!use.good)
|
||||
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);
|
||||
}
|
||||
|
||||
@ -572,12 +588,14 @@ QDateTimePrivate::ZoneState mapLocalTime(qint64 local, QDateTimePrivate::Dayligh
|
||||
Q_ASSERT(local < 0 ? (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:
|
||||
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);
|
||||
if (Q_UNLIKELY(!jd))
|
||||
return {local, offset, dst, false};
|
||||
@ -593,6 +611,7 @@ QDateTimePrivate::ZoneState mapLocalTime(qint64 local, QDateTimePrivate::Dayligh
|
||||
|
||||
// Use revised localSecs to refine offset:
|
||||
offset = localSecs - use.utcSecs;
|
||||
#endif // HAVE_TM_GMTOFF
|
||||
|
||||
// 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user