• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDECore

  • kdecore
  • date
ktzfiletimezone.cpp
Go to the documentation of this file.
1/*
2 This file is part of the KDE libraries
3 Copyright (c) 2005-2008 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#include "ktzfiletimezone.h"
22
23#include <config.h>
24
25#ifdef HAVE_SYS_TIME_H
26#include <sys/time.h>
27#endif
28#ifdef HAVE_TIME_H
29#include <time.h>
30#endif
31
32#include <QtCore/QFile>
33#include <QtCore/QDataStream>
34#include <QtCore/QVector>
35
36#include <kdebug.h>
37
38
39// Use this replacement for QDateTime::setTime_t(uint) since our time
40// values are signed.
41static QDateTime fromTime_t(qint32 seconds)
42{
43 static const QDate epochDate(1970,1,1);
44 static const QTime epochTime(0,0,0);
45 int days = seconds / 86400;
46 seconds -= days * 86400;
47 if (seconds < 0)
48 {
49 --days;
50 seconds += 86400;
51 }
52 return QDateTime(epochDate.addDays(days), epochTime.addSecs(seconds), Qt::UTC);
53}
54
55/******************************************************************************/
56
57KTzfileTimeZoneBackend::KTzfileTimeZoneBackend(KTzfileTimeZoneSource *source, const QString &name,
58 const QString &countryCode, float latitude, float longitude, const QString &comment)
59 : KTimeZoneBackend(source, name, countryCode, latitude, longitude, comment)
60{}
61
62KTzfileTimeZoneBackend::~KTzfileTimeZoneBackend()
63{}
64
65KTimeZoneBackend *KTzfileTimeZoneBackend::clone() const
66{
67 return new KTzfileTimeZoneBackend(*this);
68}
69
70QByteArray KTzfileTimeZoneBackend::type() const
71{
72 return "KTzfileTimeZone";
73}
74
75bool KTzfileTimeZoneBackend::hasTransitions(const KTimeZone *caller) const
76{
77 Q_UNUSED(caller)
78 return true;
79}
80
81
82/******************************************************************************/
83
84KTzfileTimeZone::KTzfileTimeZone(KTzfileTimeZoneSource *source, const QString &name,
85 const QString &countryCode, float latitude, float longitude,
86 const QString &comment)
87 : KTimeZone(new KTzfileTimeZoneBackend(source, name, countryCode, latitude, longitude, comment))
88{}
89
90KTzfileTimeZone::~KTzfileTimeZone()
91{}
92
93
94/******************************************************************************/
95
96class KTzfileTimeZoneDataPrivate
97{
98public:
99};
100
101
102KTzfileTimeZoneData::KTzfileTimeZoneData()
103// : d(new KTzfileTimeZoneDataPrivate)
104{ }
105
106KTzfileTimeZoneData::KTzfileTimeZoneData(const KTzfileTimeZoneData &rhs)
107 : KTimeZoneData(rhs)
108// d(new KTzfileTimeZoneDataPrivate)
109{
110}
111
112KTzfileTimeZoneData::~KTzfileTimeZoneData()
113{
114// delete d;
115}
116
117KTzfileTimeZoneData &KTzfileTimeZoneData::operator=(const KTzfileTimeZoneData &rhs)
118{
119 KTimeZoneData::operator=(rhs);
120 return *this;
121}
122
123KTimeZoneData *KTzfileTimeZoneData::clone() const
124{
125 return new KTzfileTimeZoneData(*this);
126}
127
128bool KTzfileTimeZoneData::hasTransitions() const
129{
130 return true;
131}
132
133
134/******************************************************************************/
135
136class KTzfileTimeZoneSourcePrivate
137{
138public:
139 KTzfileTimeZoneSourcePrivate(const QString &loc)
140 : location(loc) {}
141 ~KTzfileTimeZoneSourcePrivate() {}
142
143 QString location;
144};
145
146
147KTzfileTimeZoneSource::KTzfileTimeZoneSource(const QString &location)
148 : d(new KTzfileTimeZoneSourcePrivate(location))
149{
150 if (location.length() > 1 && location.endsWith(QLatin1Char('/')))
151 d->location.chop(1);
152}
153
154KTzfileTimeZoneSource::~KTzfileTimeZoneSource()
155{
156 delete d;
157}
158
159QString KTzfileTimeZoneSource::location() const
160{
161 return d->location;
162}
163
164KTimeZoneData* KTzfileTimeZoneSource::parse(const KTimeZone &zone) const
165{
166 quint32 abbrCharCount; // the number of characters of time zone abbreviation strings
167 quint32 ttisgmtcnt;
168 quint8 is;
169 quint8 T_, Z_, i_, f_; // tzfile identifier prefix
170
171 QString path = zone.name();
172 if (!path.startsWith(QLatin1Char('/')))
173 {
174 if (d->location == QLatin1String("/"))
175 path.prepend(d->location);
176 else
177 path = d->location + QLatin1Char('/') + path;
178 }
179 QFile f(path);
180 if (!f.open(QIODevice::ReadOnly))
181 {
182 kError() << "Cannot open " << f.fileName() << endl;
183 return 0;
184 }
185 QDataStream str(&f);
186
187 // Read the file type identifier
188 str >> T_ >> Z_ >> i_ >> f_;
189 if (T_ != 'T' || Z_ != 'Z' || i_ != 'i' || f_ != 'f')
190 {
191 kError() << "Not a TZFILE: " << f.fileName() << endl;
192 return 0;
193 }
194 // Discard 16 bytes reserved for future use
195 unsigned i;
196 for (i = 0; i < 4; ++i)
197 str >> ttisgmtcnt;
198
199 KTzfileTimeZoneData* data = new KTzfileTimeZoneData;
200
201 // Read the sizes of arrays held in the file
202 quint32 nTransitionTimes;
203 quint32 nLocalTimeTypes;
204 quint32 nLeapSecondAdjusts;
205 quint32 nIsStandard;
206 quint32 nIsUtc;
207 str >> nIsUtc
208 >> nIsStandard
209 >> nLeapSecondAdjusts
210 >> nTransitionTimes
211 >> nLocalTimeTypes
212 >> abbrCharCount;
213 // kDebug() << "header: " << nIsUtc << ", " << nIsStandard << ", " << nLeapSecondAdjusts << ", " <<
214 // nTransitionTimes << ", " << nLocalTimeTypes << ", " << abbrCharCount << endl;
215
216 // Read the transition times, at which the rules for computing local time change
217 struct TransitionTime
218 {
219 qint32 time; // time (as returned by time(2)) at which the rules for computing local time change
220 quint8 localTimeIndex; // index into the LocalTimeType array
221 };
222//kDebug()<<"Reading zone "<<zone.name();
223 TransitionTime *transitionTimes = new TransitionTime[nTransitionTimes];
224 for (i = 0; i < nTransitionTimes; ++i)
225 {
226 str >> transitionTimes[i].time;
227 }
228 for (i = 0; i < nTransitionTimes; ++i)
229 {
230 str >> transitionTimes[i].localTimeIndex;
231//kDebug() << "Transition time "<<i<<": "<<transitionTimes[i].time<<" lt index="<<(int)transitionTimes[i].localTimeIndex;
232 }
233
234 // Read the local time types
235 struct LocalTimeType
236 {
237 qint32 gmtoff; // number of seconds to be added to UTC
238 bool isdst; // whether tm_isdst should be set by localtime(3)
239 quint8 abbrIndex; // index into the list of time zone abbreviations
240 bool isutc; // transition times are in UTC. If UTC, isstd is ignored.
241 bool isstd; // if true, transition times are in standard time;
242 // if false, transition times are in wall clock time,
243 // i.e. standard time or daylight savings time
244 // whichever is current before the transition
245 };
246 LocalTimeType *localTimeTypes = new LocalTimeType[nLocalTimeTypes];
247 LocalTimeType *ltt = localTimeTypes;
248 for (i = 0; i < nLocalTimeTypes; ++ltt, ++i)
249 {
250 str >> ltt->gmtoff;
251 str >> is;
252 ltt->isdst = (is != 0);
253 str >> ltt->abbrIndex;
254 // kDebug() << "local type: " << ltt->gmtoff << ", " << is << ", " << ltt->abbrIndex;
255 ltt->isstd = false; // default if no data
256 ltt->isutc = false; // default if no data
257 }
258
259 // Read the timezone abbreviations. They are stored as null terminated strings in
260 // a character array.
261 // Make sure we don't fall foul of maliciously coded time zone abbreviations.
262 if (abbrCharCount > 64)
263 {
264 kError() << "excessive length for timezone abbreviations: " << abbrCharCount << endl;
265 delete data;
266 delete[] transitionTimes;
267 delete[] localTimeTypes;
268 return 0;
269 }
270 QByteArray array(abbrCharCount, 0);
271 str.readRawData(array.data(), array.size());
272 const char *abbrs = array.constData();
273 if (abbrs[abbrCharCount - 1] != 0)
274 {
275 // These abbreviations are corrupt!
276 kError() << "timezone abbreviations not null terminated: " << abbrs[abbrCharCount - 1] << endl;
277 delete data;
278 delete[] transitionTimes;
279 delete[] localTimeTypes;
280 return 0;
281 }
282 quint8 n = 0;
283 QList<QByteArray> abbreviations;
284 for (i = 0; i < abbrCharCount; ++n, i += strlen(abbrs + i) + 1)
285 {
286 abbreviations += QByteArray(abbrs + i);
287 // Convert the LocalTimeTypes pointer to a sequential index
288 ltt = localTimeTypes;
289 for (unsigned j = 0; j < nLocalTimeTypes; ++ltt, ++j)
290 {
291 if (ltt->abbrIndex == i)
292 ltt->abbrIndex = n;
293 }
294 }
295
296
297 // Read the leap second adjustments
298 qint32 t;
299 quint32 s;
300 QList<KTimeZone::LeapSeconds> leapChanges;
301 for (i = 0; i < nLeapSecondAdjusts; ++i)
302 {
303 str >> t >> s;
304 // kDebug() << "leap entry: " << t << ", " << s;
305 // Don't use QDateTime::setTime_t() because it takes an unsigned argument
306 leapChanges += KTimeZone::LeapSeconds(fromTime_t(t), static_cast<int>(s));
307 }
308 data->setLeapSecondChanges(leapChanges);
309
310 // Read the standard/wall time indicators.
311 // These are true if the transition times associated with local time types
312 // are specified as standard time, false if wall clock time.
313 for (i = 0; i < nIsStandard; ++i)
314 {
315 str >> is;
316 localTimeTypes[i].isstd = (is != 0);
317 // kDebug() << "standard: " << is;
318 }
319
320 // Read the UTC/local time indicators.
321 // These are true if the transition times associated with local time types
322 // are specified as UTC, false if local time.
323 for (i = 0; i < nIsUtc; ++i)
324 {
325 str >> is;
326 localTimeTypes[i].isutc = (is != 0);
327 // kDebug() << "UTC: " << is;
328 }
329
330
331 // Find the starting offset from UTC to use before the first transition time.
332 // This is first non-daylight savings local time type, or if there is none,
333 // the first local time type.
334 LocalTimeType* firstLtt = 0;
335 ltt = localTimeTypes;
336 for (i = 0; i < nLocalTimeTypes; ++ltt, ++i)
337 {
338 if (!ltt->isdst)
339 {
340 firstLtt = ltt;
341 break;
342 }
343 }
344
345 // Compile the time type data into a list of KTimeZone::Phase instances.
346 // Also check for local time types which are identical (this does happen)
347 // and use the same Phase instance for each.
348 QByteArray abbrev;
349 QList<KTimeZone::Phase> phases;
350 QList<QByteArray> phaseAbbrevs;
351 QVector<int> lttLookup(nLocalTimeTypes);
352 ltt = localTimeTypes;
353 for (i = 0; i < nLocalTimeTypes; ++ltt, ++i)
354 {
355 if (ltt->abbrIndex >= abbreviations.count())
356 {
357 kError() << "KTzfileTimeZoneSource::parse(): abbreviation index out of range" << endl;
358 abbrev = "???";
359 }
360 else
361 abbrev = abbreviations[ltt->abbrIndex];
362 // Check for an identical Phase
363 int phindex = 0;
364 for (int j = 0, jend = phases.count(); j < jend; ++j, ++phindex)
365 {
366 if (ltt->gmtoff == phases[j].utcOffset()
367 && (bool)ltt->isdst == phases[j].isDst()
368 && abbrev == phaseAbbrevs[j])
369 break;
370 }
371 lttLookup[i] = phindex;
372 if (phindex == phases.count())
373 {
374 phases += KTimeZone::Phase(ltt->gmtoff, abbrev, ltt->isdst);
375 phaseAbbrevs += abbrev;
376 }
377 }
378 KTimeZone::Phase prePhase(firstLtt->gmtoff,
379 (firstLtt->abbrIndex < abbreviations.count() ? abbreviations[firstLtt->abbrIndex] : ""),
380 false);
381 data->setPhases(phases, prePhase);
382
383 // Compile the transition list
384 QList<KTimeZone::Transition> transitions;
385 TransitionTime *tt = transitionTimes;
386 for (i = 0; i < nTransitionTimes; ++tt, ++i)
387 {
388 if (tt->localTimeIndex >= nLocalTimeTypes)
389 {
390 kError() << "KTzfileTimeZoneSource::parse(): transition ignored: local time type out of range: " <<(int)tt->localTimeIndex<<" > "<<nLocalTimeTypes << endl;
391 continue;
392 }
393
394 // Convert local transition times to UTC
395 ltt = &localTimeTypes[tt->localTimeIndex];
396 const KTimeZone::Phase phase = phases[lttLookup[tt->localTimeIndex]];
397//kDebug(161) << "Transition time "<<i<<": "<<fromTime_t(tt->time)<<", offset="<<phase.utcOffset()/60;
398 transitions += KTimeZone::Transition(fromTime_t(tt->time), phase);
399 }
400 data->setTransitions(transitions);
401//for(int xxx=1;xxx<data->transitions().count();xxx++)
402//kDebug(161) << "Transition time "<<xxx<<": "<<data->transitions()[xxx].time()<<", offset="<<data->transitions()[xxx].phase().utcOffset()/60;
403 delete[] localTimeTypes;
404 delete[] transitionTimes;
405
406 return data;
407}
KTimeZoneBackend
Base backend class for KTimeZone classes.
Definition: ktimezone.h:1121
KTimeZoneData
Base class for the parsed data returned by a KTimeZoneSource class.
Definition: ktimezone.h:1303
KTimeZoneData::operator=
KTimeZoneData & operator=(const KTimeZoneData &c)
Definition: ktimezone.cpp:1164
KTimeZoneData::setLeapSecondChanges
void setLeapSecondChanges(const QList< KTimeZone::LeapSeconds > &adjusts)
Initialise the leap seconds adjustment list.
Definition: ktimezone.cpp:1380
KTimeZoneData::setPhases
void setPhases(const QList< KTimeZone::Phase > &phases, const KTimeZone::Phase &previousPhase)
Initialise the daylight savings time phase list.
Definition: ktimezone.cpp:1232
KTimeZoneData::setTransitions
void setTransitions(const QList< KTimeZone::Transition > &transitions)
Initialise the daylight savings time transition list.
Definition: ktimezone.cpp:1261
KTimeZone::LeapSeconds
Definition: ktimezone.h:561
KTimeZone::Phase
Definition: ktimezone.h:430
KTimeZone::Transition
Definition: ktimezone.h:514
KTimeZone
Base class representing a time zone.
Definition: ktimezone.h:417
KTimeZone::name
QString name() const
Returns the name of the time zone.
Definition: ktimezone.cpp:669
KTzfileTimeZoneBackend
Backend class for KTzfileTimeZone class.
Definition: ktzfiletimezone.h:90
KTzfileTimeZoneBackend::KTzfileTimeZoneBackend
KTzfileTimeZoneBackend(KTzfileTimeZoneSource *source, const QString &name, const QString &countryCode, float latitude, float longitude, const QString &comment)
Implements KTzfileTimeZone::KTzfileTimeZone().
Definition: ktzfiletimezone.cpp:57
KTzfileTimeZoneBackend::~KTzfileTimeZoneBackend
~KTzfileTimeZoneBackend()
Definition: ktzfiletimezone.cpp:62
KTzfileTimeZoneBackend::clone
virtual KTimeZoneBackend * clone() const
Creates a copy of this instance.
Definition: ktzfiletimezone.cpp:65
KTzfileTimeZoneBackend::type
virtual QByteArray type() const
Returns the class name of the data represented by this instance.
Definition: ktzfiletimezone.cpp:70
KTzfileTimeZoneBackend::hasTransitions
virtual bool hasTransitions(const KTimeZone *caller) const
Implements KTzfileTimeZone::hasTransitions().
Definition: ktzfiletimezone.cpp:75
KTzfileTimeZoneData
Parsed data from tzfile(5) time zone definition files.
Definition: ktzfiletimezone.h:186
KTzfileTimeZoneData::KTzfileTimeZoneData
KTzfileTimeZoneData()
Definition: ktzfiletimezone.cpp:102
KTzfileTimeZoneData::operator=
KTzfileTimeZoneData & operator=(const KTzfileTimeZoneData &)
Definition: ktzfiletimezone.cpp:117
KTzfileTimeZoneData::hasTransitions
virtual bool hasTransitions() const
Return whether daylight saving transitions are available for the time zone.
Definition: ktzfiletimezone.cpp:128
KTzfileTimeZoneData::clone
virtual KTimeZoneData * clone() const
Creates a new copy of this object.
Definition: ktzfiletimezone.cpp:123
KTzfileTimeZoneData::~KTzfileTimeZoneData
virtual ~KTzfileTimeZoneData()
Definition: ktzfiletimezone.cpp:112
KTzfileTimeZoneSource
A class to read and parse tzfile time zone definition files.
Definition: ktzfiletimezone.h:139
KTzfileTimeZoneSource::location
QString location() const
Returns the local directory containing the time zone definition files.
Definition: ktzfiletimezone.cpp:159
KTzfileTimeZoneSource::KTzfileTimeZoneSource
KTzfileTimeZoneSource(const QString &location)
Constructs a time zone source.
Definition: ktzfiletimezone.cpp:147
KTzfileTimeZoneSource::parse
virtual KTimeZoneData * parse(const KTimeZone &zone) const
Parses a tzfile file to extract detailed information for one time zone.
Definition: ktzfiletimezone.cpp:164
KTzfileTimeZoneSource::~KTzfileTimeZoneSource
virtual ~KTzfileTimeZoneSource()
Definition: ktzfiletimezone.cpp:154
KTzfileTimeZone::~KTzfileTimeZone
~KTzfileTimeZone()
Definition: ktzfiletimezone.cpp:90
KTzfileTimeZone::KTzfileTimeZone
KTzfileTimeZone(KTzfileTimeZoneSource *source, const QString &name, const QString &countryCode=QString(), float latitude=UNKNOWN, float longitude=UNKNOWN, const QString &comment=QString())
Creates a time zone.
Definition: ktzfiletimezone.cpp:84
QDateTime
QList
Definition: kaboutdata.h:33
QString
qint32
quint32
kError
static QDebug kError(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
Definition: kdebug.h:187
kdebug.h
gmtoff
int gmtoff(time_t t)
Definition: ksystemtimezone.cpp:70
transitions
Transitions transitions(const TIME_ZONE_INFORMATION &tz, int year)
Definition: ktimezone_win.cpp:368
fromTime_t
static QDateTime fromTime_t(qint32 seconds)
Definition: ktzfiletimezone.cpp:41
ktzfiletimezone.h
TZFILE time zone functions.
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal