Expand range of allowed UTC offsets to 16 hours
It turns out that Alaska and The Philippines had historical offsets exceeding 15 hours, prior to day-transitions to bring their dates in sync with their respective sides of the international date line. Change-Id: I48fdf3aa6d8c0bacb368d08316733a10ee11a281 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>bb10
parent
455abef6c6
commit
cb54fa634a
|
|
@ -177,7 +177,7 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz);
|
|||
|
||||
A default UTC time zone backend is provided which is always available when
|
||||
feature \c timezone is enabled. This provides a set of generic Offset From
|
||||
UTC time zones in the range UTC-14:00 to UTC+14:00. These time zones can be
|
||||
UTC time zones in the range UTC-16:00 to UTC+16:00. These time zones can be
|
||||
created using either the standard ISO format names, such as "UTC+00:00", as
|
||||
listed by availableTimeZoneIds(), or using a name of similar form in
|
||||
combination with the number of offset seconds.
|
||||
|
|
@ -258,13 +258,27 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz);
|
|||
|
||||
This enumeration provides constants bounding the range of plausible timezone
|
||||
offsets from UTC, measured in seconds.
|
||||
Sane UTC offsets range from -14 to +14 hours.
|
||||
No known zone has offset > 12 hrs West of Greenwich (Baker Island, USA).
|
||||
No known zone has offset > 14 hrs East of Greenwich (Kiritimati, Christmas Island, Kiribati).
|
||||
|
||||
Sane modern zones' UTC offsets range from -14 to +12 hours.
|
||||
No known modern zone has offset > 12 hrs West of Greenwich (Baker Island, USA).
|
||||
No known modern zone has offset > 14 hrs East of Greenwich
|
||||
(Kiritimati, Christmas Island, Kiribati).
|
||||
Note that there are zones whose offsets differ by more than a day.
|
||||
|
||||
\value MinUtcOffsetSecs -14 * 3600,
|
||||
\value MaxUtcOffsetSecs +14 * 3600
|
||||
Historically, before 1867, when Russia sold Alaska to America, Alaska used the
|
||||
same date as Russia, so had offsets over 15 hours East of Greenwich.
|
||||
Earlier still, until 1844, The Philippines (then controlled by Spain) used the
|
||||
same date as Spain's American holdings, so had offsets close to 16 hours West
|
||||
of Greenwich.
|
||||
Each made its one-day transition to cross the international date line while
|
||||
using local solar mean time, before adopting a unified time-zone, so the
|
||||
offsets within their territories were variable.
|
||||
As a result, The Philippines might have exceeded 16 hours as offset at the
|
||||
extremities of its territory, but no modern zone's representative location was
|
||||
at such an extremity.
|
||||
|
||||
\value MinUtcOffsetSecs -16 * 3600,
|
||||
\value MaxUtcOffsetSecs +16 * 3600
|
||||
*/
|
||||
|
||||
#if QT_CONFIG(timezone)
|
||||
|
|
@ -468,7 +482,7 @@ QTimeZone::QTimeZone(const QByteArray &ianaId)
|
|||
/*!
|
||||
Creates a time zone instance with the given offset, \a offsetSeconds, from UTC.
|
||||
|
||||
The \a offsetSeconds from UTC must be in the range -14 hours to +14 hours
|
||||
The \a offsetSeconds from UTC must be in the range -16 hours to +16 hours
|
||||
otherwise an invalid time zone will be returned.
|
||||
|
||||
This constructor is only available when feature \c timezone is enabled. The
|
||||
|
|
@ -495,7 +509,7 @@ QTimeZone::QTimeZone(int offsetSeconds)
|
|||
|
||||
The \a ianaId must not be one of the available system IDs returned by
|
||||
availableTimeZoneIds(). The \a offsetSeconds from UTC must be in the range
|
||||
-14 hours to +14 hours.
|
||||
-16 hours to +16 hours.
|
||||
|
||||
If the custom time zone does not have a specific territory then set it to the
|
||||
default value of QLocale::AnyTerritory.
|
||||
|
|
@ -605,10 +619,10 @@ QTimeZone QTimeZone::asBackendZone() const
|
|||
Returns a time representation at a fixed \a offset, in seconds, ahead of
|
||||
UTC.
|
||||
|
||||
The \a offset from UTC must be in the range -14 hours to +14 hours otherwise an
|
||||
invalid time zone will be returned. The returned QTimeZone is a lightweight
|
||||
time representation, not a time zone (backed by system-supplied or standard
|
||||
data).
|
||||
The \a offset from UTC must be in the range -16 hours to +16 hours otherwise
|
||||
an invalid time zone will be returned. The returned QTimeZone is a
|
||||
lightweight time representation, not a time zone (backed by system-supplied
|
||||
or standard data).
|
||||
|
||||
If the offset is 0, the \l timeSpec() of the returned instance will be
|
||||
Qt::UTC. Otherwise, if \a offset is valid, timeSpec() is
|
||||
|
|
|
|||
|
|
@ -82,12 +82,14 @@ class Q_CORE_EXPORT QTimeZone
|
|||
QTimeZone(ShortData sd) : d(sd) {}
|
||||
|
||||
public:
|
||||
// Sane UTC offsets range from -14 to +14 hours:
|
||||
// Sane UTC offsets range from -16 to +16 hours:
|
||||
enum {
|
||||
// No known zone > 12 hrs West of Greenwich (Baker Island, USA)
|
||||
MinUtcOffsetSecs = -14 * 3600,
|
||||
// No known zone > 14 hrs East of Greenwich (Kiritimati, Christmas Island, Kiribati)
|
||||
MaxUtcOffsetSecs = +14 * 3600
|
||||
// No known modern zone > 12 hrs West of Greenwich.
|
||||
// Until 1844, Asia/Manila (in The Philippines) was at 15:56 West.
|
||||
MinUtcOffsetSecs = -16 * 3600,
|
||||
// No known modern zone > 14 hrs East of Greenwich.
|
||||
// Until 1867, America/Metlakatla (in Alaska) was at 15:13:42 East.
|
||||
MaxUtcOffsetSecs = +16 * 3600
|
||||
};
|
||||
|
||||
enum Initialization { LocalTime, UTC };
|
||||
|
|
|
|||
|
|
@ -182,28 +182,28 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
|
|||
|
||||
/*
|
||||
We need a UTC time at which to ask for the offset, in order to be able to
|
||||
add that offset to forLocalMSecs, to get the UTC time we
|
||||
need. Fortunately, no time-zone offset is more than 14 hours; and DST
|
||||
transitions happen (much) more than thirty-two hours apart. So sampling
|
||||
offset sixteen hours each side gives us information we can be sure
|
||||
add that offset to forLocalMSecs, to get the UTC time we need.
|
||||
Fortunately, all time-zone offsets have been less than 17 hours; and DST
|
||||
transitions happen (much) more than thirty-four hours apart. So sampling
|
||||
offset seventeen hours each side gives us information we can be sure
|
||||
brackets the correct time and at most one DST transition.
|
||||
*/
|
||||
std::integral_constant<qint64, 16 * 3600 * 1000> sixteenHoursInMSecs;
|
||||
static_assert(-sixteenHoursInMSecs / 1000 < QTimeZone::MinUtcOffsetSecs
|
||||
&& sixteenHoursInMSecs / 1000 > QTimeZone::MaxUtcOffsetSecs);
|
||||
std::integral_constant<qint64, 17 * 3600 * 1000> seventeenHoursInMSecs;
|
||||
static_assert(-seventeenHoursInMSecs / 1000 < QTimeZone::MinUtcOffsetSecs
|
||||
&& seventeenHoursInMSecs / 1000 > QTimeZone::MaxUtcOffsetSecs);
|
||||
qint64 millis;
|
||||
// Clip the bracketing times to the bounds of the supported range. Exclude
|
||||
// minMSecs(), because at least one backend (Windows) uses it for a
|
||||
// start-of-time fake transition, that we want previousTransition() to find.
|
||||
const qint64 recent =
|
||||
sub_overflow(forLocalMSecs, sixteenHoursInMSecs, &millis) || millis <= minMSecs()
|
||||
sub_overflow(forLocalMSecs, seventeenHoursInMSecs, &millis) || millis <= minMSecs()
|
||||
? minMSecs() + 1 : millis; // Necessarily <= forLocalMSecs + 2.
|
||||
// (Given that minMSecs() is std::numeric_limits<qint64>::min() + 1.)
|
||||
const qint64 imminent =
|
||||
add_overflow(forLocalMSecs, sixteenHoursInMSecs, &millis)
|
||||
add_overflow(forLocalMSecs, seventeenHoursInMSecs, &millis)
|
||||
? maxMSecs() : millis; // Necessarily >= forLocalMSecs
|
||||
// At most one of those was clipped to its boundary value:
|
||||
Q_ASSERT(recent < imminent && sixteenHoursInMSecs < imminent - recent + 2);
|
||||
Q_ASSERT(recent < imminent && seventeenHoursInMSecs < imminent - recent + 2);
|
||||
/*
|
||||
Offsets are Local - UTC, positive to the east of Greenwich, negative to
|
||||
the west; DST offset always exceeds standard offset, when DST applies.
|
||||
|
|
|
|||
|
|
@ -507,7 +507,7 @@ void tst_QTimeZone::asBackendZone()
|
|||
void tst_QTimeZone::systemZone()
|
||||
{
|
||||
const QTimeZone zone = QTimeZone::systemTimeZone();
|
||||
QVERIFY(zone.isValid());
|
||||
QVERIFY2(zone.isValid(), "Invalid system zone setting, tests are doomed.");
|
||||
QCOMPARE(zone.id(), QTimeZone::systemTimeZoneId());
|
||||
QCOMPARE(zone, QTimeZone(QTimeZone::systemTimeZoneId()));
|
||||
// Check it behaves the same as local-time:
|
||||
|
|
@ -1162,9 +1162,9 @@ void tst_QTimeZone::utcTest()
|
|||
QCOMPARE(tz.standardTimeOffset(now), 36000);
|
||||
QCOMPARE(tz.daylightTimeOffset(now), 0);
|
||||
|
||||
// Test invalid UTC offset, must be in range -14 to +14 hours
|
||||
int min = -14*60*60;
|
||||
int max = 14*60*60;
|
||||
// Test validity range of UTC offsets:
|
||||
int min = int(QTimeZone::MinUtcOffsetSecs);
|
||||
int max = int(QTimeZone::MaxUtcOffsetSecs);
|
||||
QCOMPARE(QTimeZone(min - 1).isValid(), false);
|
||||
QCOMPARE(QTimeZone(min).isValid(), true);
|
||||
QCOMPARE(QTimeZone(min + 1).isValid(), true);
|
||||
|
|
|
|||
Loading…
Reference in New Issue