/* This file is part of the KDE libraries Copyright (c) 2005-2007,2009-2012 David Jarvie This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** @file * System time zone functions * @author David Jarvie . * @author S.R.Haque . */ #ifndef KSYSTEMTIMEZONE_H #define KSYSTEMTIMEZONE_H #include #include "ktimezone.h" #include #include class KSystemTimeZoneSource; class KSystemTimeZonePrivate; class KSystemTimeZonesPrivate; class KSystemTimeZoneSourcePrivate; class KSystemTimeZoneDataPrivate; /** * The KSystemTimeZones class represents the system time zone database, consisting * of a collection of individual system time zone definitions, indexed by name. * Each individual time zone is defined in a KSystemTimeZone or KTzfileTimeZone * instance. Additional time zones (of any class derived from KTimeZone) may be * added if desired. * * At initialisation, KSystemTimeZones on UNIX systems reads the zone.tab file * to obtain the list of system time zones, and creates a KTzfileTimeZone * instance for each one. * * @note KSystemTimeZones gets the system's time zone configuration, including * the current local system time zone and the location of zone.tab, from the KDE * time zone daemon, ktimezoned. If ktimezoned cannot be started, KSystemTimeZones * will only know about the UTC time zone. * * Note that KSystemTimeZones is not derived from KTimeZones, but instead contains * a KTimeZones instance which holds the system time zone database. Convenience * static methods are defined to access its data, or alternatively you can access * the KTimeZones instance directly via the timeZones() method. * * As an example, find the local time in Oman corresponding to the local system * time of 12:15:00 on 13th November 1999: * \code * QDateTime sampleTime(QDate(1999,11,13), QTime(12,15,0), Qt::LocalTime); * KTimeZone local = KSystemTimeZones::local(); * KTimeZone oman = KSystemTimeZones::zone("Asia/Muscat"); * QDateTime omaniTime = local.convert(oman, sampleTime); * \endcode * * @note KTzfileTimeZone is used in preference to KSystemTimeZone on UNIX * systems since use of the standard system libraries by KSystemTimeZone * requires the use of tzset() in several methods. That function reads and * parses the local system time zone definition file every time it is called, * and this has been observed to make applications hang for many seconds when * a large number of KSystemTimeZone calls are made in succession. * * @note This class provides a facility to simulate the local system time * zone. This facility is provided for testing purposes only, and is only * available if the library is compiled with debug enabled. In release mode, * simulation is inoperative and the real local system time zone is used at all * times. * * @short System time zone access * @see KTimeZones, KSystemTimeZone, KSystemTimeZoneSource, KTzfileTimeZone * @ingroup timezones * @author David Jarvie . * @author S.R.Haque . */ class KDECORE_EXPORT KSystemTimeZones : public QObject { Q_OBJECT public: ~KSystemTimeZones(); /** * Returns the unique KTimeZones instance containing the system time zones * collection. It is first created if it does not already exist. * * @return time zones. */ static KTimeZones *timeZones(); /** * Returns all the time zones defined in this collection. * * @return time zone collection */ static const KTimeZones::ZoneMap zones(); /** * Returns the time zone with the given name. * * The time zone definition is obtained using system library calls, and may * not contain historical data. If you need historical time change data, * use the potentially slower method readZone(). * * @param name name of time zone * @return time zone (usually a KSystemTimeZone instance), or invalid if not found * @see readZone() */ static KTimeZone zone(const QString &name); /** * Returns the time zone with the given name, containing the full time zone * definition read directly from the system time zone database. This may * incur a higher overhead than zone(), but will provide whatever historical * data the system holds. * * @param name name of time zone * @return time zone (usually a KTzfileTimeZone instance), or invalid if not found * @see zone() */ static KTimeZone readZone(const QString &name); /** * Returns the current local system time zone. * * The idea of this routine is to provide a robust lookup of the local time * zone. On Unix systems, there are a variety of mechanisms for setting this * information, and no well defined way of getting it. For example, if you * set your time zone to "Europe/London", then the tzname[] maintained by * tzset() typically returns { "GMT", "BST" }. The function of this routine * is to actually return "Europe/London" (or rather, the corresponding * KTimeZone). * * Note that depending on how the system stores its current time zone, this * routine may return a synonym of the expected time zone. For example, * "Europe/London", "Europe/Guernsey" and some other time zones are all * identical and there may be no way for the routine to distinguish which * of these is the correct zone name from the user's point of view. * * @warning For testing purposes, if the library is compiled with debug * enabled, this method returns any simulated local system time * zone set by setLocalZone(). If the library is compiled in * release mode, it always returns the real local system time zone. * * @return local system time zone. If necessary, we will use a series of * heuristics which end by returning UTC. We will never return NULL. * Note that if UTC is returned as a default, it may not belong to the * the collection returned by KSystemTimeZones::zones(). */ static KTimeZone local(); /** * Return the real (not simulated) local system time zone. * * @warning This method is provided only for testing purposes, and should * not be used in released code. If the library is compiled without * debug enabled, local() and realLocalZone() both return the real * local system time zone. * To avoid confusion, it is recommended that calls to * realLocalZone() should be conditionally compiled, e.g.: * \code * #ifndef NDEBUG * tz = KSystemTimeZones::realLocalZone(); * #endif * \endcode * * @see setLocalZone() * @since 4.3 */ static KTimeZone realLocalZone(); /** * Set or clear the simulated local system time zone. * * @warning This method is provided only for testing purposes, and should * not be used in released code. If the library is compiled without * debug enabled, setLocalZone() has no effect. * To avoid confusion, it is recommended that calls to it should be * conditionally compiled, e.g.: * \code * #ifndef NDEBUG * KSystemTimeZones::setLocalZone(tz); * #endif * \endcode * * @param tz the time zone to simulate, or an invalid KTimeZone instance * (i.e. \code tz.isValid() == false \endcode) to cancel * simulation * @since 4.3 */ static void setLocalZone(const KTimeZone& tz); /** * Check whether there is a simulated local system time zone. * * @warning This method is provided only for testing purposes, and should * not be used in released code. If the library is compiled without * debug enabled, isSimulated() always returns false. * To avoid confusion, it is recommended that calls to it should be * conditionally compiled, e.g.: * \code * #ifndef NDEBUG * if (KSystemTimeZones::isSimulated()) * { * ... * } * #endif * \endcode * * @see setLocalZone() * @since 4.3 */ static bool isSimulated(); /** * Returns the location of the system time zone zoneinfo database. * * @return path of directory containing the zoneinfo database */ static QString zoneinfoDir(); /** * Return whether the KDE time zone daemon, ktimezoned, appears to be * available and working. If not, UTC will be the only recognized time * zone. * @since 4.6 */ static bool isTimeZoneDaemonAvailable(); private Q_SLOTS: // Connected to D-Bus signals void configChanged(); void zonetabChanged(const QString &zonetab); void zoneDefinitionChanged(const QString &zone); private: KSystemTimeZones(); KSystemTimeZonesPrivate * const d; friend class KSystemTimeZonesPrivate; }; /** * The KSystemTimeZone class represents a time zone in the system database. * * It works in partnership with the KSystemTimeZoneSource class which reads and parses the * time zone definition files. * * Typically, instances are created and accessed via the KSystemTimeZones class. * * @warning The KSystemTimeZone class uses the standard system libraries to * access time zone data, and its functionality is limited to what these libraries * provide. On many systems, dates earlier than 1970 are not handled, and on * non-GNU systems there is no guarantee that the time zone abbreviation returned * for a given date will be correct if the abbreviations applicable then were * not those currently in use. Consider using KSystemTimeZones::readZone() or the * KTzfileTimeZone class instead, which provide accurate information from the time * zone definition files (but are likely to incur more overhead). * * @short System time zone * @see KSystemTimeZones, KSystemTimeZoneSource, KSystemTimeZoneData, KTzfileTimeZone * @ingroup timezones * @author David Jarvie . */ class KDECORE_EXPORT KSystemTimeZone : public KTimeZone //krazy:exclude=dpointer (no d-pointer for KTimeZone derived classes) { public: /** * Creates a time zone. * * @param source tzfile reader and parser * @param name time zone's unique name * @param countryCode ISO 3166 2-character country code, empty if unknown * @param latitude in degrees (between -90 and +90), UNKNOWN if not known * @param longitude in degrees (between -180 and +180), UNKNOWN if not known * @param comment description of the time zone, if any */ KSystemTimeZone(KSystemTimeZoneSource *source, const QString &name, const QString &countryCode = QString(), float latitude = UNKNOWN, float longitude = UNKNOWN, const QString &comment = QString()); ~KSystemTimeZone(); private: // d-pointer is in KSystemTimeZoneBackend. // This is a requirement for classes inherited from KTimeZone. }; /** * Backend class for KSystemTimeZone class. * * This class implements KSystemTimeZone's constructors and virtual methods. A * backend class is required for all classes inherited from KTimeZone to * allow KTimeZone virtual methods to work together with reference counting of * private data. * * @short Backend class for KSystemTimeZone class * @see KTimeZoneBackend, KSystemTimeZone, KTimeZone * @ingroup timezones * @author David Jarvie . */ class KDECORE_EXPORT KSystemTimeZoneBackend : public KTimeZoneBackend //krazy:exclude=dpointer (non-const d-pointer for KTimeZoneBackend-derived classes) { public: /** Implements KSystemTimeZone::KSystemTimeZone(). */ KSystemTimeZoneBackend(KSystemTimeZoneSource *source, const QString &name, const QString &countryCode, float latitude, float longitude, const QString &comment); ~KSystemTimeZoneBackend(); /** * Creates a copy of this instance. * * @return new copy */ virtual KTimeZoneBackend *clone() const; /** * Returns the class name of the data represented by this instance. * * @return "KSystemTimeZone" */ virtual QByteArray type() const; /** * Implements KSystemTimeZone::offsetAtZoneTime(). * * Returns the offset of this time zone to UTC at the given local date/time. * Because of daylight savings time shifts, the date/time may occur twice. Optionally, * the offsets at both occurrences of @p dateTime are calculated. * * The offset is the number of seconds which you must add to UTC to get * local time in this time zone. * * @param caller calling KSystemTimeZone object * @param zoneDateTime the date/time at which the offset is to be calculated. This * is interpreted as a local time in this time zone. An error * occurs if @p zoneDateTime.timeSpec() is not Qt::LocalTime. * @param secondOffset if non-null, and the @p zoneDateTime occurs twice, receives the * UTC offset for the second occurrence. Otherwise, it is set * the same as the return value. * @return offset in seconds. If @p zoneDateTime occurs twice, it is the offset at the * first occurrence which is returned. */ virtual int offsetAtZoneTime(const KTimeZone *caller, const QDateTime &zoneDateTime, int *secondOffset) const; /** * Implements KSystemTimeZone::offsetAtUtc(). * * Returns the offset of this time zone to UTC at the given UTC date/time. * * The offset is the number of seconds which you must add to UTC to get * local time in this time zone. * * Note that system times are represented using time_t. An error occurs if the date * falls outside the range supported by time_t. * * @param caller calling KSystemTimeZone object * @param utcDateTime the UTC date/time at which the offset is to be calculated. * An error occurs if @p utcDateTime.timeSpec() is not Qt::UTC. * @return offset in seconds, or 0 if error */ virtual int offsetAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const; /** * Implements KSystemTimeZone::offset(). * * Returns the offset of this time zone to UTC at a specified UTC time. * * The offset is the number of seconds which you must add to UTC to get * local time in this time zone. * * @param caller calling KSystemTimeZone object * @param t the UTC time at which the offset is to be calculated, measured in seconds * since 00:00:00 UTC 1st January 1970 (as returned by time(2)) * @return offset in seconds, or 0 if error */ virtual int offset(const KTimeZone *caller, time_t t) const; /** * Implements KSystemTimeZone::isDstAtUtc(). * * Returns whether daylight savings time is in operation at the given UTC date/time. * * Note that system times are represented using time_t. An error occurs if the date * falls outside the range supported by time_t. * * @param caller calling KSystemTimeZone object * @param utcDateTime the UTC date/time. An error occurs if * @p utcDateTime.timeSpec() is not Qt::UTC. * @return @c true if daylight savings time is in operation, @c false otherwise */ virtual bool isDstAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const; /** * Implements KSystemTimeZone::isDst(). * * Returns whether daylight savings time is in operation at a specified UTC time. * * @param caller calling KSystemTimeZone object * @param t the UTC time, measured in seconds since 00:00:00 UTC 1st January 1970 * (as returned by time(2)) * @return @c true if daylight savings time is in operation, @c false otherwise */ virtual bool isDst(const KTimeZone *caller, time_t t) const; private: KSystemTimeZonePrivate *d; // non-const }; /** * A class to read and parse system time zone data. * * Access is performed via the system time zone library functions. * * @short Reads and parses system time zone data * @see KSystemTimeZones, KSystemTimeZone, KSystemTimeZoneData * @ingroup timezones * @author David Jarvie . */ class KDECORE_EXPORT KSystemTimeZoneSource : public KTimeZoneSource { public: /** * Constructs a system time zone source. */ KSystemTimeZoneSource(); virtual ~KSystemTimeZoneSource(); /** * Extract detailed information for one time zone, via the system time zone * library functions. * * @param zone the time zone for which data is to be extracted * @return a KSystemTimeZoneData instance containing the parsed data. * The caller is responsible for deleting the KTimeZoneData instance. * Null is returned on error. */ virtual KTimeZoneData *parse(const KTimeZone &zone) const; /** * Use in conjunction with endParseBlock() to improve efficiency when calling parse() * for a group of KSystemTimeZone instances in succession. * Call startParseBlock() before the first parse(), and call endParseBlock() after the last. * * The effect of calling these methods is to save and restore the TZ environment variable * only once before and after the group of parse() calls, rather than before and * after every call. So, between calls to startParseBlock() and endParseBlock(), do not * call any functions which rely directly or indirectly on the local time zone setting. */ static void startParseBlock(); /** * @see startParseBlock() */ static void endParseBlock(); private: KSystemTimeZoneSourcePrivate * const d; }; /** * @internal * The parsed system time zone data returned by KSystemTimeZoneSource. * * @short Parsed system time zone data * @see KSystemTimeZoneSource, KSystemTimeZone * @ingroup timezones * @author David Jarvie . */ class KSystemTimeZoneData : public KTimeZoneData { friend class KSystemTimeZoneSource; public: KSystemTimeZoneData(); /** Copy constructor; no special ownership assumed. */ KSystemTimeZoneData(const KSystemTimeZoneData &); virtual ~KSystemTimeZoneData(); /** Assignment; no special ownership assumed. Everything is value based. */ KSystemTimeZoneData &operator=(const KSystemTimeZoneData &); /** * Creates a new copy of this object. * The caller is responsible for deleting the copy. * Derived classes must reimplement this method to return a copy of the * calling instance * * @return copy of this instance. This is a KSystemTimeZoneData pointer. */ virtual KTimeZoneData *clone() const; /** * Returns the complete list of time zone abbreviations. * * @return the list of abbreviations */ virtual QList abbreviations() const; virtual QByteArray abbreviation(const QDateTime &utcDateTime) const; /** * Returns the complete list of UTC offsets for the time zone. For system * time zones, significant processing would be required to obtain such a * list, so instead an empty list is returned. * * @return empty list */ virtual QList utcOffsets() const; private: KSystemTimeZoneDataPrivate * const d; }; #endif