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

kstars

  • sources
  • kde-4.12
  • kdeedu
  • kstars
  • kstars
timezonerule.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  timezonerule.cpp - description
3  -------------------
4  begin : Tue Apr 2 2002
5  copyright : (C) 2002 by Jason Harris
6  email : kstars@30doradus.org
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "timezonerule.h"
19 
20 #include <kdebug.h>
21 #include <klocale.h>
22 
23 #include "kstarsdatetime.h"
24 
25 TimeZoneRule::TimeZoneRule() {
26  setEmpty();
27 }
28 
29 TimeZoneRule::TimeZoneRule( const QString &smonth, const QString &sday, const QTime &stime,
30  const QString &rmonth, const QString &rday, const QTime &rtime, const double &dh ) {
31  dTZ = 0.0;
32  if ( smonth != "0" ) {
33  StartMonth = initMonth( smonth );
34  RevertMonth = initMonth( rmonth );
35 
36  if ( StartMonth && RevertMonth && initDay( sday, StartDay, StartWeek ) &&
37  initDay( rday, RevertDay, RevertWeek ) && stime.isValid() && rtime.isValid() ) {
38  StartTime = stime;
39  RevertTime = rtime;
40  HourOffset = dh;
41  } else {
42  kWarning() << i18n( "Error parsing TimeZoneRule, setting to empty rule." ) ;
43  setEmpty();
44  }
45  } else { //Empty rule
46  setEmpty();
47  }
48 }
49 
50 void TimeZoneRule::setEmpty() {
51  StartMonth = 0;
52  RevertMonth = 0;
53  StartDay = 0;
54  RevertDay = 0;
55  StartWeek = -1;
56  RevertWeek = -1;
57  StartTime = QTime();
58  RevertTime = QTime();
59  HourOffset = 0.0;
60  dTZ = 0.0;
61 }
62 
63 void TimeZoneRule::setDST( bool activate ) {
64  if ( activate ) {
65  kDebug() << i18n( "Daylight Saving Time active" );
66  dTZ = HourOffset;
67  } else {
68  kDebug() << i18n( "Daylight Saving Time inactive" );
69  dTZ = 0.0;
70  }
71 }
72 
73 int TimeZoneRule::initMonth( const QString &mn ) {
74  //Check whether the argument is a three-letter English month code.
75  QString ml = mn.toLower();
76  if ( ml == "jan" ) return 1;
77  else if ( ml == "feb" ) return 2;
78  else if ( ml == "mar" ) return 3;
79  else if ( ml == "apr" ) return 4;
80  else if ( ml == "may" ) return 5;
81  else if ( ml == "jun" ) return 6;
82  else if ( ml == "jul" ) return 7;
83  else if ( ml == "aug" ) return 8;
84  else if ( ml == "sep" ) return 9;
85  else if ( ml == "oct" ) return 10;
86  else if ( ml == "nov" ) return 11;
87  else if ( ml == "dec" ) return 12;
88 
89  kWarning() << i18n( "Could not parse %1 as a valid month code.", mn );
90  return 0;
91 }
92 
93 bool TimeZoneRule::initDay( const QString &dy, int &Day, int &Week ) {
94  //Three possible ways to express a day.
95  //1. simple integer; the calendar date...set Week=0 to indicate that Date is not the day of the week
96  bool ok;
97  int day = dy.toInt( &ok );
98  if ( ok ) {
99  Day = day;
100  Week = 0;
101  return true;
102  }
103 
104  QString dl = dy.toLower();
105  //2. 3-letter day of week string, indicating the last of that day of the month
106  // ...set Week to 5 to indicate the last weekday of the month
107  if ( dl == "mon" ) { Day = 1; Week = 5; return true; }
108  else if ( dl == "tue" ) { Day = 2; Week = 5; return true; }
109  else if ( dl == "wed" ) { Day = 3; Week = 5; return true; }
110  else if ( dl == "thu" ) { Day = 4; Week = 5; return true; }
111  else if ( dl == "fri" ) { Day = 5; Week = 5; return true; }
112  else if ( dl == "sat" ) { Day = 6; Week = 5; return true; }
113  else if ( dl == "sun" ) { Day = 7; Week = 5; return true; }
114 
115  //3. 1,2 or 3 followed by 3-letter day of week string; this indicates
116  // the (1st/2nd/3rd) weekday of the month.
117  int wn = dl.left(1).toInt();
118  if ( wn >0 && wn <4 ) {
119  QString dm = dl.mid( 1, dl.length() ).toLower();
120  if ( dm == "mon" ) { Day = 1; Week = wn; return true; }
121  else if ( dm == "tue" ) { Day = 2; Week = wn; return true; }
122  else if ( dm == "wed" ) { Day = 3; Week = wn; return true; }
123  else if ( dm == "thu" ) { Day = 4; Week = wn; return true; }
124  else if ( dm == "fri" ) { Day = 5; Week = wn; return true; }
125  else if ( dm == "sat" ) { Day = 6; Week = wn; return true; }
126  else if ( dm == "sun" ) { Day = 7; Week = wn; return true; }
127  }
128 
129  kWarning() << i18n( "Could not parse %1 as a valid day code.", dy );
130  return false;
131 }
132 
133 int TimeZoneRule::findStartDay( const KStarsDateTime &d ) {
134  // Determine the calendar date of StartDay for the month and year of the given date.
135  QDate test;
136 
137  // TimeZoneRule is empty, return -1
138  if ( isEmptyRule() ) return -1;
139 
140  // If StartWeek=0, just return the integer.
141  if ( StartWeek==0 ) return StartDay;
142 
143  // Since StartWeek was not zero, StartDay is the day of the week, not the calendar date
144  else if ( StartWeek==5 ) { // count back from end of month until StartDay is found.
145  for ( test = QDate( d.date().year(), d.date().month(), d.date().daysInMonth() );
146  test.day() > 21; test = test.addDays( -1 ) )
147  if ( test.dayOfWeek() == StartDay ) break;
148  } else { // Count forward from day 1, 8 or 15 (depending on StartWeek) until correct day of week is found
149  for ( test = QDate( d.date().year(), d.date().month(), (StartWeek-1)*7 + 1 );
150  test.day() < 7*StartWeek; test = test.addDays( 1 ) )
151  if ( test.dayOfWeek() == StartDay ) break;
152  }
153  return test.day();
154 }
155 
156 int TimeZoneRule::findRevertDay( const KStarsDateTime &d ) {
157  // Determine the calendar date of RevertDay for the month and year of the given date.
158  QDate test;
159 
160  // TimeZoneRule is empty, return -1
161  if ( isEmptyRule() ) return -1;
162 
163  // If RevertWeek=0, just return the integer.
164  if ( RevertWeek==0 ) return RevertDay;
165 
166  // Since RevertWeek was not zero, RevertDay is the day of the week, not the calendar date
167  else if ( RevertWeek==5 ) { //count back from end of month until RevertDay is found.
168  for ( test = QDate( d.date().year(), d.date().month(), d.date().daysInMonth() );
169  test.day() > 21; test = test.addDays( -1 ) )
170  if ( test.dayOfWeek() == RevertDay ) break;
171  } else { //Count forward from day 1, 8 or 15 (depending on RevertWeek) until correct day of week is found
172  for ( test = QDate( d.date().year(), d.date().month(), (RevertWeek-1)*7 + 1 );
173  test.day() < 7*RevertWeek; test = test.addDays( 1 ) )
174  if ( test.dayOfWeek() == StartDay ) break;
175  }
176  return test.day();
177 }
178 
179 bool TimeZoneRule::isDSTActive( const KStarsDateTime &date ) {
180  // The empty rule always returns false
181  if ( isEmptyRule() ) return false;
182 
183  // First, check whether the month is outside the DST interval. Note that
184  // the interval check is different if StartMonth > RevertMonth (indicating that
185  // the DST interval includes the end of the year).
186  int month = date.date().month();
187 
188  if ( StartMonth < RevertMonth ) {
189  if ( month < StartMonth || month > RevertMonth ) return false;
190  } else {
191  if ( month < StartMonth && month > RevertMonth ) return false;
192  }
193 
194  // OK, if the month is equal to StartMonth or Revert Month, we have more
195  // detailed checking to do...
196  int day = date.date().day();
197 
198  if ( month == StartMonth ) {
199  int sday = findStartDay( date );
200  if ( day < sday ) return false;
201  if ( day==sday && date.time() < StartTime ) return false;
202  } else if ( month == RevertMonth ) {
203  int rday = findRevertDay( date );
204  if ( day > rday ) return false;
205  if ( day==rday && date.time() > RevertTime ) return false;
206  }
207 
208  // passed all tests, so we must be in DST.
209  return true;
210 }
211 
212 void TimeZoneRule::nextDSTChange_LTime( const KStarsDateTime &date ) {
213  KStarsDateTime result;
214 
215  // return an invalid date if the rule is the empty rule.
216  if ( isEmptyRule() ) result = KDateTime();
217 
218  else if ( deltaTZ() ) {
219  // Next change is reverting back to standard time.
220 
221  //y is the year for the next DST Revert date. It's either the current year, or
222  //the next year if the current month is already past RevertMonth
223  int y = date.date().year();
224  if ( RevertMonth < date.date().month() ) ++y;
225 
226  result = KStarsDateTime( QDate( y, RevertMonth, 1 ), RevertTime );
227  result = KStarsDateTime( QDate( y, RevertMonth, findRevertDay( result ) ), RevertTime );
228 
229  } else {
230  // Next change is starting DST.
231 
232  //y is the year for the next DST Start date. It's either the current year, or
233  //the next year if the current month is already past StartMonth
234  int y = date.date().year();
235  if ( StartMonth < date.date().month() ) ++y;
236 
237  result = KStarsDateTime( QDate( y, StartMonth, 1 ), StartTime );
238  result = KStarsDateTime( QDate( y, StartMonth, findStartDay( result ) ), StartTime );
239  }
240 
241  kDebug() << i18n( "Next Daylight Savings Time change (Local Time): " ) << result.toString();
242  next_change_ltime = result;
243 }
244 
245 
246 void TimeZoneRule::previousDSTChange_LTime( const KStarsDateTime &date ) {
247  KStarsDateTime result;
248 
249  // return an invalid date if the rule is the empty rule
250  if ( isEmptyRule() ) next_change_ltime = KDateTime();
251 
252  if ( deltaTZ() ) {
253  // Last change was starting DST.
254 
255  //y is the year for the previous DST Start date. It's either the current year, or
256  //the previous year if the current month is earlier than StartMonth
257  int y = date.date().year();
258  if ( StartMonth > date.date().month() ) --y;
259 
260  result = KStarsDateTime( QDate( y, StartMonth, 1 ), StartTime );
261  result = KStarsDateTime( QDate( y, StartMonth, findStartDay( result ) ), StartTime );
262 
263  } else if ( StartMonth ) {
264  //Last change was reverting to standard time.
265 
266  //y is the year for the previous DST Start date. It's either the current year, or
267  //the previous year if the current month is earlier than StartMonth
268  int y = date.date().year();
269  if ( RevertMonth > date.date().month() ) --y;
270 
271  result = KStarsDateTime( QDate( y, RevertMonth, 1 ), RevertTime );
272  result = KStarsDateTime( QDate( y, RevertMonth, findRevertDay( result ) ), RevertTime );
273  }
274 
275  kDebug() << i18n( "Previous Daylight Savings Time change (Local Time): " ) << result.toString();
276  next_change_ltime = result;
277 }
278 
280 void TimeZoneRule::nextDSTChange( const KStarsDateTime &local_date, const double TZoffset ) {
281  // just decrement timezone offset and hour offset
282  KStarsDateTime result = local_date.addSecs( int( (TZoffset + deltaTZ()) * -3600) );
283 
284  kDebug() << i18n( "Next Daylight Savings Time change (UTC): " ) << result.toString();
285  next_change_utc = result;
286 }
287 
289 void TimeZoneRule::previousDSTChange( const KStarsDateTime &local_date, const double TZoffset ) {
290  // just decrement timezone offset
291  KStarsDateTime result = local_date.addSecs( int( TZoffset * -3600) );
292 
293  // if prev DST change is a revert change, so the revert time is in daylight saving time
294  if ( result.date().month() == RevertMonth )
295  result = result.addSecs( int(HourOffset * -3600) );
296 
297  kDebug() << i18n( "Previous Daylight Savings Time change (UTC): " ) << result.toString();
298  next_change_utc = result;
299 }
300 
301 void TimeZoneRule::reset_with_ltime( KStarsDateTime &ltime, const double TZoffset, const bool time_runs_forward,
302  const bool automaticDSTchange ) {
303 
318  //don't need to do anything for empty rule
319  if ( isEmptyRule() ) return;
320 
321  // check if DST is active before resetting with new time
322  bool wasDSTactive(false);
323 
324  if ( deltaTZ() != 0.0 ) {
325  wasDSTactive = true;
326  }
327 
328  // check if current time is start time, this means if a DST change happend in last hour(s)
329  bool active_with_houroffset = isDSTActive(ltime.addSecs( int(HourOffset * -3600) ) );
330  bool active_normal = isDSTActive( ltime );
331 
332  // store a valid local time
333  KStarsDateTime ValidLTime = ltime;
334 
335  if ( active_with_houroffset != active_normal && ValidLTime.date().month() == StartMonth ) {
336  // current time is the start time
337  kDebug() << "Current time = Starttime: invalid local time due to daylight saving time";
338 
339  // set a correct local time because the current time doesn't exists
340  // if automatic DST change happend, new DST setting is the opposite of current setting
341  if ( automaticDSTchange ) {
342  // revert DST status
343  setDST( !wasDSTactive );
344  // new setting DST is inactive, so subtract hour offset to new time
345  if ( wasDSTactive ) {
346  // DST inactive
347  ValidLTime = ltime.addSecs( int( HourOffset * - 3600) );
348  } else {
349  // DST active
350  // add hour offset to new time
351  ValidLTime = ltime.addSecs( int( HourOffset * 3600) );
352  }
353  } else { // if ( automaticDSTchange )
354  // no automatic DST change happend, so stay in current DST mode
355  setDST( wasDSTactive );
356  if ( wasDSTactive ) {
357  // DST active
358  // add hour offset to current time, because time doesn't exists
359  ValidLTime = ltime.addSecs( int( HourOffset * 3600) );
360  } else {
361  // DST inactive
362  // subtrace hour offset to current time, because time doesn't exists
363  ValidLTime = ltime.addSecs( int( HourOffset * -3600) );
364  }
365  } // else { // if ( automaticDSTchange )
366 
367  } else { // if ( active_with_houroffset != active_normal && ValidLTime.date().month() == StartMonth )
368  // If current time was not start time, so check if current time is revert time
369  // this means if a DST change happend in next hour(s)
370  active_with_houroffset = isDSTActive(ltime.addSecs( int(HourOffset * 3600) ) );
371  if ( active_with_houroffset != active_normal && RevertMonth == ValidLTime.date().month() ) {
372  // current time is the revert time
373  kDebug() << "Current time = Reverttime";
374 
375  // we don't kneed to change the local time, because local time always exists, but
376  // some times exists twice, so we have to reset DST status
377  if ( automaticDSTchange ) {
378  // revert DST status
379  setDST( !wasDSTactive );
380  } else {
381  // no automatic DST change so stay in current DST mode
382  setDST( wasDSTactive );
383  }
384 
385  } else {
386  //Current time was neither starttime nor reverttime, so use normal calculated DST status
387  setDST( active_normal );
388  }
389  } // if ( active_with_houroffset != active_normal && ValidLTime.date().month() == StartMonth )
390 
391  // kDebug() << "Using Valid Local Time = " << ValidLTime.toString();
392 
393  if (time_runs_forward) {
394  // get next DST change time in local time
395  nextDSTChange_LTime( ValidLTime );
396  nextDSTChange( next_change_ltime, TZoffset );
397  } else {
398  // get previous DST change time in local time
399  previousDSTChange_LTime( ValidLTime );
400  previousDSTChange( next_change_ltime, TZoffset );
401  }
402  ltime = ValidLTime;
403 }
404 
405 
406 bool TimeZoneRule::equals( TimeZoneRule *r ) {
407  if ( StartDay == r->StartDay && RevertDay == r->RevertDay &&
408  StartWeek == r->StartWeek && RevertWeek == r->RevertWeek &&
409  StartMonth == r->StartMonth && RevertMonth == r->RevertMonth &&
410  StartTime == r->StartTime && RevertTime == r->RevertTime &&
411  isEmptyRule() == r->isEmptyRule() )
412  return true;
413  else
414  return false;
415 }
TimeZoneRule::deltaTZ
double deltaTZ() const
Definition: timezonerule.h:88
TimeZoneRule::setDST
void setDST(bool activate=true)
Toggle DST on/off.
Definition: timezonerule.cpp:63
TimeZoneRule::nextDSTChange_LTime
KStarsDateTime nextDSTChange_LTime()
Definition: timezonerule.h:106
TimeZoneRule
This class provides the information needed to determine whether Daylight Savings Time (DST; a...
Definition: timezonerule.h:56
timezonerule.h
TimeZoneRule::nextDSTChange
KStarsDateTime nextDSTChange()
Definition: timezonerule.h:103
KStarsDateTime::addSecs
KStarsDateTime addSecs(double s) const
Definition: kstarsdatetime.cpp:127
KStarsDateTime
Extension of KDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day...
Definition: kstarsdatetime.h:45
KDateTime
TimeZoneRule::reset_with_ltime
void reset_with_ltime(KStarsDateTime &ltime, const double TZoffset, const bool time_runs_forward, const bool automaticDSTchange=false)
Recalculate next dst change and if DST is active by a given local time with timezone offset and time ...
Definition: timezonerule.cpp:301
TimeZoneRule::TimeZoneRule
TimeZoneRule()
Default Constructor.
Definition: timezonerule.cpp:25
NaN::d
const double d
Definition: nan.h:35
kstarsdatetime.h
TimeZoneRule::isEmptyRule
bool isEmptyRule()
Definition: timezonerule.h:79
TimeZoneRule::equals
bool equals(TimeZoneRule *r)
Definition: timezonerule.cpp:406
TimeZoneRule::isDSTActive
bool isDSTActive(const KStarsDateTime &date)
Determine whether DST is in effect for the given DateTime, according to this rule.
Definition: timezonerule.cpp:179
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:36:21 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kstars

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

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

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