1 | /* |
2 | This file is part of the KDE libraries |
3 | Copyright (c) 2005-2007,2009-2012 David Jarvie <djarvie@kde.org> |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Library General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2 of the License, or (at your option) any later version. |
9 | |
10 | This library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Library General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Library General Public License |
16 | along with this library; see the file COPYING.LIB. If not, write to |
17 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | Boston, MA 02110-1301, USA. |
19 | */ |
20 | |
21 | /** @file |
22 | * System time zone functions |
23 | * @author David Jarvie <djarvie@kde.org>. |
24 | * @author S.R.Haque <srhaque@iee.org>. |
25 | */ |
26 | |
27 | #ifndef _KSYSTEMTIMEZONE_H |
28 | #define _KSYSTEMTIMEZONE_H |
29 | |
30 | #include <kdecore_export.h> |
31 | #include "ktimezone.h" |
32 | |
33 | #include <QtCore/QObject> |
34 | #include <QtCore/QDateTime> |
35 | #include <QtCore/QList> |
36 | #include <QtCore/QString> |
37 | #include <QtCore/QByteArray> |
38 | |
39 | class KSystemTimeZoneSource; |
40 | class KSystemTimeZonePrivate; |
41 | class KSystemTimeZonesPrivate; |
42 | class KSystemTimeZoneSourcePrivate; |
43 | class KSystemTimeZoneDataPrivate; |
44 | |
45 | /** |
46 | * The KSystemTimeZones class represents the system time zone database, consisting |
47 | * of a collection of individual system time zone definitions, indexed by name. |
48 | * Each individual time zone is defined in a KSystemTimeZone or KTzfileTimeZone |
49 | * instance. Additional time zones (of any class derived from KTimeZone) may be |
50 | * added if desired. |
51 | * |
52 | * At initialisation, KSystemTimeZones on UNIX systems reads the zone.tab file |
53 | * to obtain the list of system time zones, and creates a KTzfileTimeZone |
54 | * instance for each one. |
55 | * |
56 | * @note KSystemTimeZones gets the system's time zone configuration, including |
57 | * the current local system time zone and the location of zone.tab, from the KDE |
58 | * time zone daemon, ktimezoned. If ktimezoned cannot be started, KSystemTimeZones |
59 | * will only know about the UTC time zone. |
60 | * |
61 | * Note that KSystemTimeZones is not derived from KTimeZones, but instead contains |
62 | * a KTimeZones instance which holds the system time zone database. Convenience |
63 | * static methods are defined to access its data, or alternatively you can access |
64 | * the KTimeZones instance directly via the timeZones() method. |
65 | * |
66 | * As an example, find the local time in Oman corresponding to the local system |
67 | * time of 12:15:00 on 13th November 1999: |
68 | * \code |
69 | * QDateTime sampleTime(QDate(1999,11,13), QTime(12,15,0), Qt::LocalTime); |
70 | * KTimeZone local = KSystemTimeZones::local(); |
71 | * KTimeZone oman = KSystemTimeZones::zone("Asia/Muscat"); |
72 | * QDateTime omaniTime = local.convert(oman, sampleTime); |
73 | * \endcode |
74 | * |
75 | * @note KTzfileTimeZone is used in preference to KSystemTimeZone on UNIX |
76 | * systems since use of the standard system libraries by KSystemTimeZone |
77 | * requires the use of tzset() in several methods. That function reads and |
78 | * parses the local system time zone definition file every time it is called, |
79 | * and this has been observed to make applications hang for many seconds when |
80 | * a large number of KSystemTimeZone calls are made in succession. |
81 | * |
82 | * @note This class provides a facility to simulate the local system time |
83 | * zone. This facility is provided for testing purposes only, and is only |
84 | * available if the library is compiled with debug enabled. In release mode, |
85 | * simulation is inoperative and the real local system time zone is used at all |
86 | * times. |
87 | * |
88 | * @short System time zone access |
89 | * @see KTimeZones, KSystemTimeZone, KSystemTimeZoneSource, KTzfileTimeZone |
90 | * @ingroup timezones |
91 | * @author David Jarvie <djarvie@kde.org>. |
92 | * @author S.R.Haque <srhaque@iee.org>. |
93 | */ |
94 | class KDECORE_EXPORT KSystemTimeZones : public QObject |
95 | { |
96 | Q_OBJECT |
97 | public: |
98 | ~KSystemTimeZones(); |
99 | |
100 | /** |
101 | * Returns the unique KTimeZones instance containing the system time zones |
102 | * collection. It is first created if it does not already exist. |
103 | * |
104 | * @return time zones. |
105 | */ |
106 | static KTimeZones *timeZones(); |
107 | |
108 | /** |
109 | * Returns all the time zones defined in this collection. |
110 | * |
111 | * @return time zone collection |
112 | */ |
113 | static const KTimeZones::ZoneMap zones(); |
114 | |
115 | /** |
116 | * Returns the time zone with the given name. |
117 | * |
118 | * The time zone definition is obtained using system library calls, and may |
119 | * not contain historical data. If you need historical time change data, |
120 | * use the potentially slower method readZone(). |
121 | * |
122 | * @param name name of time zone |
123 | * @return time zone (usually a KSystemTimeZone instance), or invalid if not found |
124 | * @see readZone() |
125 | */ |
126 | static KTimeZone zone(const QString &name); |
127 | |
128 | /** |
129 | * Returns the time zone with the given name, containing the full time zone |
130 | * definition read directly from the system time zone database. This may |
131 | * incur a higher overhead than zone(), but will provide whatever historical |
132 | * data the system holds. |
133 | * |
134 | * @param name name of time zone |
135 | * @return time zone (usually a KTzfileTimeZone instance), or invalid if not found |
136 | * @see zone() |
137 | */ |
138 | static KTimeZone readZone(const QString &name); |
139 | |
140 | /** |
141 | * Returns the current local system time zone. |
142 | * |
143 | * The idea of this routine is to provide a robust lookup of the local time |
144 | * zone. On Unix systems, there are a variety of mechanisms for setting this |
145 | * information, and no well defined way of getting it. For example, if you |
146 | * set your time zone to "Europe/London", then the tzname[] maintained by |
147 | * tzset() typically returns { "GMT", "BST" }. The function of this routine |
148 | * is to actually return "Europe/London" (or rather, the corresponding |
149 | * KTimeZone). |
150 | * |
151 | * Note that depending on how the system stores its current time zone, this |
152 | * routine may return a synonym of the expected time zone. For example, |
153 | * "Europe/London", "Europe/Guernsey" and some other time zones are all |
154 | * identical and there may be no way for the routine to distinguish which |
155 | * of these is the correct zone name from the user's point of view. |
156 | * |
157 | * @warning For testing purposes, if the library is compiled with debug |
158 | * enabled, this method returns any simulated local system time |
159 | * zone set by setLocalZone(). If the library is compiled in |
160 | * release mode, it always returns the real local system time zone. |
161 | * |
162 | * @return local system time zone. If necessary, we will use a series of |
163 | * heuristics which end by returning UTC. We will never return NULL. |
164 | * Note that if UTC is returned as a default, it may not belong to the |
165 | * the collection returned by KSystemTimeZones::zones(). |
166 | */ |
167 | static KTimeZone local(); |
168 | |
169 | /** |
170 | * Return the real (not simulated) local system time zone. |
171 | * |
172 | * @warning This method is provided only for testing purposes, and should |
173 | * not be used in released code. If the library is compiled without |
174 | * debug enabled, local() and realLocalZone() both return the real |
175 | * local system time zone. |
176 | * To avoid confusion, it is recommended that calls to |
177 | * realLocalZone() should be conditionally compiled, e.g.: |
178 | * \code |
179 | * #ifndef NDEBUG |
180 | * tz = KSystemTimeZones::realLocalZone(); |
181 | * #endif |
182 | * \endcode |
183 | * |
184 | * @see setLocalZone() |
185 | * @since 4.3 |
186 | */ |
187 | static KTimeZone realLocalZone(); |
188 | |
189 | /** |
190 | * Set or clear the simulated local system time zone. |
191 | * |
192 | * @warning This method is provided only for testing purposes, and should |
193 | * not be used in released code. If the library is compiled without |
194 | * debug enabled, setLocalZone() has no effect. |
195 | * To avoid confusion, it is recommended that calls to it should be |
196 | * conditionally compiled, e.g.: |
197 | * \code |
198 | * #ifndef NDEBUG |
199 | * KSystemTimeZones::setLocalZone(tz); |
200 | * #endif |
201 | * \endcode |
202 | * |
203 | * @param tz the time zone to simulate, or an invalid KTimeZone instance |
204 | * (i.e. \code tz.isValid() == false \endcode) to cancel |
205 | * simulation |
206 | * @since 4.3 |
207 | */ |
208 | static void setLocalZone(const KTimeZone& tz); |
209 | |
210 | /** |
211 | * Check whether there is a simulated local system time zone. |
212 | * |
213 | * @warning This method is provided only for testing purposes, and should |
214 | * not be used in released code. If the library is compiled without |
215 | * debug enabled, isSimulated() always returns false. |
216 | * To avoid confusion, it is recommended that calls to it should be |
217 | * conditionally compiled, e.g.: |
218 | * \code |
219 | * #ifndef NDEBUG |
220 | * if (KSystemTimeZones::isSimulated()) |
221 | * { |
222 | * ... |
223 | * } |
224 | * #endif |
225 | * \endcode |
226 | * |
227 | * @see setLocalZone() |
228 | * @since 4.3 |
229 | */ |
230 | static bool isSimulated(); |
231 | |
232 | /** |
233 | * Returns the location of the system time zone zoneinfo database. |
234 | * |
235 | * @return path of directory containing the zoneinfo database |
236 | */ |
237 | static QString zoneinfoDir(); |
238 | |
239 | /** |
240 | * Return whether the KDE time zone daemon, ktimezoned, appears to be |
241 | * available and working. If not, UTC will be the only recognized time |
242 | * zone. |
243 | * @since 4.6 |
244 | */ |
245 | static bool isTimeZoneDaemonAvailable(); |
246 | |
247 | private Q_SLOTS: |
248 | // Connected to D-Bus signals |
249 | void configChanged(); |
250 | void zonetabChanged(const QString &zonetab); |
251 | void zoneDefinitionChanged(const QString &zone); |
252 | |
253 | private: |
254 | KSystemTimeZones(); |
255 | |
256 | KSystemTimeZonesPrivate * const d; |
257 | friend class KSystemTimeZonesPrivate; |
258 | }; |
259 | |
260 | /** |
261 | * The KSystemTimeZone class represents a time zone in the system database. |
262 | * |
263 | * It works in partnership with the KSystemTimeZoneSource class which reads and parses the |
264 | * time zone definition files. |
265 | * |
266 | * Typically, instances are created and accessed via the KSystemTimeZones class. |
267 | * |
268 | * @warning The KSystemTimeZone class uses the standard system libraries to |
269 | * access time zone data, and its functionality is limited to what these libraries |
270 | * provide. On many systems, dates earlier than 1970 are not handled, and on |
271 | * non-GNU systems there is no guarantee that the time zone abbreviation returned |
272 | * for a given date will be correct if the abbreviations applicable then were |
273 | * not those currently in use. Consider using KSystemTimeZones::readZone() or the |
274 | * KTzfileTimeZone class instead, which provide accurate information from the time |
275 | * zone definition files (but are likely to incur more overhead). |
276 | * |
277 | * @short System time zone |
278 | * @see KSystemTimeZones, KSystemTimeZoneSource, KSystemTimeZoneData, KTzfileTimeZone |
279 | * @ingroup timezones |
280 | * @author David Jarvie <djarvie@kde.org>. |
281 | */ |
282 | class KDECORE_EXPORT KSystemTimeZone : public KTimeZone //krazy:exclude=dpointer (no d-pointer for KTimeZone derived classes) |
283 | { |
284 | public: |
285 | |
286 | /** |
287 | * Creates a time zone. |
288 | * |
289 | * @param source tzfile reader and parser |
290 | * @param name time zone's unique name |
291 | * @param countryCode ISO 3166 2-character country code, empty if unknown |
292 | * @param latitude in degrees (between -90 and +90), UNKNOWN if not known |
293 | * @param longitude in degrees (between -180 and +180), UNKNOWN if not known |
294 | * @param comment description of the time zone, if any |
295 | */ |
296 | KSystemTimeZone(KSystemTimeZoneSource *source, const QString &name, |
297 | const QString &countryCode = QString(), float latitude = UNKNOWN, float longitude = UNKNOWN, |
298 | const QString & = QString()); |
299 | |
300 | ~KSystemTimeZone(); |
301 | |
302 | private: |
303 | // d-pointer is in KSystemTimeZoneBackend. |
304 | // This is a requirement for classes inherited from KTimeZone. |
305 | }; |
306 | |
307 | |
308 | /** |
309 | * Backend class for KSystemTimeZone class. |
310 | * |
311 | * This class implements KSystemTimeZone's constructors and virtual methods. A |
312 | * backend class is required for all classes inherited from KTimeZone to |
313 | * allow KTimeZone virtual methods to work together with reference counting of |
314 | * private data. |
315 | * |
316 | * @short Backend class for KSystemTimeZone class |
317 | * @see KTimeZoneBackend, KSystemTimeZone, KTimeZone |
318 | * @ingroup timezones |
319 | * @author David Jarvie <djarvie@kde.org>. |
320 | */ |
321 | class KDECORE_EXPORT KSystemTimeZoneBackend : public KTimeZoneBackend //krazy:exclude=dpointer (non-const d-pointer for KTimeZoneBackend-derived classes) |
322 | { |
323 | public: |
324 | /** Implements KSystemTimeZone::KSystemTimeZone(). */ |
325 | KSystemTimeZoneBackend(KSystemTimeZoneSource *source, const QString &name, |
326 | const QString &countryCode, float latitude, float longitude, const QString &); |
327 | |
328 | ~KSystemTimeZoneBackend(); |
329 | |
330 | /** |
331 | * Creates a copy of this instance. |
332 | * |
333 | * @return new copy |
334 | */ |
335 | virtual KTimeZoneBackend *clone() const; |
336 | |
337 | /** |
338 | * Returns the class name of the data represented by this instance. |
339 | * |
340 | * @return "KSystemTimeZone" |
341 | */ |
342 | virtual QByteArray type() const; |
343 | |
344 | /** |
345 | * Implements KSystemTimeZone::offsetAtZoneTime(). |
346 | * |
347 | * Returns the offset of this time zone to UTC at the given local date/time. |
348 | * Because of daylight savings time shifts, the date/time may occur twice. Optionally, |
349 | * the offsets at both occurrences of @p dateTime are calculated. |
350 | * |
351 | * The offset is the number of seconds which you must add to UTC to get |
352 | * local time in this time zone. |
353 | * |
354 | * @param caller calling KSystemTimeZone object |
355 | * @param zoneDateTime the date/time at which the offset is to be calculated. This |
356 | * is interpreted as a local time in this time zone. An error |
357 | * occurs if @p zoneDateTime.timeSpec() is not Qt::LocalTime. |
358 | * @param secondOffset if non-null, and the @p zoneDateTime occurs twice, receives the |
359 | * UTC offset for the second occurrence. Otherwise, it is set |
360 | * the same as the return value. |
361 | * @return offset in seconds. If @p zoneDateTime occurs twice, it is the offset at the |
362 | * first occurrence which is returned. |
363 | */ |
364 | virtual int offsetAtZoneTime(const KTimeZone *caller, const QDateTime &zoneDateTime, int *secondOffset) const; |
365 | |
366 | /** |
367 | * Implements KSystemTimeZone::offsetAtUtc(). |
368 | * |
369 | * Returns the offset of this time zone to UTC at the given UTC date/time. |
370 | * |
371 | * The offset is the number of seconds which you must add to UTC to get |
372 | * local time in this time zone. |
373 | * |
374 | * Note that system times are represented using time_t. An error occurs if the date |
375 | * falls outside the range supported by time_t. |
376 | * |
377 | * @param caller calling KSystemTimeZone object |
378 | * @param utcDateTime the UTC date/time at which the offset is to be calculated. |
379 | * An error occurs if @p utcDateTime.timeSpec() is not Qt::UTC. |
380 | * @return offset in seconds, or 0 if error |
381 | */ |
382 | virtual int offsetAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const; |
383 | |
384 | /** |
385 | * Implements KSystemTimeZone::offset(). |
386 | * |
387 | * Returns the offset of this time zone to UTC at a specified UTC time. |
388 | * |
389 | * The offset is the number of seconds which you must add to UTC to get |
390 | * local time in this time zone. |
391 | * |
392 | * @param caller calling KSystemTimeZone object |
393 | * @param t the UTC time at which the offset is to be calculated, measured in seconds |
394 | * since 00:00:00 UTC 1st January 1970 (as returned by time(2)) |
395 | * @return offset in seconds, or 0 if error |
396 | */ |
397 | virtual int offset(const KTimeZone *caller, time_t t) const; |
398 | |
399 | /** |
400 | * Implements KSystemTimeZone::isDstAtUtc(). |
401 | * |
402 | * Returns whether daylight savings time is in operation at the given UTC date/time. |
403 | * |
404 | * Note that system times are represented using time_t. An error occurs if the date |
405 | * falls outside the range supported by time_t. |
406 | * |
407 | * @param caller calling KSystemTimeZone object |
408 | * @param utcDateTime the UTC date/time. An error occurs if |
409 | * @p utcDateTime.timeSpec() is not Qt::UTC. |
410 | * @return @c true if daylight savings time is in operation, @c false otherwise |
411 | */ |
412 | virtual bool isDstAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const; |
413 | |
414 | /** |
415 | * Implements KSystemTimeZone::isDst(). |
416 | * |
417 | * Returns whether daylight savings time is in operation at a specified UTC time. |
418 | * |
419 | * @param caller calling KSystemTimeZone object |
420 | * @param t the UTC time, measured in seconds since 00:00:00 UTC 1st January 1970 |
421 | * (as returned by time(2)) |
422 | * @return @c true if daylight savings time is in operation, @c false otherwise |
423 | */ |
424 | virtual bool isDst(const KTimeZone *caller, time_t t) const; |
425 | |
426 | private: |
427 | KSystemTimeZonePrivate *d; // non-const |
428 | }; |
429 | |
430 | |
431 | /** |
432 | * A class to read and parse system time zone data. |
433 | * |
434 | * Access is performed via the system time zone library functions. |
435 | * |
436 | * @short Reads and parses system time zone data |
437 | * @see KSystemTimeZones, KSystemTimeZone, KSystemTimeZoneData |
438 | * @ingroup timezones |
439 | * @author David Jarvie <djarvie@kde.org>. |
440 | */ |
441 | class KDECORE_EXPORT KSystemTimeZoneSource : public KTimeZoneSource |
442 | { |
443 | public: |
444 | /** |
445 | * Constructs a system time zone source. |
446 | */ |
447 | KSystemTimeZoneSource(); |
448 | virtual ~KSystemTimeZoneSource(); |
449 | |
450 | /** |
451 | * Extract detailed information for one time zone, via the system time zone |
452 | * library functions. |
453 | * |
454 | * @param zone the time zone for which data is to be extracted |
455 | * @return a KSystemTimeZoneData instance containing the parsed data. |
456 | * The caller is responsible for deleting the KTimeZoneData instance. |
457 | * Null is returned on error. |
458 | */ |
459 | virtual KTimeZoneData *parse(const KTimeZone &zone) const; |
460 | |
461 | /** |
462 | * Use in conjunction with endParseBlock() to improve efficiency when calling parse() |
463 | * for a group of KSystemTimeZone instances in succession. |
464 | * Call startParseBlock() before the first parse(), and call endParseBlock() after the last. |
465 | * |
466 | * The effect of calling these methods is to save and restore the TZ environment variable |
467 | * only once before and after the group of parse() calls, rather than before and |
468 | * after every call. So, between calls to startParseBlock() and endParseBlock(), do not |
469 | * call any functions which rely directly or indirectly on the local time zone setting. |
470 | */ |
471 | static void startParseBlock(); |
472 | |
473 | /** |
474 | * @see startParseBlock() |
475 | */ |
476 | static void endParseBlock(); |
477 | |
478 | private: |
479 | KSystemTimeZoneSourcePrivate * const d; |
480 | }; |
481 | |
482 | |
483 | /** |
484 | * @internal |
485 | * The parsed system time zone data returned by KSystemTimeZoneSource. |
486 | * |
487 | * @short Parsed system time zone data |
488 | * @see KSystemTimeZoneSource, KSystemTimeZone |
489 | * @ingroup timezones |
490 | * @author David Jarvie <djarvie@kde.org>. |
491 | */ |
492 | class KSystemTimeZoneData : public KTimeZoneData |
493 | { |
494 | friend class KSystemTimeZoneSource; |
495 | |
496 | public: |
497 | KSystemTimeZoneData(); |
498 | /** Copy constructor; no special ownership assumed. */ |
499 | KSystemTimeZoneData(const KSystemTimeZoneData &); |
500 | virtual ~KSystemTimeZoneData(); |
501 | |
502 | /** Assignment; no special ownership assumed. Everything is value based. */ |
503 | KSystemTimeZoneData &operator=(const KSystemTimeZoneData &); |
504 | |
505 | /** |
506 | * Creates a new copy of this object. |
507 | * The caller is responsible for deleting the copy. |
508 | * Derived classes must reimplement this method to return a copy of the |
509 | * calling instance |
510 | * |
511 | * @return copy of this instance. This is a KSystemTimeZoneData pointer. |
512 | */ |
513 | virtual KTimeZoneData *clone() const; |
514 | |
515 | /** |
516 | * Returns the complete list of time zone abbreviations. |
517 | * |
518 | * @return the list of abbreviations |
519 | */ |
520 | virtual QList<QByteArray> abbreviations() const; |
521 | virtual QByteArray abbreviation(const QDateTime &utcDateTime) const; |
522 | |
523 | /** |
524 | * Returns the complete list of UTC offsets for the time zone. For system |
525 | * time zones, significant processing would be required to obtain such a |
526 | * list, so instead an empty list is returned. |
527 | * |
528 | * @return empty list |
529 | */ |
530 | virtual QList<int> utcOffsets() const; |
531 | |
532 | private: |
533 | KSystemTimeZoneDataPrivate * const d; |
534 | }; |
535 | |
536 | #endif |
537 | |