File indexing completed on 2022-11-29 18:25:18

0001 /* This file is part of the KDE libraries
0002    Copyright (c) 2005-2007,2011-2012 David Jarvie <djarvie@kde.org>
0003 
0004    This library is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017    Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include "ktimezonestest.h"
0021 #include "ktimezonestest_p.h"
0022 
0023 #include <stdio.h>
0024 #include <QTest>
0025 #include <QDir>
0026 #include <QDate>
0027 #include <QDBusConnection>
0028 #include <QDBusMessage>
0029 #include <QTimer>
0030 #include <QSignalSpy>
0031 #include <config-date.h> // for HAVE_TM_GMTOFF
0032 #include "ksystemtimezone.h"
0033 #include "ktzfiletimezone.h"
0034 
0035 QTEST_MAIN(KTimeZonesTest)
0036 
0037 TimeZoneTestData s_testData;
0038 
0039 void KTimeZonesTest::initTestCase()
0040 {
0041     qputenv("TZ", "Europe/London");
0042     ::tzset();
0043 
0044     s_testData.setupTimeZoneTest(); // see ktimezonestest_p.h
0045     mDataDir = s_testData.dataDir();
0046 }
0047 
0048 void KTimeZonesTest::cleanupTestCase()
0049 {
0050     s_testData.cleanupTimeZoneTest();
0051 }
0052 
0053 ///////////////////
0054 // KTimeZones tests
0055 ///////////////////
0056 
0057 void KTimeZonesTest::ktimezones()
0058 {
0059     KTimeZones timezones;
0060     KTimeZone zone1("Zone1");
0061     QVERIFY(zone1.isValid());
0062     KTimeZone zone2("Zone2");
0063     QVERIFY(zone2.isValid());
0064     QVERIFY(timezones.add(zone1));
0065     QVERIFY(!timezones.add(zone1));
0066     QVERIFY(timezones.add(zone2));
0067     QCOMPARE(timezones.zones().count(), 2);
0068     KTimeZone tz = timezones.zone("Zone1");
0069     QVERIFY((tz == zone1));
0070     tz = timezones.zone("Zone99");
0071     QVERIFY(!tz.isValid());
0072     zone1 = timezones.remove(zone1);
0073     QVERIFY(zone1.isValid());
0074     QCOMPARE(timezones.zones().count(), 1);
0075     QVERIFY(!timezones.remove(zone1).isValid());
0076     QVERIFY(timezones.add(zone1));
0077     QVERIFY(timezones.remove("Zone1").isValid());
0078     QVERIFY(!timezones.remove("Zone1").isValid());
0079     QVERIFY(timezones.remove("Zone2").isValid());
0080     zone1 = KTimeZone("Zone10");
0081     QVERIFY(timezones.add(zone1));
0082     QCOMPARE(timezones.zones().count(), 1);
0083     timezones.clear();
0084     QCOMPARE(timezones.zones().count(), 0);
0085 }
0086 
0087 //////////////////////////
0088 // KTimeZone: ref counting
0089 //////////////////////////
0090 
0091 void KTimeZonesTest::refcount()
0092 {
0093     KTimeZone *zone1 = new KTimeZone("Zone1");
0094     QCOMPARE(zone1->name(), QString("Zone1"));
0095     KTimeZones timezones;
0096     timezones.add(*zone1);
0097     delete zone1;
0098     zone1 = nullptr;
0099     KTimeZone tz = timezones.zone("Zone1");
0100     QVERIFY(tz.isValid());
0101     QCOMPARE(tz.name(), QString("Zone1"));
0102     QCOMPARE(tz.type(), QByteArray("KTimeZone"));
0103 }
0104 
0105 ///////////////////
0106 // KTimeZone: UTC
0107 ///////////////////
0108 
0109 void KTimeZonesTest::utc()
0110 {
0111     KTimeZone utc = KTimeZone::utc();
0112     QVERIFY(utc.isValid());
0113     QCOMPARE(utc.name(), QString("UTC"));
0114     QCOMPARE(utc.offsetAtUtc(QDateTime(QDate(2005, 1, 1), QTime(), Qt::LocalTime)), 0);
0115     QCOMPARE(utc.offsetAtUtc(QDateTime(QDate(2005, 1, 1), QTime(), Qt::UTC)), 0);
0116     QCOMPARE(utc.offsetAtUtc(QDateTime(QDate(2005, 2, 1), QTime(), Qt::UTC)), 0);
0117     QCOMPARE(utc.offsetAtUtc(QDateTime(QDate(2005, 7, 1), QTime(), Qt::UTC)), 0);
0118 }
0119 
0120 /////////////////////////
0121 // KSystemTimeZones tests
0122 /////////////////////////
0123 
0124 // Defined in ksystemtimezone.cpp for our benefit
0125 KDELIBS4SUPPORT_EXPORT void k_system_time_zone_private_reset_config();
0126 
0127 void KTimeZonesTest::invalidLocal()
0128 {
0129     KTimeZone local;
0130     KConfig config("ktimezonedrc");
0131     KConfigGroup group(&config, "TimeZones");
0132 
0133     // Check that the originally set local local time zone is valid
0134     local = KSystemTimeZones::local();
0135     QVERIFY(local.isValid());
0136     QCOMPARE(local.name(), QString::fromLatin1("Europe/Paris"));
0137     QCOMPARE(local.type(), QByteArray("KTzfileTimeZone"));
0138 
0139     // Check invalid LocalZone
0140     group.writeEntry("LocalZone", QString::fromLatin1("Invalid/Zone"));
0141     config.sync();
0142     k_system_time_zone_private_reset_config();
0143 
0144     local = KSystemTimeZones::local();
0145     QVERIFY(local.isValid());
0146     QCOMPARE(local.name(), QString::fromLatin1("UTC"));
0147     QCOMPARE(local, KTimeZone::utc());
0148 
0149     // Check empty LocalZone
0150     group.deleteEntry("LocalZone");
0151     config.sync();
0152     k_system_time_zone_private_reset_config();
0153 
0154     local = KSystemTimeZones::local();
0155     QVERIFY(local.isValid());
0156     QCOMPARE(local.name(), QString::fromLatin1("UTC"));
0157     QCOMPARE(local, KTimeZone::utc());
0158 
0159     // Check invalid ZoneinfoDir
0160     group.writeEntry("ZoneinfoDir", QString::fromLatin1("/invalid/zoneinfo/dir"));
0161     group.writeEntry("Zonetab", QString("/invalid/zoneinfo/dir" + QString::fromLatin1("/zone.tab")));
0162     group.writeEntry("LocalZone", QString::fromLatin1("Europe/Paris"));
0163     config.sync();
0164     k_system_time_zone_private_reset_config();
0165 
0166     local = KSystemTimeZones::local();
0167     QVERIFY(local.isValid());
0168     QCOMPARE(local.name(), QString::fromLatin1("UTC"));
0169     QCOMPARE(local, KTimeZone::utc());
0170 
0171     // Check empty ZoneinfoDir
0172     group.deleteEntry("ZoneinfoDir");
0173     group.deleteEntry("Zonetab");
0174     config.sync();
0175     k_system_time_zone_private_reset_config();
0176 
0177     local = KSystemTimeZones::local();
0178     QVERIFY(local.isValid());
0179     QCOMPARE(local.name(), QString::fromLatin1("UTC"));
0180     QCOMPARE(local, KTimeZone::utc());
0181 
0182     // KTimeZonesTest::local() will restore config for us
0183 }
0184 
0185 void KTimeZonesTest::local()
0186 {
0187     // Restore the configuration after ::invalidLocal()
0188     KConfig config("ktimezonedrc");
0189     KConfigGroup group(&config, "TimeZones");
0190     group.writeEntry("ZoneinfoDir", mDataDir);
0191     group.writeEntry("Zonetab", QString(mDataDir + QString::fromLatin1("/zone.tab")));
0192     group.writeEntry("LocalZone", QString::fromLatin1("Europe/Paris"));
0193     config.sync();
0194     k_system_time_zone_private_reset_config();
0195 
0196     // Verify that we have a valid local time zone
0197     KTimeZone local = KSystemTimeZones::local();
0198     QVERIFY(local.isValid());
0199     QCOMPARE(local.name(), QString::fromLatin1("Europe/Paris"));
0200     QCOMPARE(local.type(), QByteArray("KTzfileTimeZone"));
0201 }
0202 
0203 void KTimeZonesTest::zone()
0204 {
0205     KTimeZone utc = KSystemTimeZones::zone("UTC");
0206     QVERIFY(utc.isValid());
0207     KTimeZone losAngeles = KSystemTimeZones::zone("America/Los_Angeles");
0208     QVERIFY(losAngeles.isValid());
0209     KTimeZone london = KSystemTimeZones::zone("Europe/London");
0210     QVERIFY(london.isValid());
0211     QCOMPARE(london.countryCode(), QString("GB"));
0212     QCOMPARE(london.latitude(), float(51 * 3600 + 28 * 60 + 30) / 3600.0f);
0213     QCOMPARE(london.longitude(), -float(0 * 3600 + 18 * 60 + 45) / 3600.0f);
0214     QCOMPARE(london.comment(), QString("Great Britain"));
0215     QCOMPARE(losAngeles.longitude(), -float(118 * 3600 + 14 * 60 + 34) / 3600.0f);
0216 }
0217 
0218 void KTimeZonesTest::zoneinfoDir()
0219 {
0220     QString zoneinfo = KSystemTimeZones::zoneinfoDir();
0221     QCOMPARE(zoneinfo, mDataDir);
0222 }
0223 
0224 void KTimeZonesTest::zonetabChange()
0225 {
0226     QEventLoop loop;
0227     QTimer timer;
0228     timer.setSingleShot(true);
0229     QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
0230     QSignalSpy timeoutSpy(&timer, SIGNAL(timeout()));
0231 
0232     QCOMPARE(KSystemTimeZones::zones().count(), 5);
0233     KTimeZone london = KSystemTimeZones::zone("Europe/London");
0234     QVERIFY(london.isValid());
0235     QCOMPARE(london.countryCode(), QString("GB"));
0236     QCOMPARE(london.latitude(), float(51 * 3600 + 28 * 60 + 30) / 3600.0f);
0237     QCOMPARE(london.longitude(), -float(0 * 3600 + 18 * 60 + 45) / 3600.0f);
0238     QCOMPARE(london.comment(), QString("Great Britain"));
0239     QVERIFY(!KSystemTimeZones::zone("Europe/Berlin").isValid());
0240     QVERIFY(KSystemTimeZones::zone("Europe/Paris").isValid());
0241     QVERIFY(KSystemTimeZones::zone("Europe/London").isValid());
0242     QVERIFY(KSystemTimeZones::zone("Africa/Cairo").isValid());
0243     QVERIFY(!KSystemTimeZones::zone("Asia/Dili").isValid());
0244     QVERIFY(KSystemTimeZones::zone("America/Los_Angeles").isValid());
0245 
0246     // Check that 'london' is automatically updated with the new zone.tab
0247     // contents, and that the new zones are added to KSystemTimeZones.
0248     s_testData.writeZoneTab(true);
0249     QDBusMessage message = QDBusMessage::createSignal("/Daemon", "org.kde.KTimeZoned", "timeZoneDatabaseUpdated");
0250     QList<QVariant> args;
0251     args += QString(mDataDir + QLatin1String("/zone.tab"));
0252     message.setArguments(args);
0253     QDBusConnection::sessionBus().send(message);
0254     timer.start(1000);
0255     loop.exec();
0256     QCOMPARE(KSystemTimeZones::zones().count(), 7);
0257     QVERIFY(london.isValid());
0258     QCOMPARE(london.countryCode(), QString("XX"));
0259     QCOMPARE(london.latitude(), -float(51 * 3600 + 28 * 60 + 30) / 3600.0f);
0260     QCOMPARE(london.longitude(), float(0 * 3600 + 18 * 60 + 45) / 3600.0f);
0261     QCOMPARE(london.comment(), QString("Greater Britain"));
0262     QCOMPARE(KSystemTimeZones::zone("Europe/London"), london);
0263     QVERIFY(KSystemTimeZones::zone("Europe/Berlin").isValid());
0264     QVERIFY(KSystemTimeZones::zone("Europe/Paris").isValid());
0265     QVERIFY(KSystemTimeZones::zone("Europe/London").isValid());
0266     QVERIFY(KSystemTimeZones::zone("Africa/Cairo").isValid());
0267     QVERIFY(KSystemTimeZones::zone("Africa/Johannesburg").isValid());
0268     QVERIFY(KSystemTimeZones::zone("Asia/Dili").isValid());
0269     QVERIFY(KSystemTimeZones::zone("America/Los_Angeles").isValid());
0270 
0271     // Check that 'london' is automatically updated with the new zone.tab
0272     // contents, and that the removed zones are deleted from KSystemTimeZones.
0273     s_testData.writeZoneTab(false);
0274     QDBusConnection::sessionBus().send(message);
0275     timer.start(1000);
0276     loop.exec();
0277     QCOMPARE(KSystemTimeZones::zones().count(), 5);
0278     QVERIFY(london.isValid());
0279     QCOMPARE(london.countryCode(), QString("GB"));
0280     QCOMPARE(london.latitude(), float(51 * 3600 + 28 * 60 + 30) / 3600.0f);
0281     QCOMPARE(london.longitude(), -float(0 * 3600 + 18 * 60 + 45) / 3600.0f);
0282     QCOMPARE(london.comment(), QString("Great Britain"));
0283     QCOMPARE(KSystemTimeZones::zone("Europe/London"), london);
0284     QVERIFY(!KSystemTimeZones::zone("Europe/Berlin").isValid());
0285     QVERIFY(KSystemTimeZones::zone("Europe/Paris").isValid());
0286     QVERIFY(KSystemTimeZones::zone("Europe/London").isValid());
0287     QVERIFY(KSystemTimeZones::zone("Africa/Cairo").isValid());
0288     QVERIFY(!KSystemTimeZones::zone("Asia/Dili").isValid());
0289     QVERIFY(KSystemTimeZones::zone("America/Los_Angeles").isValid());
0290 }
0291 
0292 ////////////////////////
0293 // KSystemTimeZone tests
0294 ////////////////////////
0295 
0296 void KTimeZonesTest::currentOffset()
0297 {
0298     QString tzfile = ':' + mDataDir + "/Europe/Paris";
0299     QByteArray originalZone = qgetenv("TZ");   // save the original local time zone
0300     qputenv("TZ", tzfile.toLatin1());
0301     ::tzset();
0302 
0303     // Find the current offset of a time zone
0304     time_t now = time(nullptr);
0305     tm *tnow = localtime(&now);
0306 #if HAVE_TM_GMTOFF
0307     int offset = tnow->tm_gmtoff;
0308 #else
0309     int offset = 0;
0310 #endif
0311     KTimeZone local = KSystemTimeZones::local();
0312     QVERIFY(local.isValid());
0313     QCOMPARE(local.currentOffset(Qt::UTC), offset);
0314 
0315     // Restore the original local time zone
0316     if (originalZone.isEmpty()) {
0317         ::unsetenv("TZ");
0318     } else {
0319         qputenv("TZ", originalZone);
0320     }
0321     ::tzset();
0322 }
0323 
0324 void KTimeZonesTest::offsetAtUtc()
0325 {
0326     // Find some offsets for Europe/London.
0327     KTimeZone losAngeles = KSystemTimeZones::zone("America/Los_Angeles");
0328     QVERIFY(losAngeles.isValid());
0329     KTimeZone london = KSystemTimeZones::zone("Europe/London");
0330     QVERIFY(london.isValid());
0331     QDateTime winter(QDate(2005, 1, 1), QTime(0, 0, 0), Qt::UTC);
0332     QDateTime summer(QDate(2005, 6, 1), QTime(0, 0, 0), Qt::UTC);
0333     QCOMPARE(london.offsetAtUtc(winter), 0);
0334     QCOMPARE(london.offsetAtUtc(summer), 3600);;
0335     QCOMPARE(losAngeles.offsetAtUtc(winter), -28800);
0336     QCOMPARE(losAngeles.offsetAtUtc(summer), -25200);;
0337 }
0338 
0339 void KTimeZonesTest::offsetAtZoneTime()
0340 {
0341     QDateTime Gmt1(QDate(2005, 3, 27), QTime(0, 30, 0), Qt::LocalTime);
0342     QDateTime GmtToBst1(QDate(2005, 3, 27), QTime(0, 59, 59), Qt::LocalTime);
0343     QDateTime GmtToBst2(QDate(2005, 3, 27), QTime(1, 0, 0), Qt::LocalTime);
0344     QDateTime GmtToBst3(QDate(2005, 3, 27), QTime(1, 59, 59), Qt::LocalTime);
0345     QDateTime GmtToBst4(QDate(2005, 3, 27), QTime(2, 0, 0), Qt::LocalTime);
0346     QDateTime Bst1(QDate(2005, 4, 27), QTime(2, 30, 0), Qt::LocalTime);
0347     QDateTime Bst2(QDate(2005, 10, 30), QTime(0, 30, 0), Qt::LocalTime);
0348     QDateTime BstToGmt1(QDate(2005, 10, 30), QTime(0, 59, 59), Qt::LocalTime);
0349     QDateTime BstToGmt2(QDate(2005, 10, 30), QTime(1, 0, 0), Qt::LocalTime);
0350     QDateTime BstToGmt3(QDate(2005, 10, 30), QTime(1, 59, 59), Qt::LocalTime);
0351     QDateTime BstToGmt4(QDate(2005, 10, 30), QTime(2, 0, 0), Qt::LocalTime);
0352     QDateTime Gmt2(QDate(2005, 10, 30), QTime(2, 30, 0), Qt::LocalTime);
0353     KTimeZone london = KSystemTimeZones::zone("Europe/London");
0354     QVERIFY(london.isValid());
0355     int offset2;
0356     QCOMPARE(london.offsetAtZoneTime(Gmt1, &offset2), 0);
0357     QCOMPARE(offset2, 0);
0358     QCOMPARE(london.offsetAtZoneTime(GmtToBst1, &offset2), 0);
0359     QCOMPARE(offset2, 0);
0360     QCOMPARE(london.offsetAtZoneTime(GmtToBst2, &offset2), KTimeZone::InvalidOffset);
0361     QCOMPARE(offset2, KTimeZone::InvalidOffset);
0362     QCOMPARE(london.offsetAtZoneTime(GmtToBst3, &offset2), KTimeZone::InvalidOffset);
0363     QCOMPARE(offset2, KTimeZone::InvalidOffset);
0364     QCOMPARE(london.offsetAtZoneTime(GmtToBst4, &offset2), 3600);
0365     QCOMPARE(offset2, 3600);
0366     QCOMPARE(london.offsetAtZoneTime(Bst1, &offset2), 3600);
0367     QCOMPARE(offset2, 3600);
0368     QCOMPARE(london.offsetAtZoneTime(Bst2, &offset2), 3600);
0369     QCOMPARE(offset2, 3600);
0370     QCOMPARE(london.offsetAtZoneTime(BstToGmt1, &offset2), 3600);
0371     QCOMPARE(offset2, 3600);
0372     QCOMPARE(london.offsetAtZoneTime(BstToGmt2, &offset2), 3600);
0373     QCOMPARE(offset2, 0);
0374     QCOMPARE(london.offsetAtZoneTime(BstToGmt3, &offset2), 3600);
0375     QCOMPARE(offset2, 0);
0376     QCOMPARE(london.offsetAtZoneTime(BstToGmt4, &offset2), 0);
0377     QCOMPARE(offset2, 0);
0378     QCOMPARE(london.offsetAtZoneTime(Gmt2, &offset2), 0);
0379     QCOMPARE(offset2, 0);
0380 
0381     KTimeZone johannesburg = KSystemTimeZones::zone("Africa/Johannesburg");
0382     QVERIFY(johannesburg.isValid());
0383     QDateTime recent(QDate(2013, 5, 10), QTime(13, 0, 0), Qt::LocalTime);
0384     QCOMPARE(johannesburg.offsetAtZoneTime(recent, &offset2), 7200);
0385     QCOMPARE(offset2, 7200);
0386 }
0387 
0388 void KTimeZonesTest::abbreviation()
0389 {
0390     // Fetch time zone abbreviations
0391     KTimeZone losAngeles = KSystemTimeZones::zone("America/Los_Angeles");
0392     QVERIFY(losAngeles.isValid());
0393     KTimeZone london = KSystemTimeZones::zone("Europe/London");
0394     QVERIFY(london.isValid());
0395     QDateTime winter(QDate(2005, 1, 1), QTime(0, 0, 0), Qt::UTC);
0396     QDateTime summer(QDate(2005, 6, 1), QTime(0, 0, 0), Qt::UTC);
0397     QString sResult = london.abbreviation(winter);
0398     QCOMPARE(london.abbreviation(winter), QByteArray("GMT"));
0399     QCOMPARE(london.abbreviation(summer), QByteArray("BST"));
0400     QCOMPARE(losAngeles.abbreviation(winter), QByteArray("PST"));
0401     QCOMPARE(losAngeles.abbreviation(summer), QByteArray("PDT"));
0402 }
0403 
0404 void KTimeZonesTest::timet()
0405 {
0406     QDateTime t1(QDate(1970, 1, 2), QTime(1, 30, 5), Qt::UTC);
0407     QDateTime t2(QDate(1969, 12, 30), QTime(22, 29, 55), Qt::UTC);
0408     time_t t1t = KTimeZone::toTime_t(t1);
0409     time_t t2t = KTimeZone::toTime_t(t2);
0410     QCOMPARE((int)t1t, 86400 + 3600 + 30 * 60 + 5);
0411     QCOMPARE((int)t2t, -(86400 + 3600 + 30 * 60 + 5));
0412     QCOMPARE(KTimeZone::fromTime_t(t1t), t1);
0413     QCOMPARE(KTimeZone::fromTime_t(t2t), t2);
0414 }
0415 
0416 void KTimeZonesTest::toUtc()
0417 {
0418     // Convert to UTC.
0419     KTimeZone losAngeles = KSystemTimeZones::zone("America/Los_Angeles");
0420     QVERIFY(losAngeles.isValid());
0421     KTimeZone london = KSystemTimeZones::zone("Europe/London");
0422     QVERIFY(london.isValid());
0423     QDateTime winter(QDate(2005, 1, 1), QTime(0, 0, 0), Qt::UTC);
0424     QDateTime summer(QDate(2005, 6, 1), QTime(0, 0, 0), Qt::UTC);
0425     QDateTime winterLocal = winter;
0426     winterLocal.setTimeSpec(Qt::LocalTime);
0427     QDateTime summerLocal = summer;
0428     summerLocal.setTimeSpec(Qt::LocalTime);
0429     QCOMPARE(london.toUtc(winterLocal), winter);
0430     QCOMPARE(london.toUtc(summerLocal), summer.addSecs(-3600));;
0431     QCOMPARE(losAngeles.toUtc(winterLocal), winter.addSecs(8 * 3600));
0432     QCOMPARE(losAngeles.toUtc(summerLocal), summer.addSecs(7 * 3600));
0433 }
0434 
0435 void KTimeZonesTest::toZoneTime()
0436 {
0437     // Convert from UTC.
0438     KTimeZone losAngeles = KSystemTimeZones::zone("America/Los_Angeles");
0439     QVERIFY(losAngeles.isValid());
0440     KTimeZone london = KSystemTimeZones::zone("Europe/London");
0441     QVERIFY(london.isValid());
0442     QDateTime winter(QDate(2005, 1, 1), QTime(0, 0, 0), Qt::UTC);
0443     QDateTime summer(QDate(2005, 6, 1), QTime(0, 0, 0), Qt::UTC);
0444     QDateTime winterLocal = winter;
0445     winterLocal.setTimeSpec(Qt::LocalTime);
0446     QDateTime summerLocal = summer;
0447     summerLocal.setTimeSpec(Qt::LocalTime);
0448     QCOMPARE(london.toZoneTime(winter), winterLocal);
0449     QCOMPARE(london.toZoneTime(summer), summerLocal.addSecs(3600));
0450     QCOMPARE(losAngeles.toZoneTime(winter), winterLocal.addSecs(-8 * 3600));
0451     QCOMPARE(losAngeles.toZoneTime(summer), summerLocal.addSecs(-7 * 3600));
0452 
0453     QDateTime prepre(QDate(2005, 10, 29), QTime(23, 59, 59), Qt::UTC); // before time shift (local time not repeated)
0454     QDateTime pre(QDate(2005, 10, 30), QTime(0, 0, 0), Qt::UTC); // before time shift (local time repeated afterwards)
0455     QDateTime before(QDate(2005, 10, 30), QTime(0, 59, 59), Qt::UTC); // before time shift (local time repeated afterwards)
0456     QDateTime at(QDate(2005, 10, 30), QTime(1, 0, 0), Qt::UTC); // at time shift (second occurrence of local time)
0457     QDateTime last(QDate(2005, 10, 30), QTime(1, 59, 59), Qt::UTC); // after time shift (second occurrence of local time)
0458     QDateTime after(QDate(2005, 10, 30), QTime(2, 0, 0), Qt::UTC); // after time shift (local time not repeated)
0459     bool second;
0460     QCOMPARE(london.toZoneTime(prepre, &second), QDateTime(QDate(2005, 10, 30), QTime(0, 59, 59), Qt::LocalTime));
0461     QVERIFY(!second);
0462     QCOMPARE(london.toZoneTime(pre, &second), QDateTime(QDate(2005, 10, 30), QTime(1, 0, 0), Qt::LocalTime));
0463     QVERIFY(!second);
0464     QCOMPARE(london.toZoneTime(before, &second), QDateTime(QDate(2005, 10, 30), QTime(1, 59, 59), Qt::LocalTime));
0465     QVERIFY(!second);
0466     QCOMPARE(london.toZoneTime(at, &second), QDateTime(QDate(2005, 10, 30), QTime(1, 0, 0), Qt::LocalTime));
0467     QVERIFY(second);
0468     QCOMPARE(london.toZoneTime(last, &second), QDateTime(QDate(2005, 10, 30), QTime(1, 59, 59), Qt::LocalTime));
0469     QVERIFY(second);
0470     QCOMPARE(london.toZoneTime(after, &second), QDateTime(QDate(2005, 10, 30), QTime(2, 0, 0), Qt::LocalTime));
0471     QVERIFY(!second);
0472 }
0473 
0474 void KTimeZonesTest::convert()
0475 {
0476     // Try time zone conversions.
0477     KTimeZone losAngeles = KSystemTimeZones::zone("America/Los_Angeles");
0478     QVERIFY(losAngeles.isValid());
0479     KTimeZone london = KSystemTimeZones::zone("Europe/London");
0480     QVERIFY(london.isValid());
0481     QDateTime bstBeforePdt(QDate(2005, 3, 28), QTime(0, 0, 0), Qt::LocalTime);
0482     QDateTime bstAfterPdt(QDate(2005, 5, 1), QTime(0, 0, 0), Qt::LocalTime);
0483     QDateTime gmtBeforePst(QDate(2005, 10, 30), QTime(4, 0, 0), Qt::LocalTime);
0484     QDateTime gmtAfterPst(QDate(2005, 12, 1), QTime(0, 0, 0), Qt::LocalTime);
0485     QDateTime bstBeforePdtResult(QDate(2005, 3, 27), QTime(15, 0, 0), Qt::LocalTime);
0486     QDateTime bstAfterPdtResult(QDate(2005, 4, 30), QTime(16, 0, 0), Qt::LocalTime);
0487     QDateTime gmtBeforePstResult(QDate(2005, 10, 29), QTime(21, 0, 0), Qt::LocalTime);
0488     QDateTime gmtAfterPstResult(QDate(2005, 11, 30), QTime(16, 0, 0), Qt::LocalTime);
0489 
0490     QCOMPARE(london.convert(losAngeles, bstBeforePdt), bstBeforePdtResult);
0491     QCOMPARE(london.convert(losAngeles, bstAfterPdt), bstAfterPdtResult);
0492     QCOMPARE(london.convert(losAngeles, gmtBeforePst), gmtBeforePstResult);
0493     QCOMPARE(london.convert(losAngeles, gmtAfterPst), gmtAfterPstResult);
0494     QCOMPARE(losAngeles.convert(losAngeles, bstBeforePdtResult), bstBeforePdtResult);
0495 }
0496 
0497 ////////////////////////
0498 // KTzfileTimeZone tests
0499 // Plus KSystemTimeZones::readZone() tests
0500 ////////////////////////
0501 
0502 void KTimeZonesTest::tzfile()
0503 {
0504     QDateTime winter(QDate(2005, 1, 1), QTime(0, 0, 0), Qt::UTC);
0505     QString zoneinfo = KSystemTimeZones::zoneinfoDir();
0506     QVERIFY(!zoneinfo.isEmpty());
0507     KTzfileTimeZoneSource tzsource(zoneinfo);
0508     KTimeZone *tzcairo = new KTzfileTimeZone(&tzsource, "Africa/Cairo");
0509     delete tzcairo;
0510     tzcairo = new KTzfileTimeZone(&tzsource, "Africa/Cairo");
0511     QCOMPARE(tzcairo->offsetAtUtc(winter), 7200);
0512     delete tzcairo;
0513     KTimeZone *johannesburg = new KTzfileTimeZone(&tzsource, "Africa/Johannesburg");
0514     delete johannesburg;
0515     johannesburg = new KTzfileTimeZone(&tzsource, "Africa/Johannesburg");
0516     QCOMPARE(johannesburg->offsetAtUtc(winter), 7200);
0517     delete johannesburg;
0518 }
0519 
0520 void KTimeZonesTest::tzfileDstShifts()
0521 {
0522     // Check time zone conversions against zdump output for zone
0523     KTzfileTimeZoneSource tzsource(KSystemTimeZones::zoneinfoDir());
0524     KTimeZone berlin = KTzfileTimeZone(&tzsource, "Europe/Berlin");
0525     KTimeZone losAngeles = KTzfileTimeZone(&tzsource, "America/Los_Angeles");
0526     KTimeZone tz = berlin;
0527     for (int n = 0; n < 2; ++n, tz = losAngeles) {
0528         qDebug() << tz.name();
0529         QVERIFY(tz.isValid());
0530         QCOMPARE(tz.type(), QByteArray("KTzfileTimeZone"));
0531         QFile file(QFINDTESTDATA(tz.name().remove(QRegExp("^.+/")) + QLatin1String(".zdump")));
0532         QVERIFY(file.open(QIODevice::ReadOnly));
0533         QTextStream in(&file);
0534         QString line;
0535         while (!(line = in.readLine()).isNull()) {
0536             QStringList parts = line.split(" ", QString::SkipEmptyParts);
0537             QCOMPARE(parts[6], QString::fromLatin1("UTC"));
0538             QCOMPARE(parts[7], QString::fromLatin1("="));
0539             QCOMPARE(parts[14].left(6), QString::fromLatin1("isdst="));
0540             QCOMPARE(parts[15].left(7), QString::fromLatin1("gmtoff="));
0541             QDateTime utc = QDateTime::fromString(static_cast<QStringList>(parts.mid(1, 5)).join(" "));
0542             utc.setTimeSpec(Qt::UTC);
0543             QDateTime local = QDateTime::fromString(static_cast<QStringList>(parts.mid(8, 5)).join(" "));
0544             local.setTimeSpec(Qt::LocalTime);
0545             QCOMPARE(tz.toZoneTime(utc), local);
0546             QCOMPARE(parts[13], QString::fromLatin1(tz.abbreviation(utc)));
0547             bool dst = (parts[14].right(1) != "0");
0548             QCOMPARE(tz.isDstAtUtc(utc), dst);
0549             QCOMPARE(parts[15].mid(7).toInt(), tz.offsetAtUtc(utc));
0550         }
0551         file.close();
0552     }
0553 }
0554 
0555 void KTimeZonesTest::tzfileToZoneTime()
0556 {
0557     // Convert from UTC.
0558     KTzfileTimeZoneSource tzsource(KSystemTimeZones::zoneinfoDir());
0559     KTimeZone london = KTzfileTimeZone(&tzsource, "Europe/London");
0560     QVERIFY(london.isValid());
0561     QCOMPARE(london.type(), QByteArray("KTzfileTimeZone"));
0562     QDateTime prepre(QDate(2005, 10, 29), QTime(23, 59, 59), Qt::UTC); // before time shift (local time not repeated)
0563     QDateTime pre(QDate(2005, 10, 30), QTime(0, 0, 0), Qt::UTC); // before time shift (local time repeated afterwards)
0564     QDateTime before(QDate(2005, 10, 30), QTime(0, 59, 59), Qt::UTC); // before time shift (local time repeated afterwards)
0565     QDateTime at(QDate(2005, 10, 30), QTime(1, 0, 0), Qt::UTC); // at time shift (second occurrence of local time)
0566     QDateTime last(QDate(2005, 10, 30), QTime(1, 59, 59), Qt::UTC); // after time shift (second occurrence of local time)
0567     QDateTime after(QDate(2005, 10, 30), QTime(2, 0, 0), Qt::UTC); // after time shift (local time not repeated)
0568     bool second;
0569     QCOMPARE(london.toZoneTime(prepre, &second), QDateTime(QDate(2005, 10, 30), QTime(0, 59, 59), Qt::LocalTime));
0570     QVERIFY(!second);
0571     QCOMPARE(london.toZoneTime(pre, &second), QDateTime(QDate(2005, 10, 30), QTime(1, 0, 0), Qt::LocalTime));
0572     QVERIFY(!second);
0573     QCOMPARE(london.toZoneTime(before, &second), QDateTime(QDate(2005, 10, 30), QTime(1, 59, 59), Qt::LocalTime));
0574     QVERIFY(!second);
0575     QCOMPARE(london.toZoneTime(at, &second), QDateTime(QDate(2005, 10, 30), QTime(1, 0, 0), Qt::LocalTime));
0576     QVERIFY(second);
0577     QCOMPARE(london.toZoneTime(last, &second), QDateTime(QDate(2005, 10, 30), QTime(1, 59, 59), Qt::LocalTime));
0578     QVERIFY(second);
0579     QCOMPARE(london.toZoneTime(after, &second), QDateTime(QDate(2005, 10, 30), QTime(2, 0, 0), Qt::LocalTime));
0580     QVERIFY(!second);
0581 
0582     KTimeZone sysLondon = KSystemTimeZones::readZone("Europe/London");
0583     QVERIFY(sysLondon.isValid());
0584     QCOMPARE(sysLondon.toZoneTime(prepre, &second), QDateTime(QDate(2005, 10, 30), QTime(0, 59, 59), Qt::LocalTime));
0585     QVERIFY(!second);
0586     QCOMPARE(sysLondon.toZoneTime(pre, &second), QDateTime(QDate(2005, 10, 30), QTime(1, 0, 0), Qt::LocalTime));
0587     QVERIFY(!second);
0588     QCOMPARE(sysLondon.toZoneTime(before, &second), QDateTime(QDate(2005, 10, 30), QTime(1, 59, 59), Qt::LocalTime));
0589     QVERIFY(!second);
0590     QCOMPARE(sysLondon.toZoneTime(at, &second), QDateTime(QDate(2005, 10, 30), QTime(1, 0, 0), Qt::LocalTime));
0591     QVERIFY(second);
0592     QCOMPARE(sysLondon.toZoneTime(last, &second), QDateTime(QDate(2005, 10, 30), QTime(1, 59, 59), Qt::LocalTime));
0593     QVERIFY(second);
0594     QCOMPARE(sysLondon.toZoneTime(after, &second), QDateTime(QDate(2005, 10, 30), QTime(2, 0, 0), Qt::LocalTime));
0595     QVERIFY(!second);
0596 }
0597 
0598 void KTimeZonesTest::tzfileOffsetAtUtc()
0599 {
0600     QDateTime a3Gmt(QDate(2004, 12, 27), QTime(0, 30, 0), Qt::UTC);
0601     QDateTime a2Gmt(QDate(2005, 2, 27), QTime(0, 30, 0), Qt::UTC);
0602     QDateTime aGmt(QDate(2005, 3, 27), QTime(0, 30, 0), Qt::UTC);
0603     QDateTime aBst(QDate(2005, 3, 27), QTime(1, 30, 0), Qt::UTC);
0604     QDateTime a2Bst(QDate(2005, 7, 27), QTime(2, 30, 0), Qt::UTC);
0605     QDateTime bBst(QDate(2005, 10, 29), QTime(23, 30, 0), Qt::UTC);
0606     QDateTime bBstBeforeGmt(QDate(2005, 10, 30), QTime(0, 30, 0), Qt::UTC);
0607     QDateTime bGmt(QDate(2005, 10, 30), QTime(2, 30, 0), Qt::UTC);
0608     KTzfileTimeZoneSource tzsource(KSystemTimeZones::zoneinfoDir());
0609     KTimeZone london = KTzfileTimeZone(&tzsource, "Europe/London");
0610     QVERIFY(london.isValid());
0611     QCOMPARE(london.type(), QByteArray("KTzfileTimeZone"));
0612     QCOMPARE(london.offsetAtUtc(a3Gmt), 0);
0613     QCOMPARE(london.offsetAtUtc(a2Gmt), 0);             // uses cache
0614     QCOMPARE(london.offsetAtUtc(aGmt), 0);              // uses cache
0615     QCOMPARE(london.offsetAtUtc(aBst), 3600);
0616     QCOMPARE(london.offsetAtUtc(a2Bst), 3600);          // uses cache
0617     QCOMPARE(london.offsetAtUtc(bBst), 3600);           // uses cache
0618     QCOMPARE(london.offsetAtUtc(bBstBeforeGmt), 3600);  // uses cache
0619     QCOMPARE(london.offsetAtUtc(bGmt), 0);
0620 
0621     QDateTime recent(QDate(2013, 5, 10), QTime(13, 0, 0), Qt::UTC);
0622     KTimeZone johannesburg = KTzfileTimeZone(&tzsource, "Africa/Johannesburg");
0623     QVERIFY(johannesburg.isValid());
0624     QCOMPARE(johannesburg.type(), QByteArray("KTzfileTimeZone"));
0625     QCOMPARE(johannesburg.offsetAtUtc(recent), 7200);
0626 }
0627 
0628 void KTimeZonesTest::tzfileOffsetAtZoneTime()
0629 {
0630     QDateTime Gmt0(QDate(2005, 2, 27), QTime(0, 30, 0), Qt::LocalTime);
0631     QDateTime Gmt1(QDate(2005, 3, 27), QTime(0, 30, 0), Qt::LocalTime);
0632     QDateTime GmtToBst1(QDate(2005, 3, 27), QTime(0, 59, 59), Qt::LocalTime);
0633     QDateTime GmtToBst2(QDate(2005, 3, 27), QTime(1, 0, 0), Qt::LocalTime);
0634     QDateTime GmtToBst3(QDate(2005, 3, 27), QTime(1, 59, 59), Qt::LocalTime);
0635     QDateTime GmtToBst4(QDate(2005, 3, 27), QTime(2, 0, 0), Qt::LocalTime);
0636     QDateTime Bst1(QDate(2005, 4, 27), QTime(2, 30, 0), Qt::LocalTime);
0637     QDateTime Bst2(QDate(2005, 10, 30), QTime(0, 30, 0), Qt::LocalTime);
0638     QDateTime BstToGmt1(QDate(2005, 10, 30), QTime(0, 59, 59), Qt::LocalTime);
0639     QDateTime BstToGmt2(QDate(2005, 10, 30), QTime(1, 0, 0), Qt::LocalTime);
0640     QDateTime BstToGmt3(QDate(2005, 10, 30), QTime(1, 59, 59), Qt::LocalTime);
0641     QDateTime BstToGmt4(QDate(2005, 10, 30), QTime(2, 0, 0), Qt::LocalTime);
0642     QDateTime Gmt2(QDate(2005, 10, 30), QTime(2, 30, 0), Qt::LocalTime);
0643     KTzfileTimeZoneSource tzsource(KSystemTimeZones::zoneinfoDir());
0644     KTimeZone london = KTzfileTimeZone(&tzsource, "Europe/London");
0645     QVERIFY(london.isValid());
0646     int offset2;
0647     QCOMPARE(london.offsetAtZoneTime(Gmt0, &offset2), 0);
0648     QCOMPARE(offset2, 0);
0649     QCOMPARE(london.offsetAtZoneTime(Gmt1, &offset2), 0);          // uses cache
0650     QCOMPARE(offset2, 0);
0651     QCOMPARE(london.offsetAtZoneTime(GmtToBst1, &offset2), 0);     // uses cache
0652     QCOMPARE(offset2, 0);
0653     QCOMPARE(london.offsetAtZoneTime(GmtToBst2, &offset2), KTimeZone::InvalidOffset);
0654     QCOMPARE(offset2, KTimeZone::InvalidOffset);
0655     QCOMPARE(london.offsetAtZoneTime(GmtToBst3, &offset2), KTimeZone::InvalidOffset);
0656     QCOMPARE(offset2, KTimeZone::InvalidOffset);
0657     QCOMPARE(london.offsetAtZoneTime(GmtToBst4, &offset2), 3600);
0658     QCOMPARE(offset2, 3600);
0659     QCOMPARE(london.offsetAtZoneTime(Bst1, &offset2), 3600);
0660     QCOMPARE(offset2, 3600);
0661     QCOMPARE(london.offsetAtZoneTime(Bst2, &offset2), 3600);       // uses cache
0662     QCOMPARE(offset2, 3600);
0663     QCOMPARE(london.offsetAtZoneTime(BstToGmt1, &offset2), 3600);  // uses cache
0664     QCOMPARE(offset2, 3600);
0665     QCOMPARE(london.offsetAtZoneTime(BstToGmt2, &offset2), 3600);
0666     QCOMPARE(offset2, 0);
0667     QCOMPARE(london.offsetAtZoneTime(BstToGmt3, &offset2), 3600);
0668     QCOMPARE(offset2, 0);
0669     QCOMPARE(london.offsetAtZoneTime(BstToGmt4, &offset2), 0);
0670     QCOMPARE(offset2, 0);
0671     QCOMPARE(london.offsetAtZoneTime(Gmt2, &offset2), 0);          // uses cache
0672     QCOMPARE(offset2, 0);
0673 
0674     KTimeZone sysLondon = KSystemTimeZones::readZone("Europe/London");
0675     QVERIFY(sysLondon.isValid());
0676     QCOMPARE(sysLondon.offsetAtZoneTime(Gmt0, &offset2), 0);
0677     QCOMPARE(offset2, 0);
0678     QCOMPARE(sysLondon.offsetAtZoneTime(Gmt1, &offset2), 0);          // uses cache
0679     QCOMPARE(offset2, 0);
0680     QCOMPARE(sysLondon.offsetAtZoneTime(GmtToBst1, &offset2), 0);     // uses cache
0681     QCOMPARE(offset2, 0);
0682     QCOMPARE(sysLondon.offsetAtZoneTime(GmtToBst2, &offset2), KTimeZone::InvalidOffset);
0683     QCOMPARE(offset2, KTimeZone::InvalidOffset);
0684     QCOMPARE(sysLondon.offsetAtZoneTime(GmtToBst3, &offset2), KTimeZone::InvalidOffset);
0685     QCOMPARE(offset2, KTimeZone::InvalidOffset);
0686     QCOMPARE(sysLondon.offsetAtZoneTime(GmtToBst4, &offset2), 3600);
0687     QCOMPARE(offset2, 3600);
0688     QCOMPARE(sysLondon.offsetAtZoneTime(Bst1, &offset2), 3600);
0689     QCOMPARE(offset2, 3600);
0690     QCOMPARE(sysLondon.offsetAtZoneTime(Bst2, &offset2), 3600);       // uses cache
0691     QCOMPARE(offset2, 3600);
0692     QCOMPARE(sysLondon.offsetAtZoneTime(BstToGmt1, &offset2), 3600);  // uses cache
0693     QCOMPARE(offset2, 3600);
0694     QCOMPARE(sysLondon.offsetAtZoneTime(BstToGmt2, &offset2), 3600);
0695     QCOMPARE(offset2, 0);
0696     QCOMPARE(sysLondon.offsetAtZoneTime(BstToGmt3, &offset2), 3600);
0697     QCOMPARE(offset2, 0);
0698     QCOMPARE(sysLondon.offsetAtZoneTime(BstToGmt4, &offset2), 0);
0699     QCOMPARE(offset2, 0);
0700     QCOMPARE(sysLondon.offsetAtZoneTime(Gmt2, &offset2), 0);          // uses cache
0701     QCOMPARE(offset2, 0);
0702 
0703     KTimeZone johannesburg = KTzfileTimeZone(&tzsource, "Africa/Johannesburg");
0704     QVERIFY(johannesburg.isValid());
0705     QCOMPARE(johannesburg.type(), QByteArray("KTzfileTimeZone"));
0706     QDateTime recent(QDate(2013,5,10), QTime(13,0,0), Qt::LocalTime);
0707     QCOMPARE(johannesburg.offsetAtZoneTime(recent, &offset2), 7200);
0708     QCOMPARE(offset2, 7200);
0709 }
0710 
0711 void KTimeZonesTest::tzfileUtcOffsets()
0712 {
0713     KTzfileTimeZoneSource tzsource(KSystemTimeZones::zoneinfoDir());
0714     KTimeZone london = KTzfileTimeZone(&tzsource, "Europe/London");
0715     QVERIFY(london.isValid());
0716     QList<int> offsets = london.utcOffsets();
0717     QCOMPARE(offsets.count(), 3);
0718     QCOMPARE(offsets[0], 0);    // GMT
0719     QCOMPARE(offsets[1], 3600); // BST
0720     QCOMPARE(offsets[2], 7200); // DST
0721 
0722     KTimeZone sysLondon = KSystemTimeZones::readZone("Europe/London");
0723     QVERIFY(sysLondon.isValid());
0724     offsets = sysLondon.utcOffsets();
0725     QCOMPARE(offsets.count(), 3);
0726     QCOMPARE(offsets[0], 0);    // GMT
0727     QCOMPARE(offsets[1], 3600); // BST
0728     QCOMPARE(offsets[2], 7200); // DST
0729 }
0730 
0731 void KTimeZonesTest::tzfileAbbreviation()
0732 {
0733     KTzfileTimeZoneSource tzsource(KSystemTimeZones::zoneinfoDir());
0734     KTimeZone london = KTzfileTimeZone(&tzsource, "Europe/London");
0735     QVERIFY(london.isValid());
0736     QDateTime winter(QDate(2005, 1, 1), QTime(0, 0, 0), Qt::UTC);
0737     QDateTime summer(QDate(2005, 6, 1), QTime(0, 0, 0), Qt::UTC);
0738     QDateTime standard(QDate(1970, 4, 30), QTime(12, 45, 16, 25), Qt::UTC);
0739     QString sResult = london.abbreviation(winter);
0740     QCOMPARE(london.abbreviation(winter), QByteArray("GMT"));
0741     QCOMPARE(london.abbreviation(summer), QByteArray("BST"));
0742     QCOMPARE(london.abbreviation(standard), QByteArray("BST"));
0743 
0744     KTimeZone sysLondon = KSystemTimeZones::readZone("Europe/London");
0745     QVERIFY(sysLondon.isValid());
0746     sResult = sysLondon.abbreviation(winter);
0747     QCOMPARE(sysLondon.abbreviation(winter), QByteArray("GMT"));
0748     QCOMPARE(sysLondon.abbreviation(summer), QByteArray("BST"));
0749     QCOMPARE(sysLondon.abbreviation(standard), QByteArray("BST"));
0750 }
0751 
0752 void KTimeZonesTest::tzfileTransitions()
0753 {
0754     KTzfileTimeZoneSource tzsource(KSystemTimeZones::zoneinfoDir());
0755     KTimeZone london = KTzfileTimeZone(&tzsource, "Europe/London");
0756     QVERIFY(london.isValid());
0757     QList<KTimeZone::Transition> all = london.transitions();
0758     QVERIFY(!all.isEmpty());
0759     QDateTime jan2003(QDate(2003, 1, 1), QTime(0, 0, 0), Qt::UTC);
0760     QDateTime jan2006(QDate(2006, 1, 1), QTime(0, 0, 0), Qt::UTC);
0761     int index2006 = london.transitionIndex(jan2006);
0762     if (index2006 >= 0) {
0763         QVERIFY(all[index2006].time() <= jan2006);
0764         QList<KTimeZone::Transition> some = london.transitions(QDateTime(), jan2006);
0765         QList<KTimeZone::Transition> check = all.mid(0, index2006 + 1);
0766         QCOMPARE(some.count(), check.count());
0767         for (int i = 0;  i < some.count();  ++i) {
0768             QCOMPARE(some[i].time(), check[i].time());
0769             QCOMPARE(some[i].phase(), check[i].phase());
0770         }
0771         if (all[index2006].time() < jan2006  &&  ++index2006 < all.count()) {
0772             QVERIFY(all[index2006].time() > jan2006);
0773         }
0774         some = london.transitions(jan2006);
0775         check = all.mid(index2006);
0776         for (int i = 0;  i < some.count();  ++i) {
0777             QCOMPARE(some[i].time(), check[i].time());
0778             QCOMPARE(some[i].phase(), check[i].phase());
0779         }
0780     }
0781     index2006 = london.transitionIndex(jan2006);
0782     int index2003 = london.transitionIndex(jan2003);
0783     if (index2003 >= 0) {
0784         QVERIFY(all[index2003].time() <= jan2003);
0785         if (all[index2003].time() < jan2003  &&  ++index2003 < all.count()) {
0786             QVERIFY(all[index2003].time() > jan2003);
0787         }
0788         QList<KTimeZone::Transition> some = london.transitions(jan2003, jan2006);
0789         QList<KTimeZone::Transition> check = all.mid(index2003, index2006 - index2003 + 1);
0790         QCOMPARE(some.count(), check.count());
0791         for (int i = 0;  i < some.count();  ++i) {
0792 
0793             QCOMPARE(some[i].time(), check[i].time());
0794             QCOMPARE(some[i].phase(), check[i].phase());
0795         }
0796     }
0797 }
0798