/* This file is part of the KDE libraries Copyright (c) 2005-2007 David Jarvie Copyright (c) 2005 S.R.Haque . 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 * Time zone functions * @author David Jarvie . * @author S.R.Haque . */ #ifndef KTIMEZONES_H #define KTIMEZONES_H #include #include #include #include #include #include class KTimeZone; class KTimeZoneBackend; class KTimeZoneData; class KTimeZoneSource; class KTimeZonesPrivate; class KTimeZonePrivate; class KTimeZoneSourcePrivate; class KTimeZoneDataPrivate; class KTimeZoneTransitionPrivate; class KTimeZoneLeapSecondsPrivate; /** @defgroup timezones Time zone classes * * The time zone classes provide a framework for accessing time zone data, and * converting times and dates between different time zones. They provide access * to the system time zone database, and also allow developers to derive classes * to access custom sources of time zone information such as calendar files. * * A time zone is represented by the KTimeZone class. This provides access to * the time zone's detailed definition and contains methods to convert times to * and from that zone. In order to save processing, KTimeZone obtains its time * zone details only when they are actually required. Each KTimeZone class has * a corresponding KTimeZoneBackend backend class which implements reference * counting of the time zone's data. * * A collection of time zones is represented by the KTimeZones class, which acts * as a container of KTimeZone objects. Within any KTimeZones object, each * KTimeZone instance is uniquely identified by its name. Typically, each * individual source of time zone information would be represented by a different * KTimeZones object. This scheme allows conflicting time zone definitions * between the different sources to be handled, since KTimeZone names need only * be unique within a single KTimeZones object. Note that KTimeZone instances do * not have to belong to any KTimeZones container. * * Time zone source data can come in all sorts of different forms: TZFILE format * for a UNIX system time zone database, definitions within calendar files, calls * to libraries (e.g. libc), etc. The KTimeZoneSource class provides reading and * parsing functions to access such data, handing off the parsed data for a * specific time zone in a KTimeZoneData object. Both of these are base classes * from which should be derived other classes which know about the particular * access method and data format (KTimeZoneSource) and which details are actually * provided (KTimeZoneData). When a KTimeZone instance needs its time zone's * definition, it calls KTimeZoneSource::parse() and receives the data back in a * KTimeZoneData object which it keeps for reference. * * KTimeZoneData holds the definitions of the different daylight saving time and * standard time phases in KTimeZone::Phase objects, and the timed sequence of * daylight saving time changes in KTimeZone::Transition objects. Leap seconds * adjustments are held in KTimeZone::LeapSeconds objects. You can access this * data directly via KTimeZone and KTimeZoneData methods if required. * * The mapping of the different classes to external data is as follows: * * - Each different source data format or access method is represented by a * different KTimeZoneSource class. * * - Each different set of data provided from source data is represented by a * different KTimeZoneData class. For example, some time zone sources provide * only the absolute basic information about time zones, i.e. name, transition * times and offsets from UTC. Others provide information on leap second * adjustments, while still others might contain information on which countries * use the time zone. To allow for this variation, KTimeZoneData is made * available for inheritance. When the necessary information is not available, * the KTimeZone::Phase, KTimeZone::Transition and KTimeZone::LeapSeconds data * will be empty. * * - Each KTimeZoneData class will have a corresponding KTimeZone class, and * related KTimeZoneBackend class, which can interpret its data. * * - Each different source database will typically be represented by a different * KTimeZones instance, to avoid possible conflicts between time zone definitions. * If it is known that two source databases are definitely compatible, they can * be grouped together into the same KTimeZones instance. * * * \section sys System time zones * * Access to system time zones is provided by the KSystemTimeZones class, which * reads the zone.tab file to obtain the list of system time zones, and creates a * KTimeZone instance for each one. * * \section deriving Handling time zone data from other sources * * To implement time zone classes to access a new time zone data source, you need * as a minimum to derive a new class from KTimeZoneSource, and implement one or * more parse() methods. If you can know in advance what KTimeZone instances to create * without having to parse the source data, you should reimplement the virtual method * KTimeZoneSource::parse(const KTimeZone&). Otherwise, you need to define your * own parse() methods with appropriate signatures, to both read and parse the new * data, and create new KTimeZone instances. * * If the data for each time zone which is available from the new source happens * to be the same as for another source for which KTimeZone classes already exist, * you could simply use the existing KTimeZone, KTimeZoneBackend and KTimeZoneData * derived classes to receive the parsed data from your new KTimeZoneSource class: * * \code * class NewTimeZoneSource : public KTimeZoneSource * { * public: * NewTimeZoneSource(...); // parameters might include location of data source ... * ~NewTimeZoneSource(); * * // Option 1: reimplement KTimeZoneSource::parse() if you can * // pre-create the KTimeZone instances. * KTimeZoneData *parse(const KTimeZone &zone) const; * * // Option 2: implement new parse() methods if you don't know * // in advance what KTimeZone instances to create. * void parse(..., KTimeZones *zones) const; * NewTimeZone *parse(...) const; * }; * * // Option 1: * KTimeZoneData *NewTimeZoneSource::parse(const KTimeZone &zone) const * { * QString zoneName = zone.name(); * ExistingTimeZoneData* data = new ExistingTimeZoneData(); * * // Read the data for 'zoneName' from the new data source. * * // Parse what we have read, and write it into 'data'. * // Compile the sequence of daylight savings changes and leap * // seconds adjustments (if available) and write into 'data'. * * return data; * } * \endcode * * If the data from the new source is different from what any existing * KTimeZoneData class contains, you will need to implement new KTimeZone, * KTimeZoneBackend and KTimeZoneData classes in addition to the KTimeZoneSource * class illustrated above: * * \code * class NewTimeZone : public KTimeZone * { * public: * NewTimeZone(NewTimeZoneSource *source, const QString &name, ...); * ~NewTimeZone(); * * // Methods implementing KTimeZone virtual methods are implemented * // in NewTimeZoneBackend, not here. * * // Anything else which you need * private: * // No d-pointer ! * }; * * class NewTimeZoneBackend : public KTimeZoneBackend * { * public: * NewTimeZoneBackend(NewTimeZoneSource *source, const QString &name, ...); * ~NewTimeZoneBackend(); * * KTimeZoneBackend *clone() const; * * // Virtual methods which need to be reimplemented * int offsetAtZoneTime(const KTimeZone *caller, const QDateTime &zoneDateTime, int *secondOffset = 0) const; * int offsetAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const; * int offset(const KTimeZone *caller, time_t t) const; * int isDstAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const; * bool isDst(const KTimeZone *caller, time_t t) const; * * // Anything else which you need * private: * NewTimeZonePrivate *d; // non-const ! * }; * * class NewTimeZoneData : public KTimeZoneData * { * friend class NewTimeZoneSource; * * public: * NewTimeZoneData(); * ~NewTimeZoneData(); * * // Virtual methods which need to be reimplemented * KTimeZoneData *clone() const; * QList abbreviations() const; * QByteArray abbreviation(const QDateTime &utcDateTime) const; * * // Data members containing whatever is read by NewTimeZoneSource * }; * \endcode * * Here is a guide to implementing the offset() and offsetAtUtc() methods, in * the case where the source data does not use time_t for its time measurement: * * \code * int NewTimeZoneBackend::offsetAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const * { * // Access this time zone's data. If we haven't already read it, * // force a read from source now. * NewTimeZoneData *zdata = caller->data(true); * * // Use 'zdata' contents to work out the UTC offset * * return offset; * } * * int NewTimeZoneBackend::offset(const KTimeZone *caller, time_t t) const * { * return offsetAtUtc(KTimeZone::fromTime_t(t)); * } * \endcode * * The other NewTimeZoneBackend methods would work in an analogous way to * NewTimeZoneBackend::offsetAtUtc() and NewTimeZoneBackend::offset(). */ /** * The KTimeZones class represents a time zone database which consists of a * collection of individual time zone definitions. * * Each individual time zone is defined in a KTimeZone instance, which provides * generic support for private or system time zones. The time zones in the * collection are indexed by name, which must be unique within the collection. * * Different time zone sources could define the same time zone differently. (For * example, a calendar file originating from another system might hold its own * time zone definitions, which may not necessarily be identical to your own * system's definitions.) In order to keep conflicting definitions separate, * it will often be necessary when dealing with multiple time zone sources to * create a separate KTimeZones instance for each source collection. * * If you want to access system time zones, use the KSystemTimeZones class. * * @short Represents a time zone database or collection * @ingroup timezones * @author David Jarvie . * @author S.R.Haque . */ class KDECORE_EXPORT KTimeZones { public: KTimeZones(); ~KTimeZones(); /** * Returns the time zone with the given name. * * @param name name of time zone * @return time zone, or 0 if not found */ KTimeZone zone(const QString &name) const; /** Map of KTimeZone instances, indexed by time zone name. */ typedef QMap ZoneMap; /** * Returns all the time zones defined in this collection. * * @return time zone collection, indexed by time zone name */ const ZoneMap zones() const; /** * Adds a time zone to the collection. * The time zone's name must be unique within the collection. * * @param zone time zone to add * @return @c true if successful, @c false if zone's name duplicates one already in the collection * @see remove() */ bool add(const KTimeZone &zone); /** * Removes a time zone from the collection. * * @param zone time zone to remove * @return the time zone which was removed, or invalid if not found * @see clear(), add() */ KTimeZone remove(const KTimeZone &zone); /** * Removes a time zone from the collection. * * @param name name of time zone to remove * @return the time zone which was removed, or invalid if not found * @see clear(), add() */ KTimeZone remove(const QString &name); /** * Clears the collection. * * @see remove() */ void clear(); private: KTimeZones(const KTimeZones &); // prohibit copying KTimeZones &operator=(const KTimeZones &); // prohibit copying KTimeZonesPrivate * const d; }; /** * Base class representing a time zone. * * The KTimeZone base class contains general descriptive data about the time zone, and * provides an interface for methods to read and parse time zone definitions, and to * translate between UTC and local time. Derived classes must implement these methods, * and may also hold the actual details of the dates and times of daylight savings * changes, offsets from UTC, etc. They should be tailored to deal with the type and * format of data held by a particular type of time zone database. * * If this base class is instantiated as a valid instance, it always represents the * UTC time zone. * * KTimeZone is designed to work in partnership with KTimeZoneSource. KTimeZone * provides access to individual time zones, while classes derived from * KTimeZoneSource read and parse a particular format of time zone definition. * Because time zone sources can differ in what information they provide about time zones, * the parsed data retured by KTimeZoneSource can vary between different sources, * resulting in the need to create different KTimeZone classes to handle the data. * * KTimeZone instances are often grouped into KTimeZones collections. * * Copying KTimeZone instances is very efficient since the class data is explicitly * shared, meaning that only a pointer to the data is actually copied. To achieve * this, each class inherited from KTimeZone must have a corresponding backend * class derived from KTimeZoneBackend. * * @note Classes derived from KTimeZone should not have their own d-pointer. The * d-pointer is instead contained in their backend class (derived from * KTimeZoneBackend). This allows KTimeZone's reference-counting of private data to * take care of the derived class's data as well, ensuring that instance data is * not deleted while any references to the class instance remains. All virtual * methods which override KTimeZone virtual methods must be defined in the * backend class instead. * * @short Base class representing a time zone * @see KTimeZoneBackend, KTimeZoneSource, KTimeZoneData * @ingroup timezones * @author David Jarvie . * @author S.R.Haque . */ class KDECORE_EXPORT KTimeZone //krazy:exclude=dpointer (has non-const d-pointer to Backend class) { public: /* * Time zone phase. * * A phase can be daylight savings time or standard time. It holds the * UTC offset and time zone abbreviation (e.g. EST, GMT). * * @short Time zone phase * @author David Jarvie . */ class KDECORE_EXPORT Phase { public: /** * Default constructor. * Creates a standard-time time zone phase with UTC offset 0. */ Phase(); /** * Constructor. * * @param utcOffset number of seconds to add to UTC to get local time in this phase * @param abbreviations time zone abbreviation for this phase. If translations exist, * concatenate all abbreviations as null-terminated strings. * @param dst true if daylight savings time, false if standard time * @param comment optional comment */ Phase(int utcOffset, const QByteArray &abbreviations, bool dst, const QString &comment = QString()); /** * Constructor. * * @param utcOffset number of seconds to add to UTC to get local time in this phase * @param abbreviations time zone abbreviation for this phase, plus any translations * @param dst true if daylight savings time, false if standard time * @param comment optional comment */ Phase(int utcOffset, const QList &abbreviations, bool dst, const QString &comment = QString()); Phase(const Phase &rhs); ~Phase(); Phase &operator=(const Phase &rhs); bool operator==(const Phase &rhs) const; bool operator!=(const Phase &rhs) const { return !operator==(rhs); } /** * Return the UTC offset in seconds during this phase. * The UTC offset is the number of seconds which you must add to UTC * to get local time. * * @return offset in seconds to add to UTC */ int utcOffset() const; /** * Return the time zone abbreviations which apply to this phase. * * More than one abbreviation may be returned, to allow for possible translations. * * @return time zone abbreviations */ QList abbreviations() const; /** * Return whether daylight savings time applies during this phase. * * @return true if daylight savings are in operation, false otherwise */ bool isDst() const; /** * Return the comment (if any) applying to this phase. * * @return comment */ QString comment() const; private: QSharedDataPointer d; }; /* * Time zone daylight saving time transition. * * A Transition instance holds details of a transition to daylight saving time or * standard time, including the UTC time of the change. * * @short Time zone transition * @author David Jarvie . */ class KDECORE_EXPORT Transition { public: Transition(); Transition(const QDateTime &dt, const Phase &phase); Transition(const KTimeZone::Transition &t); ~Transition(); Transition &operator=(const KTimeZone::Transition &t); /** * Return the UTC time of the transition. * * @return UTC time */ QDateTime time() const; /** * Return the time zone phase which takes effect after the transition. * * @return time zone phase */ Phase phase() const; /** * Compare the date/time values of two transitions. * * @param rhs other instance * @return @c true if this Transition is earlier than @p rhs */ bool operator<(const Transition &rhs) const; private: KTimeZoneTransitionPrivate *const d; }; /* * Leap seconds adjustment for a time zone. * * This class defines a leap seconds adjustment for a time zone by its UTC time of * occurrence and the cumulative number of leap seconds to be added at that time. * * @short Leap seconds adjustment for a time zone * @see KTimeZone, KTimeZoneData * @ingroup timezones * @author David Jarvie . */ class KDECORE_EXPORT LeapSeconds { public: LeapSeconds(); LeapSeconds(const QDateTime &utcTime, int leapSeconds, const QString &comment = QString()); LeapSeconds(const LeapSeconds &c); ~LeapSeconds(); LeapSeconds &operator=(const LeapSeconds &c); bool operator<(const LeapSeconds &c) const; // needed by qSort() /** * Return whether this instance holds valid data. * * @return true if valid, false if invalid */ bool isValid() const; /** * Return the UTC date/time when this change occurred. * * @return date/time */ QDateTime dateTime() const; /** * Return the cumulative number of leap seconds to be added after this * change occurs. * * @return number of leap seconds */ int leapSeconds() const; /** * Return the comment (if any) applying to this change. * * @return comment */ QString comment() const; private: KTimeZoneLeapSecondsPrivate *const d; }; /** * Constructs a null time zone. A null time zone is invalid. * * @see isValid() */ KTimeZone(); /** * Constructs a UTC time zone. * * @param name name of the UTC time zone */ explicit KTimeZone(const QString &name); /** * Creates a time zone. * * @param source tzfile reader and parser * @param name time zone's unique name, which must be the tzfile path relative * to the location specified for @p source * @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 */ KTimeZone(KTimeZoneSource *source, const QString &name, const QString &countryCode = QString(), float latitude = UNKNOWN, float longitude = UNKNOWN, const QString &comment = QString()); KTimeZone(const KTimeZone &tz); KTimeZone &operator=(const KTimeZone &tz); virtual ~KTimeZone(); /** * Checks whether this is the same instance as another one. * Note that only the pointers to the time zone data are compared, not the * contents. So it will only return equality if one instance was copied * from the other. * * @param rhs other instance * @return true if the same instance, else false */ bool operator==(const KTimeZone &rhs) const; bool operator!=(const KTimeZone &rhs) const { return !operator==(rhs); } /** * Returns the class name of the data represented by this instance. * If a derived class object has been assigned to this instance, this * method will return the name of that class. * * @return "KTimeZone" or the class name of a derived class */ QByteArray type() const; /** * Checks whether the instance is valid. * * @return true if valid, false if invalid */ bool isValid() const; /** * Returns the name of the time zone. * If it is held in a KTimeZones container, the name is the time zone's unique * identifier within that KTimeZones instance. * * @return name in system-dependent format */ QString name() const; /** * Returns the two-letter country code of the time zone. * * @return upper case ISO 3166 2-character country code, empty if unknown */ QString countryCode() const; /** * Returns the latitude of the time zone. * * @return latitude in degrees, UNKNOWN if not known */ float latitude() const; /** * Returns the latitude of the time zone. * * @return latitude in degrees, UNKNOWN if not known */ float longitude() const; /** * Returns any comment for the time zone. * * @return comment, may be empty */ QString comment() const; /** * Returns the list of time zone abbreviations used by the time zone. * This may include historical ones which are no longer in use or have * been superseded. * * @return list of abbreviations * @see abbreviation() */ QList abbreviations() const; /** * Returns the time zone abbreviation current at a specified time. * * @param utcDateTime UTC date/time. An error occurs if * @p utcDateTime.timeSpec() is not Qt::UTC. * @return time zone abbreviation, or empty string if error * @see abbreviations() */ QByteArray abbreviation(const QDateTime &utcDateTime) const; /** * Returns the complete list of UTC offsets used by the time zone. This may * include historical ones which are no longer in use or have been * superseded. * * A UTC offset is the number of seconds which you must add to UTC to get * local time in this time zone. * * If due to the nature of the source data for the time zone, compiling a * complete list would require significant processing, an empty list is * returned instead. * * @return sorted list of UTC offsets, or empty list if not readily available. */ QList utcOffsets() const; /** * Converts a date/time, which is interpreted as being local time in this * time zone, into local time in another time zone. * * @param newZone other time zone which the time is to be converted into * @param zoneDateTime local date/time. An error occurs if * @p zoneDateTime.timeSpec() is not Qt::LocalTime. * @return converted date/time, or invalid date/time if error * @see toUtc(), toZoneTime() */ QDateTime convert(const KTimeZone &newZone, const QDateTime &zoneDateTime) const; /** * Converts a date/time, which is interpreted as local time in this time * zone, into UTC. * * Because of daylight savings time shifts, the date/time may occur twice. In * such cases, this method returns the UTC time for the first occurrence. * If you need the UTC time of the second occurrence, use offsetAtZoneTime(). * * @param zoneDateTime local date/time. An error occurs if * @p zoneDateTime.timeSpec() is not Qt::LocalTime. * @return UTC date/time, or invalid date/time if error * @see toZoneTime(), convert() */ QDateTime toUtc(const QDateTime &zoneDateTime) const; /** * Converts a UTC date/time into local time in this time zone. * * Because of daylight savings time shifts, some local date/time values occur * twice. The @p secondOccurrence parameter may be used to determine whether * the time returned is the first or second occurrence of that time. * * @param utcDateTime UTC date/time. An error occurs if * @p utcDateTime.timeSpec() is not Qt::UTC. * @param secondOccurrence if non-null, returns @p true if the return value * is the second occurrence of that time, else @p false * @return local date/time, or invalid date/time if error * @see toUtc(), convert() */ QDateTime toZoneTime(const QDateTime &utcDateTime, bool *secondOccurrence = 0) const; /** * Returns the current offset of this time zone to UTC or the local * system time zone. The offset is the number of seconds which you must * add to UTC or the local system time to get local time in this time zone. * * Take care if you cache the results of this routine; that would * break if the result were stored across a daylight savings change. * * @param basis Qt::UTC to return the offset to UTC, Qt::LocalTime * to return the offset to local system time * @return offset in seconds * @see offsetAtZoneTime(), offsetAtUtc() */ int currentOffset(Qt::TimeSpec basis = Qt::UTC) const; /** * 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 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. If @p zoneDateTime does not exist because * of daylight savings time shifts, InvalidOffset is returned. If any other error * occurs, 0 is returned. * @see offsetAtUtc(), currentOffset() */ virtual int offsetAtZoneTime(const QDateTime &zoneDateTime, int *secondOffset = 0) const; /** * 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. * * If a derived class needs to work in terms of time_t (as when accessing the * system time functions, for example), it should override both this method and * offset() so as to implement its offset calculations in offset(), and * reimplement this method simply as * \code * offset(toTime_t(utcDateTime)); * \endcode * * @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 * @see offset(), offsetAtZoneTime(), currentOffset() */ virtual int offsetAtUtc(const QDateTime &utcDateTime) const; /** * 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. * * Note that time_t has a more limited range than QDateTime, so consider using * offsetAtUtc() instead. * * @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 * @see offsetAtUtc() */ virtual int offset(time_t t) const; /** * Returns whether daylight savings time is in operation at the given UTC date/time. * * If a derived class needs to work in terms of time_t (as when accessing the * system time functions, for example), it should override both this method and * isDst() so as to implement its offset calculations in isDst(), and reimplement * this method simply as * \code * isDst(toTime_t(utcDateTime)); * \endcode * * @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 * @see isDst() */ virtual bool isDstAtUtc(const QDateTime &utcDateTime) const; /** * Returns whether daylight savings time is in operation at a specified UTC time. * * Note that time_t has a more limited range than QDateTime, so consider using * isDstAtUtc() instead. * * @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 * @see isDstAtUtc() */ virtual bool isDst(time_t t) const; /** * Return all daylight savings time phases for the time zone. * * Note that some time zone data sources (such as system time zones accessed * via the system libraries) may not allow a list of daylight savings time * changes to be compiled easily. In such cases, this method will return an * empty list. * * @return list of phases */ QList phases() const; /** * Return whether daylight saving transitions are available for the time zone. * * The base class returns @c false. * * @return @c true if transitions are available, @c false if not * @see transitions(), transition() */ virtual bool hasTransitions() const; /** * Return all daylight saving transitions, in time order. If desired, the * transitions returned may be restricted to a specified time range. * * Note that some time zone data sources (such as system time zones accessed * via the system libraries) may not allow a list of daylight saving time * changes to be compiled easily. In such cases, this method will return an * empty list. * * @param start start UTC date/time, or invalid date/time to return all transitions * up to @p end. @p start.timeSpec() must be Qt::UTC, else * @p start will be considered invalid. * @param end end UTC date/time, or invalid date/time for no end. @p end.timeSpec() * must be Qt::UTC, else @p end will be considered invalid. * @return list of transitions, in time order * @see hasTransitions(), transition(), transitionTimes() */ QList transitions(const QDateTime &start = QDateTime(), const QDateTime &end = QDateTime()) const; /** * Find the last daylight savings time transition at or before a given * UTC or local time. * * Because of daylight savings time shifts, a local time may occur twice or * may not occur at all. In the former case, the transitions at or before * both occurrences of @p dt may optionally be calculated and returned in * @p secondTransition. The latter case may optionally be detected by use of * @p validTime. * * @param dt date/time. @p dt.timeSpec() may be set to Qt::UTC or Qt::LocalTime. * @param secondTransition if non-null, and the @p dt occurs twice, receives the * transition for the second occurrence. Otherwise, it is set * the same as the return value. * @param validTime if non-null, is set to false if @p dt does not occur, or * to true otherwise * @return time zone transition, or null either if @p dt is either outside the * defined range of the transition data or if @p dt does not occur * @see transitionIndex(), hasTransitions(), transitions() */ const KTimeZone::Transition *transition(const QDateTime &dt, const Transition **secondTransition = 0, bool *validTime = 0) const; /** * Find the index to the last daylight savings time transition at or before * a given UTC or local time. The return value is the index into the transition * list returned by transitions(). * * Because of daylight savings time shifts, a local time may occur twice or * may not occur at all. In the former case, the transitions at or before * both occurrences of @p dt may optionally be calculated and returned in * @p secondIndex. The latter case may optionally be detected by use of * @p validTime. * * @param dt date/time. @p dt.timeSpec() may be set to Qt::UTC or Qt::LocalTime. * @param secondIndex if non-null, and the @p dt occurs twice, receives the * index to the transition for the second occurrence. Otherwise, * it is set the same as the return value. * @param validTime if non-null, is set to false if @p dt does not occur, or * to true otherwise * @return index into the time zone transition list, or -1 either if @p dt is * either outside the defined range of the transition data or if @p dt * does not occur * @see transition(), transitions(), hasTransitions() */ int transitionIndex(const QDateTime &dt, int *secondIndex = 0, bool *validTime = 0) const; /** * Return the times of all daylight saving transitions to a given time zone * phase, in time order. If desired, the times returned may be restricted to * a specified time range. * * Note that some time zone data sources (such as system time zones accessed * via the system libraries) may not allow a list of daylight saving time * changes to be compiled easily. In such cases, this method will return an * empty list. * * @param phase time zone phase * @param start start UTC date/time, or invalid date/time to return all transitions * up to @p end. @p start.timeSpec() must be Qt::UTC, else * @p start will be considered invalid. * @param end end UTC date/time, or invalid date/time for no end. @p end.timeSpec() * must be Qt::UTC, else @p end will be considered invalid. * @return ordered list of transition times * @see hasTransitions(), transition(), transitions() */ QList transitionTimes(const Phase &phase, const QDateTime &start = QDateTime(), const QDateTime &end = QDateTime()) const; /** * Return all leap second adjustments, in time order. * * Note that some time zone data sources (such as system time zones accessed * via the system libraries) may not provide information on leap second * adjustments. In such cases, this method will return an empty list. * * @return list of adjustments */ QList leapSecondChanges() const; /** * Returns the source reader/parser for the time zone's source database. * * @return reader/parser */ KTimeZoneSource *source() const; /** * Extracts time zone detail information for this time zone from the source database. * * @return @c false if the parse encountered errors, @c true otherwise */ bool parse() const; /** * Returns the detailed parsed data for the time zone. * This will return null unless either parse() has been called beforehand, or * @p create is true. * * @param create true to parse the zone's data first if not already parsed * @return pointer to data, or null if data has not been parsed */ const KTimeZoneData *data(bool create = false) const; /** * Update the definition of the time zone to be identical to another * KTimeZone instance. A prerequisite is that the two instances must * have the same name. * * The main purpose of this method is to allow updates of the time zone * definition by derived classes without invalidating pointers to the * instance (particularly pointers held by KDateTime objects). Note * that the KTimeZoneData object and KTimeZoneSource pointer are not * updated: the caller class should do this itself by calling setData(). * * @param other time zone whose definition is to be used * @return true if definition was updated (i.e. names are the same) * * @see setData() */ bool updateBase(const KTimeZone &other); /** * Converts a UTC time, measured in seconds since 00:00:00 UTC 1st January 1970 * (as returned by time(2)), to a UTC QDateTime value. * QDateTime::setTime_t() is limited to handling @p t >= 0, since its parameter * is unsigned. This method takes a parameter of time_t which is signed. * * @return converted time * @see toTime_t() */ static QDateTime fromTime_t(time_t t); /** * Converts a UTC QDateTime to a UTC time, measured in seconds since 00:00:00 UTC * 1st January 1970 (as returned by time(2)). * QDateTime::toTime_t() returns an unsigned value. This method returns a time_t * value, which is signed. * * @param utcDateTime date/time. An error occurs if @p utcDateTime.timeSpec() is * not Qt::UTC. * @return converted time, or -1 if the date is out of range for time_t or * @p utcDateTime.timeSpec() is not Qt::UTC * @see fromTime_t() */ static time_t toTime_t(const QDateTime &utcDateTime); /** * Returns a standard UTC time zone, with name "UTC". * * @note The KTimeZone returned by this method does not belong to any * KTimeZones collection. Any KTimeZones instance may contain its own UTC * KTimeZone defined by its time zone source data, but that will be a * different instance than this KTimeZone. * * @return UTC time zone */ static KTimeZone utc(); /** Indicates an invalid UTC offset. This is returned by offsetAtZoneTime() when * the local time does not occur due to a shift to daylight savings time. */ static const int InvalidOffset; /** Indicates an invalid time_t value. */ static const time_t InvalidTime_t; /** * A representation for unknown locations; this is a float * that does not represent a real latitude or longitude. */ static const float UNKNOWN; protected: KTimeZone(KTimeZoneBackend *impl); /** * Sets the detailed parsed data for the time zone, and optionally * a new time zone source object. * * @param data parsed data * @param source if non-null, the new source object for the time zone * * @see data() */ void setData(KTimeZoneData *data, KTimeZoneSource *source = 0); private: KTimeZoneBackend *d; }; /** * Base backend class for KTimeZone classes. * * KTimeZone and each class inherited from it must have a corresponding * backend class to implement its constructors and its virtual methods, * and to provide a virtual clone() method. This allows KTimeZone virtual methods * to work together with reference counting of private data. * * @note Classes derived from KTimeZoneBackend should not normally implement their * own copy constructor or assignment operator, and must have a non-const d-pointer. * * @short Base backend class for KTimeZone classes * @see KTimeZone * @ingroup timezones * @author David Jarvie . */ class KDECORE_EXPORT KTimeZoneBackend //krazy:exclude=dpointer (non-const d-pointer for KTimeZoneBackend-derived classes) { public: /** Implements KTimeZone::KTimeZone(). */ KTimeZoneBackend(); /** Implements KTimeZone::KTimeZone(const QString&). */ explicit KTimeZoneBackend(const QString &name); /** * Constructs a time zone. * * @param source reader/parser for the database containing this time zone. This will * be an instance of a class derived from KTimeZoneSource. * @param name in system-dependent format. The name must be unique within any * KTimeZones instance which contains this KTimeZone. * @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 */ KTimeZoneBackend(KTimeZoneSource *source, const QString &name, const QString &countryCode = QString(), float latitude = KTimeZone::UNKNOWN, float longitude = KTimeZone::UNKNOWN, const QString &comment = QString()); KTimeZoneBackend(const KTimeZoneBackend &other); KTimeZoneBackend &operator=(const KTimeZoneBackend &other); virtual ~KTimeZoneBackend(); /** * Creates a copy of this instance. * * @note Every inherited class must reimplement clone(). * * @return new copy */ virtual KTimeZoneBackend *clone() const; /** * Returns the class name of the data represented by this instance. * * @note Every inherited class must reimplement type(). * * This base class returns "KTimeZone". * * @return the class name */ virtual QByteArray type() const; /** * Implements KTimeZone::offsetAtZoneTime(). * * @param caller calling KTimeZone object */ virtual int offsetAtZoneTime(const KTimeZone* caller, const QDateTime &zoneDateTime, int *secondOffset) const; /** * Implements KTimeZone::offsetAtUtc(). * * @param caller calling KTimeZone object */ virtual int offsetAtUtc(const KTimeZone* caller, const QDateTime &utcDateTime) const; /** * Implements KTimeZone::offset(). * * @param caller calling KTimeZone object */ virtual int offset(const KTimeZone* caller, time_t t) const; /** * Implements KTimeZone::isDstAtUtc(). * * @param caller calling KTimeZone object */ virtual bool isDstAtUtc(const KTimeZone* caller, const QDateTime &utcDateTime) const; /** * Implements KTimeZone::isDst(). * * @param caller calling KTimeZone object */ virtual bool isDst(const KTimeZone* caller, time_t t) const; /** * Implements KTimeZone::hasTransitions(). * * @param caller calling KTimeZone object */ virtual bool hasTransitions(const KTimeZone* caller) const; private: KTimeZonePrivate *d; // non-const friend class KTimeZone; }; /** * Base class representing a source of time zone information. * * Derive subclasses from KTimeZoneSource to read and parse time zone details * from a time zone database or other source of time zone information. If can know * in advance what KTimeZone instances to create without having to parse the source * data, you should reimplement the virtual method parse(const KTimeZone&). Otherwise, * you need to define your own parse() methods with appropriate signatures, to both * read and parse the new data, and create new KTimeZone instances. * * KTimeZoneSource itself may be used as a dummy source which returns empty * time zone details. * * @short Base class representing a source of time zone information * @see KTimeZone, KTimeZoneData * @ingroup timezones * @author David Jarvie . * @author S.R.Haque . */ class KDECORE_EXPORT KTimeZoneSource { public: KTimeZoneSource(); /** * Constructs a time zone source. * * The directory containing the time zone definition files is given by the * @p location parameter, which will usually be the zoneinfo directory. For * tzfile files in other locations, bear in mind that the name generated * for each KTimeZone is its file path relative to @p location. * * @param location the local directory containing the time zone definition files */ explicit KTimeZoneSource(const QString &location); virtual ~KTimeZoneSource(); /** * Extracts detail information for one time zone from the source database. * * In this base class, the method always succeeds and returns an empty data * instance. Derived classes should reimplement this method to return an * appropriate data class derived from KTimeZoneData. Some source databases * may not be compatible with this method of parsing. In these cases, they * should use the constructor KTimeZoneSource(false) and calling this method * will produce a fatal error. * * @param zone the time zone for which data is to be extracted. * @return an instance of a class derived from KTimeZoneData 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; /** * Return whether the source database supports the ad hoc extraction of data for * individual time zones using parse(const KTimeZone&). * * @return true if parse(const KTimeZone&) works, false if parsing must be * performed by other methods */ bool useZoneParse() const; /** * Returns the local directory containing the time zone definition files. * * @return path to time zone definition files */ QString location() const; protected: /** * Constructor for use by derived classes, which specifies whether the * source database supports the ad hoc extraction of data for individual * time zones using parse(const KTimeZone&). * * If parse(const KTimeZone&) cannot be used, KTimeZone derived classes * which use this KTimeZoneSource derived class must create a * KTimeZoneData object at construction time so that KTimeZone::data() * will always return a data object. * * Note the default constructor is equivalent to KTimeZoneSource(true), i.e. * it is only necessary to use this constructor if parse(const KTimeZone&) * does not work. * * @param useZoneParse true if parse(const KTimeZone&) works, false if * parsing must be performed by other methods */ explicit KTimeZoneSource(bool useZoneParse); private: KTimeZoneSourcePrivate * const d; }; /** * Base class for the parsed data returned by a KTimeZoneSource class. * * It contains all the data available from the KTimeZoneSource class, * including, when available, a complete list of daylight savings time * changes and leap seconds adjustments. * * This base class can be instantiated, but contains no data. * * @short Base class for parsed time zone data * @see KTimeZone, KTimeZoneSource * @ingroup timezones * @author David Jarvie . */ class KDECORE_EXPORT KTimeZoneData { friend class KTimeZone; public: KTimeZoneData(); KTimeZoneData(const KTimeZoneData &c); virtual ~KTimeZoneData(); KTimeZoneData &operator=(const KTimeZoneData &c); /** * 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 */ virtual KTimeZoneData *clone() const; /** * Returns the complete list of time zone abbreviations. This may include * translations. * * @return the list of abbreviations. * In this base class, it consists of the single string "UTC". * @see abbreviation() */ virtual QList abbreviations() const; /** * Returns the time zone abbreviation current at a specified time. * * @param utcDateTime UTC date/time. An error occurs if * @p utcDateTime.timeSpec() is not Qt::UTC. * @return time zone abbreviation, or empty string if error * @see abbreviations() */ virtual QByteArray abbreviation(const QDateTime &utcDateTime) const; /** * Returns the complete list of UTC offsets for the time zone, if the time * zone's source makes such information readily available. If compiling a * complete list would require significant processing, an empty list is * returned instead. * * @return sorted list of UTC offsets, or empty list if not readily available. * In this base class, it consists of the single value 0. */ virtual QList utcOffsets() const; /** * Returns the UTC offset to use before the start of data for the time zone. * * @return UTC offset */ int previousUtcOffset() const; /** * Return all daylight savings time phases. * * Note that some time zone data sources (such as system time zones accessed * via the system libraries) may not allow a list of daylight savings time * changes to be compiled easily. In such cases, this method will return an * empty list. * * @return list of phases */ QList phases() const; /** * Return whether daylight saving transitions are available for the time zone. * * The base class returns @c false. * * @return @c true if transitions are available, @c false if not * @see transitions(), transition() */ virtual bool hasTransitions() const; /** * Return all daylight saving transitions, in time order. If desired, the * transitions returned may be restricted to a specified time range. * * Note that some time zone data sources (such as system time zones accessed * via the system libraries) may not allow a list of daylight saving time * changes to be compiled easily. In such cases, this method will return an * empty list. * * @param start start date/time, or invalid date/time to return all transitions up * to @p end. @p start.timeSpec() must be Qt::UTC, else * @p start will be considered invalid. * @param end end date/time, or invalid date/time for no end. @p end.timeSpec() * must be Qt::UTC, else @p end will be considered invalid. * @return list of transitions, in time order * @see hasTransitions(), transition(), transitionTimes() */ QList transitions(const QDateTime &start = QDateTime(), const QDateTime &end = QDateTime()) const; /** * Find the last daylight savings time transition at or before a given * UTC or local time. * * Because of daylight savings time shifts, a local time may occur twice or * may not occur at all. In the former case, the transitions at or before * both occurrences of @p dt may optionally be calculated and returned in * @p secondTransition. The latter case may optionally be detected by use of * @p validTime. * * @param dt date/time. @p dt.timeSpec() may be set to Qt::UTC or Qt::LocalTime. * @param secondTransition if non-null, and the @p dt occurs twice, receives the * transition for the second occurrence. Otherwise, it is set * the same as the return value. * @param validTime if non-null, is set to false if @p dt does not occur, or * to true otherwise * @return time zone transition, or null either if @p dt is either outside the * defined range of the transition data or if @p dt does not occur * @see transitionIndex(), hasTransitions(), transitions() */ const KTimeZone::Transition *transition(const QDateTime &dt, const KTimeZone::Transition **secondTransition = 0, bool *validTime = 0) const; /** * Find the index to the last daylight savings time transition at or before * a given UTC or local time. The return value is the index into the transition * list returned by transitions(). * * Because of daylight savings time shifts, a local time may occur twice or * may not occur at all. In the former case, the transitions at or before * both occurrences of @p dt may optionally be calculated and returned in * @p secondIndex. The latter case may optionally be detected by use of * @p validTime. * * @param dt date/time. @p dt.timeSpec() may be set to Qt::UTC or Qt::LocalTime. * @param secondIndex if non-null, and the @p dt occurs twice, receives the * index to the transition for the second occurrence. Otherwise, * it is set the same as the return value. * @param validTime if non-null, is set to false if @p dt does not occur, or * to true otherwise * @return index into the time zone transition list, or -1 either if @p dt is * either outside the defined range of the transition data or if @p dt * does not occur * @see transition(), transitions(), hasTransitions() */ int transitionIndex(const QDateTime &dt, int *secondIndex = 0, bool *validTime = 0) const; /** * Return the times of all daylight saving transitions to a given time zone * phase, in time order. If desired, the times returned may be restricted to * a specified time range. * * Note that some time zone data sources (such as system time zones accessed * via the system libraries) may not allow a list of daylight saving time * changes to be compiled easily. In such cases, this method will return an * empty list. * * @param phase time zone phase * @param start start UTC date/time, or invalid date/time to return all transitions * up to @p end. @p start.timeSpec() must be Qt::UTC, else * @p start will be considered invalid. * @param end end UTC date/time, or invalid date/time for no end. @p end.timeSpec() * must be Qt::UTC, else @p end will be considered invalid. * @return ordered list of transition times * @see hasTransitions(), transition(), transitions() */ QList transitionTimes(const KTimeZone::Phase &phase, const QDateTime &start = QDateTime(), const QDateTime &end = QDateTime()) const; /** * Return all leap second adjustments, in time order. * * Note that some time zone data sources (such as system time zones accessed * via the system libraries) may not provide information on leap second * adjustments. In such cases, this method will return an empty list. * * @return list of adjustments */ QList leapSecondChanges() const; /** * Find the leap second adjustment which is applicable at a given UTC time. * * @param utc UTC date/time. An error occurs if @p utc.timeSpec() is not Qt::UTC. * @return leap second adjustment, or invalid if @p utc is earlier than the * first leap second adjustment or @p utc is a local time */ KTimeZone::LeapSeconds leapSecondChange(const QDateTime &utc) const; protected: /** * Initialise the daylight savings time phase list. * * @param phases list of phases * @param previousPhase phase to use before the first daylight savings time * transition * @see phases() * @since 4.8.3 */ void setPhases(const QList &phases, const KTimeZone::Phase& previousPhase); /** * Initialise the daylight savings time phase list. * This setPhases() variant should be used when the time zone abbreviation * used before the start of the first phase is not known. * * @param phases list of phases * @param previousUtcOffset UTC offset to use before the start of the first * phase * @see phases() */ void setPhases(const QList &phases, int previousUtcOffset); /** * Initialise the daylight savings time transition list. * * @param transitions list of transitions * @see transitions() */ void setTransitions(const QList &transitions); /** * Initialise the leap seconds adjustment list. * * @param adjusts list of adjustments * @see leapSecondChanges() */ void setLeapSecondChanges(const QList &adjusts); private: friend KTimeZoneSource; KTimeZoneDataPrivate * const d; }; #endif