summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/time/qtimezoneprivate_tz.cpp19
-rw-r--r--tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp12
2 files changed, 23 insertions, 8 deletions
diff --git a/src/corelib/time/qtimezoneprivate_tz.cpp b/src/corelib/time/qtimezoneprivate_tz.cpp
index 2955a5c957..8f02e3a7d6 100644
--- a/src/corelib/time/qtimezoneprivate_tz.cpp
+++ b/src/corelib/time/qtimezoneprivate_tz.cpp
@@ -393,19 +393,22 @@ static QDate calculatePosixDate(const QByteArray &dateRule, int year)
return calculateDowDate(year, month, dow, week);
}
} else if (dateRule.at(0) == 'J') {
- // Day of Year ignores Feb 29
+ // Day of Year 1...365, ignores Feb 29.
+ // So March always starts on day 60.
int doy = dateRule.mid(1).toInt(&ok);
if (ok && doy > 0 && doy < 366) {
- QDate date = QDate(year, 1, 1).addDays(doy - 1);
- if (QDate::isLeapYear(date.year()) && date.month() > 2)
- date = date.addDays(-1);
- return date;
+ // Subtract 1 because we're adding days *after* the first of
+ // January, unless it's after February in a leap year, when the leap
+ // day cancels that out:
+ if (!QDate::isLeapYear(year) || doy < 60)
+ --doy;
+ return QDate(year, 1, 1).addDays(doy);
}
} else {
- // Day of Year includes Feb 29
+ // Day of Year 0...365, includes Feb 29
int doy = dateRule.toInt(&ok);
- if (ok && doy > 0 && doy <= 366)
- return QDate(year, 1, 1).addDays(doy - 1);
+ if (ok && doy >= 0 && doy < 366)
+ return QDate(year, 1, 1).addDays(doy);
}
return QDate();
}
diff --git a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp
index 2e197cca4a..19b638cce7 100644
--- a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp
+++ b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp
@@ -1141,6 +1141,18 @@ void tst_QTimeZone::tzTest()
QTzTimeZonePrivate tzposix("MET-1METDST-2,M3.5.0/02:00:00,M10.5.0/03:00:00");
QVERIFY(tzposix.isValid());
+ // RHEL has been seen with this as Africa/Casablanca's POSIX rule:
+ QTzTimeZonePrivate permaDst("<+00>0<+01>,0/0,J365/25");
+ const QTimeZone utcP1("UTC+01:00"); // Should always have same offset as permaDst
+ QVERIFY(permaDst.isValid());
+ QVERIFY(permaDst.hasDaylightTime());
+ QVERIFY(permaDst.isDaylightTime(QDate(2020, 1, 1).startOfDay(utcP1).toMSecsSinceEpoch()));
+ QVERIFY(permaDst.isDaylightTime(QDate(2020, 12, 31).endOfDay(utcP1).toMSecsSinceEpoch()));
+ // Note that the final /25 could be misunderstood as putting a fall-back at
+ // 1am on the next year's Jan 1st; check we don't do that:
+ QVERIFY(permaDst.isDaylightTime(
+ QDateTime(QDate(2020, 1, 1), QTime(1, 30), utcP1).toMSecsSinceEpoch()));
+
QTimeZone tzBrazil("BRT+3"); // parts of Northern Brazil, as a POSIX rule
QVERIFY(tzBrazil.isValid());
QCOMPARE(tzBrazil.offsetFromUtc(QDateTime(QDate(1111, 11, 11).startOfDay())), -10800);