00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "ksystemtimezone.moc"
00026
00027 #include <config.h>
00028
00029 #ifdef HAVE_SYS_TIME_H
00030 #include <sys/time.h>
00031 #endif
00032 #ifdef HAVE_TIME_H
00033 #include <time.h>
00034 #endif
00035 #include <climits>
00036 #include <cstdlib>
00037
00038 #include <QtCore/QCoreApplication>
00039 #include <QtCore/QFile>
00040 #include <QtCore/QFileInfo>
00041 #include <QtCore/QDir>
00042 #include <QtCore/QRegExp>
00043 #include <QtCore/QStringList>
00044 #include <QtCore/QTextStream>
00045 #include <QtDBus/QDBusConnection>
00046 #include <QtDBus/QDBusInterface>
00047 #include <QtDBus/QDBusReply>
00048
00049 #include <kglobal.h>
00050 #include <klocale.h>
00051 #include <kcodecs.h>
00052 #include <kstringhandler.h>
00053 #include <ktemporaryfile.h>
00054 #include <kdebug.h>
00055 #include <kconfiggroup.h>
00056 #include "ktzfiletimezone.h"
00057 #ifdef Q_OS_WIN
00058 #include "ktimezone_win.h"
00059 #endif
00060
00061 #define KTIMEZONED_DBUS_IFACE "org.kde.KTimeZoned"
00062
00063
00064
00065
00066
00067 int gmtoff(time_t t)
00068 {
00069 #ifdef _POSIX_THREAD_SAFE_FUNCTIONS
00070 tm tmtime;
00071 if (!localtime_r(&t, &tmtime))
00072 return 0;
00073 #ifdef HAVE_TM_GMTOFF
00074 return tmtime.tm_gmtoff;
00075 #else
00076 int lwday = tmtime.tm_wday;
00077 int lt = 3600*tmtime.tm_hour + 60*tmtime.tm_min + tmtime.tm_sec;
00078 if (!gmtime_r(&t, &tmtime))
00079 return 0;
00080 int uwday = tmtime.tm_wday;
00081 int ut = 3600*tmtime.tm_hour + 60*tmtime.tm_min + tmtime.tm_sec;
00082 #endif
00083 #else
00084 tm *tmtime = localtime(&t);
00085 if (!tmtime)
00086 return 0;
00087 #ifdef HAVE_TM_GMTOFF
00088 return tmtime->tm_gmtoff;
00089 #else
00090 int lwday = tmtime->tm_wday;
00091 int lt = 3600*tmtime->tm_hour + 60*tmtime->tm_min + tmtime->tm_sec;
00092 tmtime = gmtime(&t);
00093 int uwday = tmtime->tm_wday;
00094 int ut = 3600*tmtime->tm_hour + 60*tmtime->tm_min + tmtime->tm_sec;
00095 #endif
00096 #endif
00097 #ifndef HAVE_TM_GMTOFF
00098 if (lwday != uwday)
00099 {
00100
00101 if (lwday == uwday + 1 || (lwday == 0 && uwday == 6))
00102 lt += 24*3600;
00103 else
00104 lt -= 24*3600;
00105 }
00106 return lt - ut;
00107 #endif
00108 }
00109
00110
00111
00112
00113 class KSystemTimeZonesPrivate : public KTimeZones
00114 {
00115 public:
00116 static KSystemTimeZonesPrivate *instance();
00117 static KTzfileTimeZoneSource *tzfileSource();
00118 static void setLocalZone();
00119 static void cleanup();
00120 static void readConfig(bool init);
00121 #ifdef Q_OS_WIN
00122 static void updateTimezoneInformation()
00123 {
00124 instance()->updateTimezoneInformation(true);
00125 }
00126 #else
00127 static void updateZonetab() { instance()->readZoneTab(true); }
00128 #endif
00129
00130 static KTimeZone m_localZone;
00131 static QString m_localZoneName;
00132 static QString m_zoneinfoDir;
00133 static QString m_zonetab;
00134 static KSystemTimeZoneSource *m_source;
00135
00136 private:
00137 KSystemTimeZonesPrivate() {}
00138 #ifdef Q_OS_WIN
00139 void updateTimezoneInformation(bool update);
00140 #else
00141 void readZoneTab(bool update);
00142 static float convertCoordinate(const QString &coordinate);
00143 #endif
00144
00145 static KSystemTimeZones *m_parent;
00146 static KSystemTimeZonesPrivate *m_instance;
00147 static KTzfileTimeZoneSource *m_tzfileSource;
00148 };
00149
00150 KTimeZone KSystemTimeZonesPrivate::m_localZone;
00151 QString KSystemTimeZonesPrivate::m_localZoneName;
00152 QString KSystemTimeZonesPrivate::m_zoneinfoDir;
00153 QString KSystemTimeZonesPrivate::m_zonetab;
00154 KSystemTimeZoneSource *KSystemTimeZonesPrivate::m_source = 0;
00155 KTzfileTimeZoneSource *KSystemTimeZonesPrivate::m_tzfileSource = 0;
00156 KSystemTimeZones *KSystemTimeZonesPrivate::m_parent = 0;
00157 KSystemTimeZonesPrivate *KSystemTimeZonesPrivate::m_instance = 0;
00158
00159 KTzfileTimeZoneSource *KSystemTimeZonesPrivate::tzfileSource()
00160 {
00161 if (!m_tzfileSource)
00162 {
00163 instance();
00164 m_tzfileSource = new KTzfileTimeZoneSource(m_zoneinfoDir);
00165 }
00166 return m_tzfileSource;
00167 }
00168
00169
00170 #ifndef NDEBUG
00171 K_GLOBAL_STATIC(KTimeZone, simulatedLocalZone)
00172 #endif
00173
00174
00175 KSystemTimeZones::KSystemTimeZones()
00176 : d(0)
00177 {
00178 QDBusConnection dbus = QDBusConnection::sessionBus();
00179 dbus.connect(QString(), QString(), KTIMEZONED_DBUS_IFACE, "configChanged", this, SLOT(configChanged()));
00180 dbus.connect(QString(), QString(), KTIMEZONED_DBUS_IFACE, "zonetabChanged", this, SLOT(zonetabChanged(QString)));
00181
00182
00183 }
00184
00185 KSystemTimeZones::~KSystemTimeZones()
00186 {
00187 }
00188
00189 KTimeZone KSystemTimeZones::local()
00190 {
00191 #ifndef NDEBUG
00192 if (simulatedLocalZone->isValid())
00193 return *simulatedLocalZone;
00194 #endif
00195 KSystemTimeZonesPrivate::instance();
00196 return KSystemTimeZonesPrivate::m_localZone;
00197 }
00198
00199 KTimeZone KSystemTimeZones::realLocalZone()
00200 {
00201 KSystemTimeZonesPrivate::instance();
00202 return KSystemTimeZonesPrivate::m_localZone;
00203 }
00204
00205 void KSystemTimeZones::setLocalZone(const KTimeZone& tz)
00206 {
00207 #ifndef NDEBUG
00208 *simulatedLocalZone = tz;
00209 #endif
00210 }
00211
00212 bool KSystemTimeZones::isSimulated()
00213 {
00214 #ifndef NDEBUG
00215 return simulatedLocalZone->isValid();
00216 #else
00217 return false;
00218 #endif
00219 }
00220
00221 QString KSystemTimeZones::zoneinfoDir()
00222 {
00223 KSystemTimeZonesPrivate::instance();
00224 return KSystemTimeZonesPrivate::m_zoneinfoDir;
00225 }
00226
00227 KTimeZones *KSystemTimeZones::timeZones()
00228 {
00229 return KSystemTimeZonesPrivate::instance();
00230 }
00231
00232 KTimeZone KSystemTimeZones::readZone(const QString &name)
00233 {
00234 return KTzfileTimeZone(KSystemTimeZonesPrivate::tzfileSource(), name);
00235 }
00236
00237 const KTimeZones::ZoneMap KSystemTimeZones::zones()
00238 {
00239 return KSystemTimeZonesPrivate::instance()->zones();
00240 }
00241
00242 KTimeZone KSystemTimeZones::zone(const QString& name)
00243 {
00244 return KSystemTimeZonesPrivate::instance()->zone(name);
00245 }
00246
00247 void KSystemTimeZones::configChanged()
00248 {
00249 kDebug(161) << "KSystemTimeZones::configChanged()";
00250 KSystemTimeZonesPrivate::readConfig(false);
00251 }
00252
00253 void KSystemTimeZones::zonetabChanged(const QString &zonetab)
00254 {
00255 Q_UNUSED(zonetab)
00256 #ifndef Q_OS_WIN
00257 kDebug(161) << "KSystemTimeZones::zonetabChanged()";
00258
00259
00260 KSystemTimeZonesPrivate::updateZonetab();
00261 #endif
00262 }
00263
00264 void KSystemTimeZones::zoneDefinitionChanged(const QString &zone)
00265 {
00266
00267
00268
00269
00270 Q_UNUSED(zone)
00271 }
00272
00273
00274
00275
00276 KSystemTimeZonesPrivate *KSystemTimeZonesPrivate::instance()
00277 {
00278 if (!m_instance)
00279 {
00280 m_instance = new KSystemTimeZonesPrivate;
00281
00282
00283 m_parent = new KSystemTimeZones;
00284
00285 QDBusInterface *ktimezoned = new QDBusInterface("org.kde.kded", "/modules/ktimezoned", KTIMEZONED_DBUS_IFACE);
00286 QDBusReply<void> reply = ktimezoned->call("initialize", false);
00287 if (!reply.isValid())
00288 kError(161) << "KSystemTimeZones: ktimezoned initialize() D-Bus call failed: " << reply.error().message() << endl;
00289 kDebug(161)<<"instance(): ... initialised";
00290 delete ktimezoned;
00291
00292
00293 readConfig(true);
00294
00295
00296 #ifdef Q_OS_WIN
00297
00298
00299 m_instance->updateTimezoneInformation(false);
00300 #else
00301
00302 if (!m_zonetab.isEmpty())
00303 m_instance->readZoneTab(false);
00304 #endif
00305 setLocalZone();
00306 if (!m_localZone.isValid())
00307 m_localZone = KTimeZone::utc();
00308
00309 qAddPostRoutine(KSystemTimeZonesPrivate::cleanup);
00310 }
00311 return m_instance;
00312 }
00313
00314 void KSystemTimeZonesPrivate::readConfig(bool init)
00315 {
00316 KConfig config(QLatin1String("ktimezonedrc"));
00317 if (!init)
00318 config.reparseConfiguration();
00319 KConfigGroup group(&config, "TimeZones");
00320 m_zoneinfoDir = group.readEntry("ZoneinfoDir");
00321 m_zonetab = group.readEntry("Zonetab");
00322 m_localZoneName = group.readEntry("LocalZone");
00323 if (m_zoneinfoDir.length() > 1 && m_zoneinfoDir.endsWith('/'))
00324 m_zoneinfoDir.truncate(m_zoneinfoDir.length() - 1);
00325 if (!init)
00326 setLocalZone();
00327 kDebug(161) << "readConfig(): local zone=" << m_localZoneName;
00328 }
00329
00330 void KSystemTimeZonesPrivate::setLocalZone()
00331 {
00332 QString filename;
00333 if (m_localZoneName.startsWith('/'))
00334 {
00335
00336 filename = m_localZoneName;
00337 }
00338 else
00339 {
00340
00341
00342 m_localZone = m_instance->zone(m_localZoneName);
00343 if (m_localZone.isValid())
00344 return;
00345
00346 filename = m_zoneinfoDir + '/' + m_localZoneName;
00347 }
00348
00349
00350 QString zonename = filename;
00351 if (zonename.startsWith(m_zoneinfoDir + '/'))
00352 zonename = zonename.mid(m_zoneinfoDir.length() + 1);
00353 m_localZone = KTzfileTimeZone(KSystemTimeZonesPrivate::tzfileSource(), zonename);
00354 if (m_localZone.isValid() && m_instance)
00355 {
00356
00357 KTimeZone oldzone = m_instance->zone(zonename);
00358 if (!oldzone.isValid() || oldzone.type() != "KTzfileTimeZone")
00359 {
00360 m_instance->remove(oldzone);
00361 m_instance->add(m_localZone);
00362 }
00363 }
00364 }
00365
00366 void KSystemTimeZonesPrivate::cleanup()
00367 {
00368 delete m_parent;
00369 delete m_instance;
00370 delete m_source;
00371 delete m_tzfileSource;
00372 }
00373
00374 #ifdef Q_OS_WIN
00375
00376 void KSystemTimeZonesPrivate::updateTimezoneInformation(bool update)
00377 {
00378 if (!m_source)
00379 m_source = new KSystemTimeZoneSourceWindows;
00380 QStringList newZones;
00381 Q_FOREACH( const QString & tz, KSystemTimeZoneWindows::listTimeZones() ) {
00382
00383
00384 KSystemTimeZoneWindows stz(m_source, tz);
00385 if (update)
00386 {
00387
00388 newZones += stz.name();
00389 KTimeZone oldTz = zone(stz.name());
00390 if (oldTz.isValid())
00391 oldTz.updateBase(stz);
00392 else
00393 add(stz);
00394 }
00395 else
00396 add(stz);
00397 }
00398 if (update)
00399 {
00400
00401 const ZoneMap oldZones = zones();
00402 for (ZoneMap::const_iterator it = oldZones.begin(); it != oldZones.end(); ++it)
00403 {
00404 if (newZones.indexOf(it.key()) < 0)
00405 remove(it.value());
00406 }
00407 }
00408 }
00409
00410 #else
00411
00412
00413
00414
00415 void KSystemTimeZonesPrivate::readZoneTab(bool update)
00416 {
00417 kDebug(161) << "readZoneTab(" << m_zonetab<< ")";
00418 QStringList newZones;
00419 QFile f;
00420 f.setFileName(m_zonetab);
00421 if (!f.open(QIODevice::ReadOnly))
00422 return;
00423 QTextStream str(&f);
00424 QRegExp lineSeparator("[ \t]");
00425 QRegExp ordinateSeparator("[+-]");
00426 if (!m_source)
00427 m_source = new KSystemTimeZoneSource;
00428 while (!str.atEnd())
00429 {
00430 QString line = str.readLine();
00431 if (line.isEmpty() || line[0] == '#')
00432 continue;
00433 QStringList tokens = KStringHandler::perlSplit(lineSeparator, line, 4);
00434 int n = tokens.count();
00435 if (n < 3)
00436 {
00437 kError(161) << "readZoneTab(): invalid record: " << line << endl;
00438 continue;
00439 }
00440
00441
00442 int i = tokens[1].indexOf(QRegExp("[+-]"), 1);
00443 if (i < 0)
00444 {
00445 kError(161) << "readZoneTab() " << tokens[2] << ": invalid coordinates: " << tokens[1] << endl;
00446 continue;
00447 }
00448
00449 float latitude = convertCoordinate(tokens[1].left(i));
00450 float longitude = convertCoordinate(tokens[1].mid(i));
00451
00452
00453 if (tokens[0] == "??")
00454 tokens[0] = "";
00455
00456
00457 if (n > 3 && tokens[3] == "-")
00458 tokens[3] = "";
00459 KSystemTimeZone tz(m_source, tokens[2], tokens[0], latitude, longitude, (n > 3 ? tokens[3] : QString()));
00460 if (update)
00461 {
00462
00463 newZones += tz.name();
00464 KTimeZone oldTz = zone(tz.name());
00465 if (oldTz.isValid())
00466 oldTz.updateBase(tz);
00467 else
00468 add(tz);
00469 }
00470 else
00471 add(tz);
00472 }
00473 f.close();
00474
00475 if (update)
00476 {
00477
00478 const ZoneMap oldZones = zones();
00479 for (ZoneMap::ConstIterator it = oldZones.constBegin(); it != oldZones.constEnd(); ++it)
00480 {
00481 if (newZones.indexOf(it.key()) < 0)
00482 remove(it.value());
00483 }
00484 }
00485 }
00486
00490 float KSystemTimeZonesPrivate::convertCoordinate(const QString &coordinate)
00491 {
00492 int value = coordinate.toInt();
00493 int degrees = 0;
00494 int minutes = 0;
00495 int seconds = 0;
00496
00497 if (coordinate.length() > 6)
00498 {
00499 degrees = value / 10000;
00500 value -= degrees * 10000;
00501 minutes = value / 100;
00502 value -= minutes * 100;
00503 seconds = value;
00504 }
00505 else
00506 {
00507 degrees = value / 100;
00508 value -= degrees * 100;
00509 minutes = value;
00510 }
00511 value = degrees * 3600 + minutes * 60 + seconds;
00512 return value / 3600.0;
00513 }
00514 #endif
00515
00516
00517
00518
00519
00520 KSystemTimeZoneBackend::KSystemTimeZoneBackend(KSystemTimeZoneSource *source, const QString &name,
00521 const QString &countryCode, float latitude, float longitude, const QString &comment)
00522 : KTimeZoneBackend(source, name, countryCode, latitude, longitude, comment)
00523 {}
00524
00525 KSystemTimeZoneBackend::~KSystemTimeZoneBackend()
00526 {}
00527
00528 KTimeZoneBackend *KSystemTimeZoneBackend::clone() const
00529 {
00530 return new KSystemTimeZoneBackend(*this);
00531 }
00532
00533 QByteArray KSystemTimeZoneBackend::type() const
00534 {
00535 return "KSystemTimeZone";
00536 }
00537
00538 int KSystemTimeZoneBackend::offsetAtZoneTime(const KTimeZone *caller, const QDateTime &zoneDateTime, int *secondOffset) const
00539 {
00540 if (!caller->isValid() || !zoneDateTime.isValid() || zoneDateTime.timeSpec() != Qt::LocalTime)
00541 return 0;
00542
00543 const QByteArray originalZone = qgetenv("TZ");
00544 QByteArray tz = caller->name().toUtf8();
00545 tz.prepend(":");
00546 bool change = (tz != originalZone);
00547 if (change)
00548 {
00549 ::setenv("TZ", tz, 1);
00550 ::tzset();
00551 }
00552
00553
00554 tm tmtime;
00555 tmtime.tm_sec = zoneDateTime.time().second();
00556 tmtime.tm_min = zoneDateTime.time().minute();
00557 tmtime.tm_hour = zoneDateTime.time().hour();
00558 tmtime.tm_mday = zoneDateTime.date().day();
00559 tmtime.tm_mon = zoneDateTime.date().month() - 1;
00560 tmtime.tm_year = zoneDateTime.date().year() - 1900;
00561 tmtime.tm_isdst = -1;
00562 time_t t = mktime(&tmtime);
00563 int offset1 = (t == (time_t)-1) ? 0 : gmtoff(t);
00564 if (secondOffset)
00565 {
00566 int offset2 = offset1;
00567 if (t != (time_t)-1)
00568 {
00569
00570
00571
00572 int maxShift = 3600;
00573 offset2 = gmtoff(t + maxShift);
00574 if (offset2 < offset1)
00575 {
00576
00577 if (offset1 - offset2 < maxShift)
00578 offset2 = gmtoff(t + (offset1 - offset2));
00579 }
00580 else if ((offset2 = gmtoff(t - maxShift)) > offset1)
00581 {
00582
00583 if (offset2 - offset1 < maxShift)
00584 offset2 = gmtoff(t - (offset2 - offset1));
00585
00586 int o = offset1;
00587 offset1 = offset2;
00588 offset2 = o;
00589 }
00590 else offset2 = offset1;
00591 }
00592 *secondOffset = offset2;
00593 }
00594
00595 if (change)
00596 {
00597
00598 if (originalZone.isEmpty())
00599 ::unsetenv("TZ");
00600 else
00601 ::setenv("TZ", originalZone, 1);
00602 ::tzset();
00603 }
00604 return offset1;
00605 }
00606
00607 int KSystemTimeZoneBackend::offsetAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const
00608 {
00609 return offset(caller, KTimeZone::toTime_t(utcDateTime));
00610 }
00611
00612 int KSystemTimeZoneBackend::offset(const KTimeZone *caller, time_t t) const
00613 {
00614 if (!caller->isValid() || t == KTimeZone::InvalidTime_t)
00615 return 0;
00616
00617
00618 const QByteArray originalZone = qgetenv("TZ");
00619 QByteArray tz = caller->name().toUtf8();
00620 tz.prepend(":");
00621 bool change = (tz != originalZone);
00622 if (change)
00623 {
00624 ::setenv("TZ", tz, 1);
00625 ::tzset();
00626 }
00627
00628 int secs = gmtoff(t);
00629
00630 if (change)
00631 {
00632
00633 if (originalZone.isEmpty())
00634 ::unsetenv("TZ");
00635 else
00636 ::setenv("TZ", originalZone, 1);
00637 ::tzset();
00638 }
00639 return secs;
00640 }
00641
00642 bool KSystemTimeZoneBackend::isDstAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const
00643 {
00644 return isDst(caller, KTimeZone::toTime_t(utcDateTime));
00645 }
00646
00647 bool KSystemTimeZoneBackend::isDst(const KTimeZone *caller, time_t t) const
00648 {
00649 Q_UNUSED(caller)
00650 if (t != (time_t)-1)
00651 {
00652 #ifdef _POSIX_THREAD_SAFE_FUNCTIONS
00653 tm tmtime;
00654 if (localtime_r(&t, &tmtime))
00655 return tmtime.tm_isdst > 0;
00656 #else
00657 tm *tmtime = localtime(&t);
00658 if (tmtime)
00659 return tmtime->tm_isdst > 0;
00660 #endif
00661 }
00662 return false;
00663 }
00664
00665
00666
00667
00668 KSystemTimeZone::KSystemTimeZone(KSystemTimeZoneSource *source, const QString &name,
00669 const QString &countryCode, float latitude, float longitude, const QString &comment)
00670 : KTimeZone(new KSystemTimeZoneBackend(source, name, countryCode, latitude, longitude, comment))
00671 {
00672 }
00673
00674 KSystemTimeZone::~KSystemTimeZone()
00675 {
00676 }
00677
00678
00679
00680
00681 class KSystemTimeZoneDataPrivate
00682 {
00683 public:
00684 QByteArray TZ;
00685 QList<QByteArray> abbreviations;
00686 };
00687
00688
00689
00690 class KSystemTimeZoneSourcePrivate
00691 {
00692 public:
00693 static void setTZ(const QByteArray &zoneName);
00694 static void restoreTZ();
00695 static QByteArray savedTZ;
00696 static QByteArray originalTZ;
00697 static bool TZIsSaved;
00698 static bool multiParse;
00699 };
00700
00701 QByteArray KSystemTimeZoneSourcePrivate::savedTZ;
00702 QByteArray KSystemTimeZoneSourcePrivate::originalTZ;
00703 bool KSystemTimeZoneSourcePrivate::TZIsSaved = false;
00704 bool KSystemTimeZoneSourcePrivate::multiParse = false;
00705
00706
00707 KSystemTimeZoneSource::KSystemTimeZoneSource()
00708 : d(0)
00709
00710 {
00711 }
00712
00713 KSystemTimeZoneSource::~KSystemTimeZoneSource()
00714 {
00715
00716 }
00717
00718 KTimeZoneData* KSystemTimeZoneSource::parse(const KTimeZone &zone) const
00719 {
00720 QByteArray tz = zone.name().toUtf8();
00721 KSystemTimeZoneSourcePrivate::setTZ(tz);
00722
00723 tzset();
00724 KSystemTimeZoneData* data = new KSystemTimeZoneData;
00725 data->d->TZ = tz;
00726 data->d->abbreviations.append(tzname[0]);
00727 data->d->abbreviations.append(tzname[1]);
00728
00729
00730
00731
00732 KSystemTimeZoneSourcePrivate::restoreTZ();
00733 return data;
00734 }
00735
00736 void KSystemTimeZoneSource::startParseBlock()
00737 {
00738 KSystemTimeZoneSourcePrivate::originalTZ = qgetenv("TZ");
00739 KSystemTimeZoneSourcePrivate::multiParse = true;
00740 }
00741
00742 void KSystemTimeZoneSource::endParseBlock()
00743 {
00744 if (KSystemTimeZoneSourcePrivate::multiParse)
00745 {
00746
00747 if (KSystemTimeZoneSourcePrivate::originalTZ.isEmpty())
00748 ::unsetenv("TZ");
00749 else
00750 ::setenv("TZ", KSystemTimeZoneSourcePrivate::originalTZ, 1);
00751 ::tzset();
00752 KSystemTimeZoneSourcePrivate::multiParse = false;
00753 }
00754 }
00755
00756
00757
00758 void KSystemTimeZoneSourcePrivate::setTZ(const QByteArray &zoneName)
00759 {
00760 QByteArray tz = zoneName;
00761 tz.prepend(":");
00762 bool setTZ = multiParse;
00763 if (!setTZ)
00764 {
00765 savedTZ = qgetenv("TZ");
00766 TZIsSaved = true;
00767 setTZ = (tz != savedTZ);
00768 }
00769 if (setTZ)
00770 {
00771 ::setenv("TZ", tz, 1);
00772 ::tzset();
00773 }
00774 }
00775
00776
00777 void KSystemTimeZoneSourcePrivate::restoreTZ()
00778 {
00779 if (TZIsSaved)
00780 {
00781 if (savedTZ.isEmpty())
00782 ::unsetenv("TZ");
00783 else
00784 ::setenv("TZ", savedTZ, 1);
00785 ::tzset();
00786 TZIsSaved = false;
00787 }
00788 }
00789
00790
00791
00792
00793 KSystemTimeZoneData::KSystemTimeZoneData()
00794 : d(new KSystemTimeZoneDataPrivate)
00795 { }
00796
00797 KSystemTimeZoneData::KSystemTimeZoneData(const KSystemTimeZoneData &rhs)
00798 : KTimeZoneData(),
00799 d(new KSystemTimeZoneDataPrivate)
00800 {
00801 operator=(rhs);
00802 }
00803
00804 KSystemTimeZoneData::~KSystemTimeZoneData()
00805 {
00806 delete d;
00807 }
00808
00809 KSystemTimeZoneData &KSystemTimeZoneData::operator=(const KSystemTimeZoneData &rhs)
00810 {
00811 d->TZ = rhs.d->TZ;
00812 d->abbreviations = rhs.d->abbreviations;
00813 return *this;
00814 }
00815
00816 KTimeZoneData *KSystemTimeZoneData::clone() const
00817 {
00818 return new KSystemTimeZoneData(*this);
00819 }
00820
00821 QList<QByteArray> KSystemTimeZoneData::abbreviations() const
00822 {
00823 return d->abbreviations;
00824 }
00825
00826 QByteArray KSystemTimeZoneData::abbreviation(const QDateTime &utcDateTime) const
00827 {
00828 QByteArray abbr;
00829 if (utcDateTime.timeSpec() != Qt::UTC)
00830 return abbr;
00831 time_t t = utcDateTime.toTime_t();
00832 if (t != KTimeZone::InvalidTime_t)
00833 {
00834 KSystemTimeZoneSourcePrivate::setTZ(d->TZ);
00835
00836
00837
00838
00839
00840 #ifdef _POSIX_THREAD_SAFE_FUNCTIONS
00841 tm tmtime;
00842 if (localtime_r(&t, &tmtime))
00843 #ifdef HAVE_STRUCT_TM_TM_ZONE
00844 abbr = tmtime.tm_zone;
00845 #else
00846 abbr = tzname[(tmtime.tm_isdst > 0) ? 1 : 0];
00847 #endif
00848 #else
00849 tm *tmtime = localtime(&t);
00850 if (tmtime)
00851 #ifdef HAVE_STRUCT_TM_TM_ZONE
00852 abbr = tmtime->tm_zone;
00853 #else
00854 abbr = tzname[(tmtime->tm_isdst > 0) ? 1 : 0];
00855 #endif
00856 #endif
00857 KSystemTimeZoneSourcePrivate::restoreTZ();
00858 }
00859 return abbr;
00860 }
00861
00862 QList<int> KSystemTimeZoneData::utcOffsets() const
00863 {
00864 return QList<int>();
00865 }
00866