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

KDECore

  • sources
  • kde-4.14
  • kdelibs
  • 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.
41 static 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 
57 KTzfileTimeZoneBackend::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 
62 KTzfileTimeZoneBackend::~KTzfileTimeZoneBackend()
63 {}
64 
65 KTimeZoneBackend *KTzfileTimeZoneBackend::clone() const
66 {
67  return new KTzfileTimeZoneBackend(*this);
68 }
69 
70 QByteArray KTzfileTimeZoneBackend::type() const
71 {
72  return "KTzfileTimeZone";
73 }
74 
75 bool KTzfileTimeZoneBackend::hasTransitions(const KTimeZone *caller) const
76 {
77  Q_UNUSED(caller)
78  return true;
79 }
80 
81 
82 /******************************************************************************/
83 
84 KTzfileTimeZone::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 
90 KTzfileTimeZone::~KTzfileTimeZone()
91 {}
92 
93 
94 /******************************************************************************/
95 
96 class KTzfileTimeZoneDataPrivate
97 {
98 public:
99 };
100 
101 
102 KTzfileTimeZoneData::KTzfileTimeZoneData()
103 // : d(new KTzfileTimeZoneDataPrivate)
104 { }
105 
106 KTzfileTimeZoneData::KTzfileTimeZoneData(const KTzfileTimeZoneData &rhs)
107  : KTimeZoneData(rhs)
108 // d(new KTzfileTimeZoneDataPrivate)
109 {
110 }
111 
112 KTzfileTimeZoneData::~KTzfileTimeZoneData()
113 {
114 // delete d;
115 }
116 
117 KTzfileTimeZoneData &KTzfileTimeZoneData::operator=(const KTzfileTimeZoneData &rhs)
118 {
119  KTimeZoneData::operator=(rhs);
120  return *this;
121 }
122 
123 KTimeZoneData *KTzfileTimeZoneData::clone() const
124 {
125  return new KTzfileTimeZoneData(*this);
126 }
127 
128 bool KTzfileTimeZoneData::hasTransitions() const
129 {
130  return true;
131 }
132 
133 
134 /******************************************************************************/
135 
136 class KTzfileTimeZoneSourcePrivate
137 {
138 public:
139  KTzfileTimeZoneSourcePrivate(const QString &loc)
140  : location(loc) {}
141  ~KTzfileTimeZoneSourcePrivate() {}
142 
143  QString location;
144 };
145 
146 
147 KTzfileTimeZoneSource::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 
154 KTzfileTimeZoneSource::~KTzfileTimeZoneSource()
155 {
156  delete d;
157 }
158 
159 QString KTzfileTimeZoneSource::location() const
160 {
161  return d->location;
162 }
163 
164 KTimeZoneData* 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 }
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
kdebug.h
KTzfileTimeZoneBackend::hasTransitions
virtual bool hasTransitions(const KTimeZone *caller) const
Implements KTzfileTimeZone::hasTransitions().
Definition: ktzfiletimezone.cpp:75
KTimeZoneData::setPhases
void setPhases(const QList< KTimeZone::Phase > &phases, const KTimeZone::Phase &previousPhase)
Initialise the daylight savings time phase list.
Definition: ktimezone.cpp:1232
QByteArray
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
KTimeZoneData
Base class for the parsed data returned by a KTimeZoneSource class.
Definition: ktimezone.h:1302
transitions
Transitions transitions(const TIME_ZONE_INFORMATION &tz, int year)
Definition: ktimezone_win.cpp:368
QDataStream
QString::prepend
QString & prepend(QChar ch)
fromTime_t
static QDateTime fromTime_t(qint32 seconds)
Definition: ktzfiletimezone.cpp:41
KTzfileTimeZoneData
Parsed data from tzfile(5) time zone definition files.
Definition: ktzfiletimezone.h:185
QFile::fileName
QString fileName() const
KTimeZoneData::setLeapSecondChanges
void setLeapSecondChanges(const QList< KTimeZone::LeapSeconds > &adjusts)
Initialise the leap seconds adjustment list.
Definition: ktimezone.cpp:1380
kError
static QDebug kError(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
Definition: kdebug.h:187
KTimeZoneData::setTransitions
void setTransitions(const QList< KTimeZone::Transition > &transitions)
Initialise the daylight savings time transition list.
Definition: ktimezone.cpp:1261
quint32
KTzfileTimeZoneData::KTzfileTimeZoneData
KTzfileTimeZoneData()
Definition: ktzfiletimezone.cpp:102
QTime
KTzfileTimeZoneBackend::clone
virtual KTimeZoneBackend * clone() const
Creates a copy of this instance.
Definition: ktzfiletimezone.cpp:65
QFile
KTzfileTimeZone::~KTzfileTimeZone
~KTzfileTimeZone()
Definition: ktzfiletimezone.cpp:90
QDataStream::readRawData
int readRawData(char *s, int len)
KTimeZone::Phase
Definition: ktimezone.h:429
KTzfileTimeZoneBackend
Backend class for KTzfileTimeZone class.
Definition: ktzfiletimezone.h:89
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
QList::count
int count(const T &value) const
KTzfileTimeZoneSource::~KTzfileTimeZoneSource
virtual ~KTzfileTimeZoneSource()
Definition: ktzfiletimezone.cpp:154
KTzfileTimeZoneData::hasTransitions
virtual bool hasTransitions() const
Return whether daylight saving transitions are available for the time zone.
Definition: ktzfiletimezone.cpp:128
KTimeZone::LeapSeconds
Definition: ktimezone.h:560
QByteArray::constData
const char * constData() const
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
KTzfileTimeZoneBackend::~KTzfileTimeZoneBackend
~KTzfileTimeZoneBackend()
Definition: ktzfiletimezone.cpp:62
QTime::addSecs
QTime addSecs(int s) const
gmtoff
int gmtoff(time_t t)
Definition: ksystemtimezone.cpp:70
QString::endsWith
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
QDate
QString
QList< QByteArray >
QFile::open
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
QLatin1Char
KTimeZone
Base class representing a time zone.
Definition: ktimezone.h:416
KTzfileTimeZoneBackend::type
virtual QByteArray type() const
Returns the class name of the data represented by this instance.
Definition: ktzfiletimezone.cpp:70
KTzfileTimeZoneSource::KTzfileTimeZoneSource
KTzfileTimeZoneSource(const QString &location)
Constructs a time zone source.
Definition: ktzfiletimezone.cpp:147
KTzfileTimeZoneSource::location
QString location() const
Returns the local directory containing the time zone definition files.
Definition: ktzfiletimezone.cpp:159
KTzfileTimeZoneData::operator=
KTzfileTimeZoneData & operator=(const KTzfileTimeZoneData &)
Definition: ktzfiletimezone.cpp:117
QVector
QLatin1String
KTimeZoneData::operator=
KTimeZoneData & operator=(const KTimeZoneData &c)
Definition: ktimezone.cpp:1164
bool
QString::length
int length() const
QByteArray::data
char * data()
qint32
KTimeZone::Transition
Definition: ktimezone.h:513
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
KTimeZone::name
QString name() const
Returns the name of the time zone.
Definition: ktimezone.cpp:669
QDate::addDays
QDate addDays(int ndays) const
QByteArray::size
int size() const
QDateTime
ktzfiletimezone.h
TZFILE time zone functions.
KTimeZoneBackend
Base backend class for KTimeZone classes.
Definition: ktimezone.h:1120
KTzfileTimeZoneSource
A class to read and parse tzfile time zone definition files.
Definition: ktzfiletimezone.h:138
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:22:12 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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

Search



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