File indexing completed on 2023-09-24 04:04:55
0001 /* 0002 This file is part of the KDE libraries 0003 Copyright (c) 2005-2007,2009-2012 David Jarvie <djarvie@kde.org> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This library is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this library; see the file COPYING.LIB. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 Boston, MA 02110-1301, USA. 0019 */ 0020 0021 /** @file 0022 * System time zone functions 0023 * @author David Jarvie <djarvie@kde.org>. 0024 * @author S.R.Haque <srhaque@iee.org>. 0025 */ 0026 0027 #ifndef _KSYSTEMTIMEZONE_H 0028 #define _KSYSTEMTIMEZONE_H 0029 0030 #include <kdelibs4support_export.h> 0031 #include "ktimezone.h" 0032 0033 #include <QObject> 0034 #include <QDateTime> 0035 #include <QList> 0036 #include <QString> 0037 #include <QByteArray> 0038 0039 class KSystemTimeZoneSource; 0040 class KSystemTimeZonePrivate; 0041 class KSystemTimeZonesPrivate; 0042 class KSystemTimeZoneSourcePrivate; 0043 class KSystemTimeZoneDataPrivate; 0044 0045 /** 0046 * The KSystemTimeZones class represents the system time zone database, consisting 0047 * of a collection of individual system time zone definitions, indexed by name. 0048 * Each individual time zone is defined in a KSystemTimeZone or KTzfileTimeZone 0049 * instance. Additional time zones (of any class derived from KTimeZone) may be 0050 * added if desired. 0051 * 0052 * At initialisation, KSystemTimeZones on UNIX systems reads the zone.tab file 0053 * to obtain the list of system time zones, and creates a KTzfileTimeZone 0054 * instance for each one. 0055 * 0056 * @note KSystemTimeZones gets the system's time zone configuration, including 0057 * the current local system time zone and the location of zone.tab, from the KDE 0058 * time zone daemon, ktimezoned. If ktimezoned cannot be started, KSystemTimeZones 0059 * will only know about the UTC time zone. 0060 * 0061 * Note that KSystemTimeZones is not derived from KTimeZones, but instead contains 0062 * a KTimeZones instance which holds the system time zone database. Convenience 0063 * static methods are defined to access its data, or alternatively you can access 0064 * the KTimeZones instance directly via the timeZones() method. 0065 * 0066 * As an example, find the local time in Oman corresponding to the local system 0067 * time of 12:15:00 on 13th November 1999: 0068 * \code 0069 * QDateTime sampleTime(QDate(1999,11,13), QTime(12,15,0), Qt::LocalTime); 0070 * KTimeZone local = KSystemTimeZones::local(); 0071 * KTimeZone oman = KSystemTimeZones::zone("Asia/Muscat"); 0072 * QDateTime omaniTime = local.convert(oman, sampleTime); 0073 * \endcode 0074 * 0075 * @note KTzfileTimeZone is used in preference to KSystemTimeZone on UNIX 0076 * systems since use of the standard system libraries by KSystemTimeZone 0077 * requires the use of tzset() in several methods. That function reads and 0078 * parses the local system time zone definition file every time it is called, 0079 * and this has been observed to make applications hang for many seconds when 0080 * a large number of KSystemTimeZone calls are made in succession. 0081 * 0082 * @note This class provides a facility to simulate the local system time 0083 * zone. This facility is provided for testing purposes only, and is only 0084 * available if the library is compiled with debug enabled. In release mode, 0085 * simulation is inoperative and the real local system time zone is used at all 0086 * times. 0087 * 0088 * @short System time zone access 0089 * @see KTimeZones, KSystemTimeZone, KSystemTimeZoneSource, KTzfileTimeZone 0090 * @ingroup timezones 0091 * @author David Jarvie <djarvie@kde.org>. 0092 * @author S.R.Haque <srhaque@iee.org>. 0093 */ 0094 class KDELIBS4SUPPORT_EXPORT KSystemTimeZones : public QObject 0095 { 0096 Q_OBJECT 0097 public: 0098 ~KSystemTimeZones() override; 0099 0100 /** 0101 * Returns the unique KTimeZones instance containing the system time zones 0102 * collection. It is first created if it does not already exist. 0103 * 0104 * @return time zones. 0105 */ 0106 static KTimeZones *timeZones(); 0107 0108 /** 0109 * Returns all the time zones defined in this collection. 0110 * 0111 * @return time zone collection 0112 */ 0113 static const KTimeZones::ZoneMap zones(); 0114 0115 /** 0116 * Returns the time zone with the given name. 0117 * 0118 * The time zone definition is obtained using system library calls, and may 0119 * not contain historical data. If you need historical time change data, 0120 * use the potentially slower method readZone(). 0121 * 0122 * @param name name of time zone 0123 * @return time zone (usually a KSystemTimeZone instance), or invalid if not found 0124 * @see readZone() 0125 */ 0126 static KTimeZone zone(const QString &name); 0127 0128 /** 0129 * Returns the time zone with the given name, containing the full time zone 0130 * definition read directly from the system time zone database. This may 0131 * incur a higher overhead than zone(), but will provide whatever historical 0132 * data the system holds. 0133 * 0134 * @param name name of time zone 0135 * @return time zone (usually a KTzfileTimeZone instance), or invalid if not found 0136 * @see zone() 0137 */ 0138 static KTimeZone readZone(const QString &name); 0139 0140 /** 0141 * Returns the current local system time zone. 0142 * 0143 * The idea of this routine is to provide a robust lookup of the local time 0144 * zone. On Unix systems, there are a variety of mechanisms for setting this 0145 * information, and no well defined way of getting it. For example, if you 0146 * set your time zone to "Europe/London", then the tzname[] maintained by 0147 * tzset() typically returns { "GMT", "BST" }. The function of this routine 0148 * is to actually return "Europe/London" (or rather, the corresponding 0149 * KTimeZone). 0150 * 0151 * Note that depending on how the system stores its current time zone, this 0152 * routine may return a synonym of the expected time zone. For example, 0153 * "Europe/London", "Europe/Guernsey" and some other time zones are all 0154 * identical and there may be no way for the routine to distinguish which 0155 * of these is the correct zone name from the user's point of view. 0156 * 0157 * @warning For testing purposes, if the library is compiled with debug 0158 * enabled, this method returns any simulated local system time 0159 * zone set by setLocalZone(). If the library is compiled in 0160 * release mode, it always returns the real local system time zone. 0161 * 0162 * @return local system time zone. If necessary, we will use a series of 0163 * heuristics which end by returning UTC. We will never return NULL. 0164 * Note that if UTC is returned as a default, it may not belong to the 0165 * the collection returned by KSystemTimeZones::zones(). 0166 */ 0167 static KTimeZone local(); 0168 0169 /** 0170 * Return the real (not simulated) local system time zone. 0171 * 0172 * @warning This method is provided only for testing purposes, and should 0173 * not be used in released code. If the library is compiled without 0174 * debug enabled, local() and realLocalZone() both return the real 0175 * local system time zone. 0176 * To avoid confusion, it is recommended that calls to 0177 * realLocalZone() should be conditionally compiled, e.g.: 0178 * \code 0179 * #ifndef NDEBUG 0180 * tz = KSystemTimeZones::realLocalZone(); 0181 * #endif 0182 * \endcode 0183 * 0184 * @see setLocalZone() 0185 * @since 4.3 0186 */ 0187 static KTimeZone realLocalZone(); 0188 0189 /** 0190 * Set or clear the simulated local system time zone. 0191 * 0192 * @warning This method is provided only for testing purposes, and should 0193 * not be used in released code. If the library is compiled without 0194 * debug enabled, setLocalZone() has no effect. 0195 * To avoid confusion, it is recommended that calls to it should be 0196 * conditionally compiled, e.g.: 0197 * \code 0198 * #ifndef NDEBUG 0199 * KSystemTimeZones::setLocalZone(tz); 0200 * #endif 0201 * \endcode 0202 * 0203 * @param tz the time zone to simulate, or an invalid KTimeZone instance 0204 * (i.e. \code tz.isValid() == false \endcode) to cancel 0205 * simulation 0206 * @since 4.3 0207 */ 0208 static void setLocalZone(const KTimeZone &tz); 0209 0210 /** 0211 * Check whether there is a simulated local system time zone. 0212 * 0213 * @warning This method is provided only for testing purposes, and should 0214 * not be used in released code. If the library is compiled without 0215 * debug enabled, isSimulated() always returns false. 0216 * To avoid confusion, it is recommended that calls to it should be 0217 * conditionally compiled, e.g.: 0218 * \code 0219 * #ifndef NDEBUG 0220 * if (KSystemTimeZones::isSimulated()) 0221 * { 0222 * ... 0223 * } 0224 * #endif 0225 * \endcode 0226 * 0227 * @see setLocalZone() 0228 * @since 4.3 0229 */ 0230 static bool isSimulated(); 0231 0232 /** 0233 * Returns the location of the system time zone zoneinfo database. 0234 * 0235 * @return path of directory containing the zoneinfo database 0236 */ 0237 static QString zoneinfoDir(); 0238 0239 /** 0240 * Return whether the KDE time zone daemon, ktimezoned, appears to be 0241 * available and working. If not, UTC will be the only recognized time 0242 * zone. 0243 * @since 4.6 0244 */ 0245 static bool isTimeZoneDaemonAvailable(); 0246 0247 private Q_SLOTS: 0248 // Connected to D-Bus signals 0249 void configChanged(); 0250 void zonetabChanged(const QString &zonetab); 0251 void zoneDefinitionChanged(const QString &zone); 0252 0253 private: 0254 KSystemTimeZones(); 0255 0256 KSystemTimeZonesPrivate *const d; 0257 friend class KSystemTimeZonesPrivate; 0258 }; 0259 0260 /** 0261 * The KSystemTimeZone class represents a time zone in the system database. 0262 * 0263 * It works in partnership with the KSystemTimeZoneSource class which reads and parses the 0264 * time zone definition files. 0265 * 0266 * Typically, instances are created and accessed via the KSystemTimeZones class. 0267 * 0268 * @warning The KSystemTimeZone class uses the standard system libraries to 0269 * access time zone data, and its functionality is limited to what these libraries 0270 * provide. On many systems, dates earlier than 1970 are not handled, and on 0271 * non-GNU systems there is no guarantee that the time zone abbreviation returned 0272 * for a given date will be correct if the abbreviations applicable then were 0273 * not those currently in use. Consider using KSystemTimeZones::readZone() or the 0274 * KTzfileTimeZone class instead, which provide accurate information from the time 0275 * zone definition files (but are likely to incur more overhead). 0276 * 0277 * @short System time zone 0278 * @see KSystemTimeZones, KSystemTimeZoneSource, KSystemTimeZoneData, KTzfileTimeZone 0279 * @ingroup timezones 0280 * @author David Jarvie <djarvie@kde.org>. 0281 */ 0282 class KDELIBS4SUPPORT_EXPORT KSystemTimeZone : public KTimeZone //krazy:exclude=dpointer (no d-pointer for KTimeZone derived classes) 0283 { 0284 public: 0285 0286 /** 0287 * Creates a time zone. 0288 * 0289 * @param source tzfile reader and parser 0290 * @param name time zone's unique name 0291 * @param countryCode ISO 3166 2-character country code, empty if unknown 0292 * @param latitude in degrees (between -90 and +90), UNKNOWN if not known 0293 * @param longitude in degrees (between -180 and +180), UNKNOWN if not known 0294 * @param comment description of the time zone, if any 0295 */ 0296 KSystemTimeZone(KSystemTimeZoneSource *source, const QString &name, 0297 const QString &countryCode = QString(), float latitude = UNKNOWN, float longitude = UNKNOWN, 0298 const QString &comment = QString()); 0299 0300 ~KSystemTimeZone() override; 0301 0302 private: 0303 // d-pointer is in KSystemTimeZoneBackend. 0304 // This is a requirement for classes inherited from KTimeZone. 0305 }; 0306 0307 /** 0308 * Backend class for KSystemTimeZone class. 0309 * 0310 * This class implements KSystemTimeZone's constructors and virtual methods. A 0311 * backend class is required for all classes inherited from KTimeZone to 0312 * allow KTimeZone virtual methods to work together with reference counting of 0313 * private data. 0314 * 0315 * @short Backend class for KSystemTimeZone class 0316 * @see KTimeZoneBackend, KSystemTimeZone, KTimeZone 0317 * @ingroup timezones 0318 * @author David Jarvie <djarvie@kde.org>. 0319 */ 0320 class KDELIBS4SUPPORT_EXPORT KSystemTimeZoneBackend : public KTimeZoneBackend //krazy:exclude=dpointer (non-const d-pointer for KTimeZoneBackend-derived classes) 0321 { 0322 public: 0323 /** Implements KSystemTimeZone::KSystemTimeZone(). */ 0324 KSystemTimeZoneBackend(KSystemTimeZoneSource *source, const QString &name, 0325 const QString &countryCode, float latitude, float longitude, const QString &comment); 0326 0327 ~KSystemTimeZoneBackend() override; 0328 0329 /** 0330 * Creates a copy of this instance. 0331 * 0332 * @return new copy 0333 */ 0334 KTimeZoneBackend *clone() const override; 0335 0336 /** 0337 * Returns the class name of the data represented by this instance. 0338 * 0339 * @return "KSystemTimeZone" 0340 */ 0341 QByteArray type() const override; 0342 0343 /** 0344 * Implements KSystemTimeZone::offsetAtZoneTime(). 0345 * 0346 * Returns the offset of this time zone to UTC at the given local date/time. 0347 * Because of daylight savings time shifts, the date/time may occur twice. Optionally, 0348 * the offsets at both occurrences of @p dateTime are calculated. 0349 * 0350 * The offset is the number of seconds which you must add to UTC to get 0351 * local time in this time zone. 0352 * 0353 * @param caller calling KSystemTimeZone object 0354 * @param zoneDateTime the date/time at which the offset is to be calculated. This 0355 * is interpreted as a local time in this time zone. An error 0356 * occurs if @p zoneDateTime.timeSpec() is not Qt::LocalTime. 0357 * @param secondOffset if non-null, and the @p zoneDateTime occurs twice, receives the 0358 * UTC offset for the second occurrence. Otherwise, it is set 0359 * the same as the return value. 0360 * @return offset in seconds. If @p zoneDateTime occurs twice, it is the offset at the 0361 * first occurrence which is returned. 0362 */ 0363 int offsetAtZoneTime(const KTimeZone *caller, const QDateTime &zoneDateTime, int *secondOffset) const override; 0364 0365 /** 0366 * Implements KSystemTimeZone::offsetAtUtc(). 0367 * 0368 * Returns the offset of this time zone to UTC at the given UTC date/time. 0369 * 0370 * The offset is the number of seconds which you must add to UTC to get 0371 * local time in this time zone. 0372 * 0373 * Note that system times are represented using time_t. An error occurs if the date 0374 * falls outside the range supported by time_t. 0375 * 0376 * @param caller calling KSystemTimeZone object 0377 * @param utcDateTime the UTC date/time at which the offset is to be calculated. 0378 * An error occurs if @p utcDateTime.timeSpec() is not Qt::UTC. 0379 * @return offset in seconds, or 0 if error 0380 */ 0381 int offsetAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const override; 0382 0383 /** 0384 * Implements KSystemTimeZone::offset(). 0385 * 0386 * Returns the offset of this time zone to UTC at a specified UTC time. 0387 * 0388 * The offset is the number of seconds which you must add to UTC to get 0389 * local time in this time zone. 0390 * 0391 * @param caller calling KSystemTimeZone object 0392 * @param t the UTC time at which the offset is to be calculated, measured in seconds 0393 * since 00:00:00 UTC 1st January 1970 (as returned by time(2)) 0394 * @return offset in seconds, or 0 if error 0395 */ 0396 int offset(const KTimeZone *caller, time_t t) const override; 0397 0398 /** 0399 * Implements KSystemTimeZone::isDstAtUtc(). 0400 * 0401 * Returns whether daylight savings time is in operation at the given UTC date/time. 0402 * 0403 * Note that system times are represented using time_t. An error occurs if the date 0404 * falls outside the range supported by time_t. 0405 * 0406 * @param caller calling KSystemTimeZone object 0407 * @param utcDateTime the UTC date/time. An error occurs if 0408 * @p utcDateTime.timeSpec() is not Qt::UTC. 0409 * @return @c true if daylight savings time is in operation, @c false otherwise 0410 */ 0411 bool isDstAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const override; 0412 0413 /** 0414 * Implements KSystemTimeZone::isDst(). 0415 * 0416 * Returns whether daylight savings time is in operation at a specified UTC time. 0417 * 0418 * @param caller calling KSystemTimeZone object 0419 * @param t the UTC time, measured in seconds since 00:00:00 UTC 1st January 1970 0420 * (as returned by time(2)) 0421 * @return @c true if daylight savings time is in operation, @c false otherwise 0422 */ 0423 bool isDst(const KTimeZone *caller, time_t t) const override; 0424 0425 private: 0426 KSystemTimeZonePrivate *d; // non-const 0427 }; 0428 0429 /** 0430 * A class to read and parse system time zone data. 0431 * 0432 * Access is performed via the system time zone library functions. 0433 * 0434 * @short Reads and parses system time zone data 0435 * @see KSystemTimeZones, KSystemTimeZone, KSystemTimeZoneData 0436 * @ingroup timezones 0437 * @author David Jarvie <djarvie@kde.org>. 0438 */ 0439 class KDELIBS4SUPPORT_EXPORT KSystemTimeZoneSource : public KTimeZoneSource 0440 { 0441 public: 0442 /** 0443 * Constructs a system time zone source. 0444 */ 0445 KSystemTimeZoneSource(); 0446 ~KSystemTimeZoneSource() override; 0447 0448 /** 0449 * Extract detailed information for one time zone, via the system time zone 0450 * library functions. 0451 * 0452 * @param zone the time zone for which data is to be extracted 0453 * @return a KSystemTimeZoneData instance containing the parsed data. 0454 * The caller is responsible for deleting the KTimeZoneData instance. 0455 * Null is returned on error. 0456 */ 0457 KTimeZoneData *parse(const KTimeZone &zone) const override; 0458 0459 /** 0460 * Use in conjunction with endParseBlock() to improve efficiency when calling parse() 0461 * for a group of KSystemTimeZone instances in succession. 0462 * Call startParseBlock() before the first parse(), and call endParseBlock() after the last. 0463 * 0464 * The effect of calling these methods is to save and restore the TZ environment variable 0465 * only once before and after the group of parse() calls, rather than before and 0466 * after every call. So, between calls to startParseBlock() and endParseBlock(), do not 0467 * call any functions which rely directly or indirectly on the local time zone setting. 0468 */ 0469 static void startParseBlock(); 0470 0471 /** 0472 * @see startParseBlock() 0473 */ 0474 static void endParseBlock(); 0475 0476 private: 0477 KSystemTimeZoneSourcePrivate *const d; 0478 }; 0479 0480 /** 0481 * @internal 0482 * The parsed system time zone data returned by KSystemTimeZoneSource. 0483 * 0484 * @short Parsed system time zone data 0485 * @see KSystemTimeZoneSource, KSystemTimeZone 0486 * @ingroup timezones 0487 * @author David Jarvie <djarvie@kde.org>. 0488 */ 0489 class KSystemTimeZoneData : public KTimeZoneData 0490 { 0491 friend class KSystemTimeZoneSource; 0492 0493 public: 0494 KSystemTimeZoneData(); 0495 /** Copy constructor; no special ownership assumed. */ 0496 KSystemTimeZoneData(const KSystemTimeZoneData &); 0497 ~KSystemTimeZoneData() override; 0498 0499 /** Assignment; no special ownership assumed. Everything is value based. */ 0500 KSystemTimeZoneData &operator=(const KSystemTimeZoneData &); 0501 0502 /** 0503 * Creates a new copy of this object. 0504 * The caller is responsible for deleting the copy. 0505 * Derived classes must reimplement this method to return a copy of the 0506 * calling instance 0507 * 0508 * @return copy of this instance. This is a KSystemTimeZoneData pointer. 0509 */ 0510 KTimeZoneData *clone() const override; 0511 0512 /** 0513 * Returns the complete list of time zone abbreviations. 0514 * 0515 * @return the list of abbreviations 0516 */ 0517 QList<QByteArray> abbreviations() const override; 0518 QByteArray abbreviation(const QDateTime &utcDateTime) const override; 0519 0520 /** 0521 * Returns the complete list of UTC offsets for the time zone. For system 0522 * time zones, significant processing would be required to obtain such a 0523 * list, so instead an empty list is returned. 0524 * 0525 * @return empty list 0526 */ 0527 QList<int> utcOffsets() const override; 0528 0529 private: 0530 KSystemTimeZoneDataPrivate *const d; 0531 }; 0532 0533 #endif