• 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
ktimezone_win.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the KDE libraries
3  Copyright (c) 2008 Marc Mutz <mutz@kde.org>, Till Adam <adam@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 
22 #include "ktimezone_win.h"
23 #include <config.h>
24 
25 #include <kdebug.h>
26 
27 #include <QStringList>
28 #include <QLibrary>
29 
30 #include <windows.h>
31 
32 #include <memory>
33 #include <string>
34 #include <cassert>
35 
36 struct ZoneKey {
37  QString zoneOlson;
38  QString zoneWin;
39 };
40 
41 static const ZoneKey ZoneTbl[] =
42 {
43  {QLatin1String("Australia/Darwin"), QLatin1String("AUS Central Standard Time")},
44  {QLatin1String("Australia/Sydney"), QLatin1String("AUS Eastern Standard Time")},
45  {QLatin1String("Asia/Kabul"), QLatin1String("Afghanistan Standard Time")},
46  {QLatin1String("America/Anchorage"), QLatin1String("Alaskan Standard Time")},
47  {QLatin1String("Asia/Riyadh"), QLatin1String("Arab Standard Time")},
48  {QLatin1String("Asia/Dubai"), QLatin1String("Arabian Standard Time")},
49  {QLatin1String("Asia/Baghdad"), QLatin1String("Arabic Standard Time")},
50  {QLatin1String("America/Buenos_Aires"), QLatin1String("Argentina Standard Time")},
51  {QLatin1String("Asia/Yerevan"), QLatin1String("Armenian Standard Time")},
52  {QLatin1String("America/Halifax"), QLatin1String("Atlantic Standard Time")},
53  {QLatin1String("Asia/Baku"), QLatin1String("Azerbaijan Standard Time")},
54  {QLatin1String("Atlantic/Azores"), QLatin1String("Azores Standard Time")},
55  {QLatin1String("America/Regina"), QLatin1String("Canada Central Standard Time")},
56  {QLatin1String("Atlantic/Cape_Verde"), QLatin1String("Cape Verde Standard Time")},
57  {QLatin1String("Asia/Yerevan"), QLatin1String("Caucasus Standard Time")},
58  {QLatin1String("Australia/Adelaide"), QLatin1String("Cen. Australia Standard Time")},
59  {QLatin1String("America/Guatemala"), QLatin1String("Central America Standard Time")},
60  {QLatin1String("Asia/Dhaka"), QLatin1String("Central Asia Standard Time")},
61  {QLatin1String("America/Manaus"), QLatin1String("Central Brazilian Standard Time")},
62  {QLatin1String("Europe/Budapest"), QLatin1String("Central Europe Standard Time")},
63  {QLatin1String("Europe/Warsaw"), QLatin1String("Central European Standard Time")},
64  {QLatin1String("Pacific/Guadalcanal"), QLatin1String("Central Pacific Standard Time")},
65  {QLatin1String("America/Chicago"), QLatin1String("Central Standard Time")},
66  {QLatin1String("America/Mexico_City"), QLatin1String("Central Standard Time (Mexico)")},
67  {QLatin1String("Asia/Shanghai"), QLatin1String("China Standard Time")},
68  {QLatin1String("Etc/GMT+12"), QLatin1String("Dateline Standard Time")},
69  {QLatin1String("Africa/Nairobi"), QLatin1String("E. Africa Standard Time")},
70  {QLatin1String("Australia/Brisbane"), QLatin1String("E. Australia Standard Time")},
71  {QLatin1String("Europe/Minsk"), QLatin1String("E. Europe Standard Time")},
72  {QLatin1String("America/Sao_Paulo"), QLatin1String("E. South America Standard Time")},
73  {QLatin1String("America/New_York"), QLatin1String("Eastern Standard Time")},
74  {QLatin1String("Africa/Cairo"), QLatin1String("Egypt Standard Time")},
75  {QLatin1String("Asia/Yekaterinburg"), QLatin1String("Ekaterinburg Standard Time")},
76  {QLatin1String("Europe/Kiev"), QLatin1String("FLE Standard Time")},
77  {QLatin1String("Pacific/Fiji"), QLatin1String("Fiji Standard Time")},
78  {QLatin1String("Europe/London"), QLatin1String("GMT Standard Time")},
79  {QLatin1String("Europe/Istanbul"), QLatin1String("GTB Standard Time")},
80  {QLatin1String("Etc/GMT-3"), QLatin1String("Georgian Standard Time")},
81  {QLatin1String("America/Godthab"), QLatin1String("Greenland Standard Time")},
82  {QLatin1String("Atlantic/Reykjavik"), QLatin1String("Greenwich Standard Time")},
83  {QLatin1String("Pacific/Honolulu"), QLatin1String("Hawaiian Standard Time")},
84  {QLatin1String("Asia/Calcutta"), QLatin1String("India Standard Time")},
85  {QLatin1String("Asia/Tehran"), QLatin1String("Iran Standard Time")},
86  {QLatin1String("Asia/Jerusalem"), QLatin1String("Israel Standard Time")},
87  {QLatin1String("Asia/Amman"), QLatin1String("Jordan Standard Time")},
88  {QLatin1String("Asia/Seoul"), QLatin1String("Korea Standard Time")},
89  {QLatin1String("Indian/Mauritius"), QLatin1String("Mauritius Standard Time")},
90  {QLatin1String("America/Mexico_City"), QLatin1String("Mexico Standard Time")},
91  {QLatin1String("America/Chihuahua"), QLatin1String("Mexico Standard Time 2")},
92  {QLatin1String("Atlantic/South_Georgia"), QLatin1String("Mid-Atlantic Standard Time")},
93  {QLatin1String("Asia/Beirut"), QLatin1String("Middle East Standard Time")},
94  {QLatin1String("America/Montevideo"), QLatin1String("Montevideo Standard Time")},
95  {QLatin1String("Africa/Casablanca"), QLatin1String("Morocco Standard Time")},
96  {QLatin1String("America/Denver"), QLatin1String("Mountain Standard Time")},
97  {QLatin1String("America/Chihuahua"), QLatin1String("Mountain Standard Time (Mexico)")},
98  {QLatin1String("Asia/Rangoon"), QLatin1String("Myanmar Standard Time")},
99  {QLatin1String("Asia/Novosibirsk"), QLatin1String("N. Central Asia Standard Time")},
100  {QLatin1String("Africa/Windhoek"), QLatin1String("Namibia Standard Time")},
101  {QLatin1String("Asia/Katmandu"), QLatin1String("Nepal Standard Time")},
102  {QLatin1String("Pacific/Auckland"), QLatin1String("New Zealand Standard Time")},
103  {QLatin1String("America/St_Johns"), QLatin1String("Newfoundland Standard Time")},
104  {QLatin1String("Asia/Irkutsk"), QLatin1String("North Asia East Standard Time")},
105  {QLatin1String("Asia/Krasnoyarsk"), QLatin1String("North Asia Standard Time")},
106  {QLatin1String("America/Santiago"), QLatin1String("Pacific SA Standard Time")},
107  {QLatin1String("America/Los_Angeles"), QLatin1String("Pacific Standard Time")},
108  {QLatin1String("America/Tijuana"), QLatin1String("Pacific Standard Time (Mexico)")},
109  {QLatin1String("Asia/Karachi"), QLatin1String("Pakistan Standard Time")},
110  {QLatin1String("Europe/Paris"), QLatin1String("Romance Standard Time")},
111  {QLatin1String("Europe/Moscow"), QLatin1String("Russian Standard Time")},
112  {QLatin1String("Etc/GMT+3"), QLatin1String("SA Eastern Standard Time")},
113  {QLatin1String("America/Bogota"), QLatin1String("SA Pacific Standard Time")},
114  {QLatin1String("America/La_Paz"), QLatin1String("SA Western Standard Time")},
115  {QLatin1String("Asia/Bangkok"), QLatin1String("SE Asia Standard Time")},
116  {QLatin1String("Pacific/Apia"), QLatin1String("Samoa Standard Time")},
117  {QLatin1String("Asia/Singapore"), QLatin1String("Singapore Standard Time")},
118  {QLatin1String("Africa/Johannesburg"), QLatin1String("South Africa Standard Time")},
119  {QLatin1String("Asia/Colombo"), QLatin1String("Sri Lanka Standard Time")},
120  {QLatin1String("Asia/Taipei"), QLatin1String("Taipei Standard Time")},
121  {QLatin1String("Australia/Hobart"), QLatin1String("Tasmania Standard Time")},
122  {QLatin1String("Asia/Tokyo"), QLatin1String("Tokyo Standard Time")},
123  {QLatin1String("Pacific/Tongatapu"), QLatin1String("Tonga Standard Time")},
124  {QLatin1String("Etc/GMT+5"), QLatin1String("US Eastern Standard Time")},
125  {QLatin1String("America/Phoenix"), QLatin1String("US Mountain Standard Time")},
126  {QLatin1String("America/Caracas"), QLatin1String("Venezuela Standard Time")},
127  {QLatin1String("Asia/Vladivostok"), QLatin1String("Vladivostok Standard Time")},
128  {QLatin1String("Australia/Perth"), QLatin1String("W. Australia Standard Time")},
129  {QLatin1String("Africa/Lagos"), QLatin1String("W. Central Africa Standard Time")},
130  {QLatin1String("Europe/Berlin"), QLatin1String("W. Europe Standard Time")},
131  {QLatin1String("Asia/Tashkent"), QLatin1String("West Asia Standard Time")},
132  {QLatin1String("Pacific/Port_Moresby"), QLatin1String("West Pacific Standard Time")},
133  {QLatin1String("Asia/Yakutsk"), QLatin1String("Yakutsk Standard Time")}
134 };
135 
136 static QString getWinZoneName(const QString &name)
137 {
138  for ( int i = 0; i < sizeof(ZoneTbl) / sizeof(ZoneTbl[0]); ++i ) {
139  if (ZoneTbl[i].zoneOlson == name) {
140  return ZoneTbl[i].zoneWin;
141  }
142  }
143 
144  return name;
145 }
146 
147 typedef BOOL (WINAPI *PtrTzSpecificLocalTimeToSystemTime )(LPTIME_ZONE_INFORMATION lpTimeZoneInformation,
148  LPSYSTEMTIME lpLocalTime,
149  LPSYSTEMTIME lpUniversalTime
150 );
151 static PtrTzSpecificLocalTimeToSystemTime pTzSpecificLocalTimeToSystemTime = 0;
152 
153 namespace {
154  class HKeyCloser {
155  const HKEY hkey;
156  Q_DISABLE_COPY( HKeyCloser )
157  public:
158  explicit HKeyCloser( HKEY hk ) : hkey( hk ) {}
159  ~HKeyCloser() { RegCloseKey( hkey ); }
160  };
161 
162  struct TZI {
163  LONG Bias;
164  LONG StandardBias;
165  LONG DaylightBias;
166  SYSTEMTIME StandardDate;
167  SYSTEMTIME DaylightDate;
168  };
169 }
170 
171 // TCHAR can be either uchar, or wchar_t:
172 #ifdef UNICODE
173 
174 static inline QString tchar_to_qstring( const TCHAR * str ) {
175  return QString::fromUtf16( reinterpret_cast<const ushort*>( str ) );
176 }
177 
178 static inline const TCHAR * qstring_to_tchar( const QString& str ) {
179  return reinterpret_cast<const TCHAR*>( str.utf16() );
180 }
181 
182 static inline std::basic_string<TCHAR> qstring_to_tcharstring( const QString& str ) {
183  return std::basic_string<TCHAR>( qstring_to_tchar(str) );
184 }
185 
186 #else
187 
188 static inline QString tchar_to_qstring( const TCHAR * str ) {
189  return QString::fromLocal8Bit( str );
190 }
191 
192 static inline const TCHAR * qstring_to_tchar( const QString& str ) {
193  return str.toLocal8Bit().constData();
194 }
195 
196 static inline std::basic_string<TCHAR> qstring_to_tcharstring( const QString& str ) {
197  return std::basic_string<TCHAR>( qstring_to_tchar(str) );
198 }
199 
200 #endif
201 
202 static const TCHAR timeZonesKey[] = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones");
203 static inline QDateTime systemtime_to_qdatetime( const SYSTEMTIME & st ) {
204  return QDateTime( QDate( st.wYear, st.wMonth, st.wDay ),
205  QTime( st.wHour, st.wMinute, st.wSecond, st.wMilliseconds ) );
206 }
207 
208 static SYSTEMTIME qdatetime_to_systemtime( const QDateTime & dt ) {
209  const QDate d = dt.date();
210  const QTime t = dt.time();
211  const SYSTEMTIME st = {
212  d.year(),
213  d.month(),
214  d.dayOfWeek() % 7, // 1..7 (Mon..Sun)->0..6(Sun..Sat)
215  d.day(),
216  t.hour(),
217  t.minute(),
218  t.second(),
219  t.msec(),
220  };
221  return st;
222 }
223 
224 static bool TzSpecificLocalTimeToSystemTime_Portable( TIME_ZONE_INFORMATION* tz,
225  SYSTEMTIME *i_stLocal,
226  SYSTEMTIME *o_stUniversal )
227 {
228 
229  // the method below was introduced in XP. If it's there, use it, otherwise
230  // fall back to doing things manually
231  if (!pTzSpecificLocalTimeToSystemTime) {
232  QLibrary kernelLib(QLatin1String("kernel32"));
233  pTzSpecificLocalTimeToSystemTime = (PtrTzSpecificLocalTimeToSystemTime)kernelLib.resolve("TzSpecificLocalTimeToSystemTime");
234  }
235 
236  if ( pTzSpecificLocalTimeToSystemTime )
237  return pTzSpecificLocalTimeToSystemTime( tz, i_stLocal , o_stUniversal ) != 0;
238 
239  // the algorithm is:
240  // - switch to the desired timezone temporarily
241  // - convert system time to (local) file time in that timezone
242  // - convert local file time to utc file time
243  // - convert utc file time to system time
244  // - reset timezone
245  FILETIME ft, ft_utc;
246  int result = 1;
247  TIME_ZONE_INFORMATION currentTimeZone;
248  result = GetTimeZoneInformation(&currentTimeZone);
249  if ( result == TIME_ZONE_ID_INVALID ) {
250  kWarning(161) << "Getting time zone information failed";
251  return false;
252  }
253  result = SetTimeZoneInformation(tz);
254  if ( result == 0 ) {
255  kWarning(161) << "Setting temporary time zone failed";
256  return false;
257  }
258  result = SystemTimeToFileTime(i_stLocal, &ft);
259  if ( result == 0 ) {
260  kWarning(161) << "SysteTimeToFileTime failed";
261  return false;
262  }
263  result = LocalFileTimeToFileTime(&ft, &ft_utc);
264  if ( result == 0 ) {
265  kWarning(161) << "LocalFileTimeToFileTime failed";
266  return false;
267  }
268  result = FileTimeToSystemTime(&ft_utc,o_stUniversal);
269  if ( result == 0 ) {
270  kWarning(161) << "FileTimeToSystemTime failed";
271  return false;
272  }
273  result = SetTimeZoneInformation(&currentTimeZone);
274  if ( result == 0 ) {
275  kWarning(161) << "Re-setting time zone information failed";
276  return false;
277  }
278  return true;
279 }
280 
281 
282 
283 
284 static bool get_binary_value( HKEY key, const TCHAR * value, void * data, DWORD numData, DWORD * outNumData=0 ) {
285  DWORD size = numData;
286  DWORD type = REG_BINARY;
287  if ( RegQueryValueEx( key, value, 0, &type, (LPBYTE)data, &size ) != ERROR_SUCCESS )
288  return false;
289  assert( type == REG_BINARY );
290  if ( type != REG_BINARY )
291  return false;
292  if ( outNumData )
293  *outNumData = size;
294  return true;
295 }
296 
297 static bool get_string_value( HKEY key, const TCHAR * value, TCHAR * dest, DWORD destSizeInBytes ) {
298  DWORD size = destSizeInBytes;
299  DWORD type = REG_SZ;
300  dest[0] = '\0';
301  if ( RegQueryValueEx( key, value, 0, &type, (LPBYTE)dest, &size ) != ERROR_SUCCESS )
302  return false;
303  //dest[ qMin( size, destSizeInBytes - sizeof( WCHAR ) ) / sizeof( WCHAR ) ] = 0;
304  assert( type == REG_SZ );
305  if ( type != REG_SZ )
306  return false;
307  return true;
308 }
309 
310 //
311 //
312 // Backend interface impl:
313 //
314 //
315 
316 static bool check_prereq( const KTimeZone * caller, const QDateTime & dt, Qt::TimeSpec spec ) {
317  return caller && caller->isValid() && dt.isValid() && dt.timeSpec() == spec ;
318 }
319 
320 static inline bool check_local( const KTimeZone * caller, const QDateTime & dt ) {
321  return check_prereq( caller, dt, Qt::LocalTime );
322 }
323 
324 static inline bool check_utc( const KTimeZone * caller, const QDateTime & dt ) {
325  return check_prereq( caller, dt, Qt::UTC );
326 }
327 
328 static bool has_transition( const TIME_ZONE_INFORMATION & tz ) {
329  return tz.StandardDate.wMonth != 0 && tz.DaylightDate.wMonth != 0 ;
330 }
331 
332 static int win_dayofweek_to_qt_dayofweek( int wdow ) {
333  // Sun(0)..Sat(6) -> Mon(1)...Sun(7)
334  return wdow ? wdow : 7 ;
335 }
336 
337 static int qt_dayofweek_to_win_dayofweek( int qdow ) {
338  // Mon(1)...Sun(7) -> Sub(0)...Sat(6)
339  return qdow % 7;
340 }
341 
342 static QDate find_nth_weekday_in_month_of_year( int nth, int dayOfWeek, int month, int year ) {
343  assert( nth >= 1 );
344  assert( nth <= 5 );
345 
346  const QDate first( year, month, 1 );
347  const int actualDayOfWeek = first.dayOfWeek();
348  QDate candidate = first.addDays( ( nth - 1 ) * 7 + dayOfWeek - actualDayOfWeek );
349  assert( candidate.dayOfWeek() == dayOfWeek );
350  if ( nth == 5 )
351  if ( candidate.month() != month )
352  candidate = candidate.addDays( -7 );
353  assert( candidate.month() == month );
354  return candidate;
355 }
356 
357 static QDateTime transition( const SYSTEMTIME & st, int year ) {
358  assert( st.wYear == 0 );
359  assert( st.wMonth != 0 );
360  return QDateTime( find_nth_weekday_in_month_of_year( st.wDay, win_dayofweek_to_qt_dayofweek( st.wDayOfWeek ), st.wMonth, year ),
361  QTime( st.wHour, st.wMinute, st.wSecond, st.wMilliseconds ) );
362 }
363 
364 struct Transitions {
365  QDateTime stdStart, dstStart;
366 };
367 
368 Transitions transitions( const TIME_ZONE_INFORMATION & tz, int year ) {
369  const Transitions t = {
370  transition( tz.StandardDate, year ), transition( tz.DaylightDate, year )
371  };
372  return t;
373 }
374 
375 
376 static const int MAX_KEY_LENGTH = 255;
377 
378 static QStringList list_key( HKEY key ) {
379 
380  DWORD numSubKeys = 0;
381  QStringList result;
382 
383  if ( RegQueryInfoKey( key, 0, 0, 0, &numSubKeys, 0, 0, 0, 0, 0, 0, 0 ) == ERROR_SUCCESS )
384  for ( DWORD i = 0 ; i < numSubKeys ; ++i ) {
385  TCHAR name[MAX_KEY_LENGTH+1];
386  DWORD nameLen = MAX_KEY_LENGTH;
387  if ( RegEnumKeyEx( key, i, name, &nameLen, 0, 0, 0, 0 ) == ERROR_SUCCESS )
388  result.push_back( tchar_to_qstring( name ) );
389  }
390 
391  return result;
392 }
393 
394 static QStringList list_standard_names()
395 {
396  QStringList standardNames;
397 
398  HKEY timeZones;
399  QStringList keys;
400  if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, timeZonesKey, 0, KEY_READ, &timeZones ) == ERROR_SUCCESS )
401  keys = list_key(timeZones);
402 
403  std::basic_string<TCHAR> path( timeZonesKey );
404  path += TEXT( "\\" );
405 
406  const HKeyCloser closer( timeZones );
407  Q_FOREACH( const QString & keyname, keys ) {
408 
409  std::basic_string<TCHAR> keypath(path);
410  keypath += qstring_to_tcharstring(keyname);
411  HKEY key;
412  if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, keypath.c_str(), 0, KEY_READ, &key ) != ERROR_SUCCESS ) {
413  return standardNames; // FIXME what's the right error handling here?
414  }
415 
416  const HKeyCloser closer( key );
417 
418  TIME_ZONE_INFORMATION tz;
419  get_string_value( key, L"Std", tz.StandardName, sizeof( tz.StandardName ) );
420 
421  standardNames << tchar_to_qstring(tz.StandardName);
422  }
423 
424  for ( int i = 0; i < sizeof(ZoneTbl) / sizeof(ZoneTbl[0]); ++i ) {
425  standardNames << ZoneTbl[i].zoneOlson;
426  }
427 
428  return standardNames;
429 }
430 
431 static std::basic_string<TCHAR> pathFromZoneName(const KTimeZone& zone)
432 {
433  std::basic_string<TCHAR> path( timeZonesKey );
434  path += TEXT( "\\" );
435 
436  QString name = zone.name();
437 
438  name = getWinZoneName(name);
439 
440  HKEY timeZones;
441  QStringList keys;
442  if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, timeZonesKey, 0, KEY_READ, &timeZones ) == ERROR_SUCCESS )
443  keys = list_key(timeZones);
444 
445  const HKeyCloser closer( timeZones );
446  Q_FOREACH( const QString & keyname, keys ) {
447 
448  std::basic_string<TCHAR> keypath(path);
449  keypath += qstring_to_tcharstring(keyname);
450  HKEY key;
451  if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, keypath.c_str(), 0, KEY_READ, &key ) != ERROR_SUCCESS ) {
452  return 0; // FIXME what's the right error handling here?
453  }
454 
455  const HKeyCloser closer( key );
456 
457  TIME_ZONE_INFORMATION tz;
458  get_string_value( key, L"Std", tz.StandardName, sizeof( tz.StandardName ) );
459 
460  if ( tchar_to_qstring(tz.StandardName) == name ) {
461  return keypath;
462  }
463  }
464  Q_ASSERT(false);
465 
466  return path;
467 }
468 
469 /******************************************************************************/
470 
471 class KSystemTimeZoneSourceWindowsPrivate
472 {
473 public:
474  KSystemTimeZoneSourceWindowsPrivate() {}
475  ~KSystemTimeZoneSourceWindowsPrivate() {}
476 };
477 
478 
479 class KSystemTimeZoneBackendWindows : public KTimeZoneBackend
480 {
481 public:
482  KSystemTimeZoneBackendWindows(KTimeZoneSource *source, const QString &name)
483  : KTimeZoneBackend(source, name) {}
484 
485  ~KSystemTimeZoneBackendWindows() {}
486 
487  KSystemTimeZoneBackendWindows *clone() const;
488 
489  QByteArray type() const;
490 
491  int offsetAtZoneTime(const KTimeZone *caller, const QDateTime &zoneDateTime, int *secondOffset) const;
492  int offsetAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const;
493  int offset(const KTimeZone *caller, time_t t) const;
494  bool isDstAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const;
495  bool isDst(const KTimeZone *caller, time_t t) const;
496 };
497 
498 class KSystemTimeZoneDataWindows : public KTimeZoneData
499 {
500 public:
501  KSystemTimeZoneDataWindows()
502  :KTimeZoneData()
503  {
504 
505  }
506  TIME_ZONE_INFORMATION _tzi;
507  QString displayName;
508 
509  const TIME_ZONE_INFORMATION & tzi( int year = 0 ) const { Q_UNUSED( year ); return _tzi; }
510 };
511 
512 KSystemTimeZoneSourceWindows::KSystemTimeZoneSourceWindows()
513 :d( new KSystemTimeZoneSourceWindowsPrivate )
514 {
515 }
516 
517 KTimeZoneData* KSystemTimeZoneSourceWindows::parse(const KTimeZone &zone) const
518 {
519  KSystemTimeZoneDataWindows* data = new KSystemTimeZoneDataWindows();
520 
521  std::basic_string<TCHAR> path = pathFromZoneName(zone);
522 
523  HKEY key;
524  if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, path.c_str(), 0, KEY_READ, &key ) != ERROR_SUCCESS ) {
525  delete data;
526  return 0; // FIXME what's the right error handling here?
527  }
528 
529  const HKeyCloser closer( key );
530 
531  TZI tzi = { 0 };
532 
533  if ( !get_binary_value( key, TEXT( "TZI" ), &tzi, sizeof( TZI ) ) ) {
534  delete data;
535  return 0; // ?
536  }
537 
538  get_string_value( key, L"Std", data->_tzi.StandardName, sizeof( data->_tzi.StandardName ) );
539  get_string_value( key, L"Dlt", data->_tzi.DaylightName, sizeof( data->_tzi.DaylightName ) );
540 
541  TCHAR display[512];
542  get_string_value( key, L"Display", display, sizeof( display ) );
543  data->displayName = tchar_to_qstring( display );
544 
545 #define COPY( name ) data->_tzi.name = tzi.name
546  COPY( Bias );
547  COPY( StandardBias );
548  COPY( StandardDate );
549  COPY( DaylightBias );
550  COPY( DaylightDate );
551 #undef COPY
552 
553  return data;
554 }
555 
556 Transitions transitions( const KTimeZone * caller, int year ) {
557  return transitions( static_cast<const KSystemTimeZoneDataWindows*>( caller->data(true) )->tzi( year ), year );
558 }
559 
560 static bool is_dst( const TIME_ZONE_INFORMATION & tzi, const QDateTime & utc, int year ) {
561  if ( !has_transition( tzi ) )
562  return false;
563  const Transitions trans = transitions( tzi, year );
564  if ( trans.stdStart < trans.dstStart )
565  return trans.dstStart <= utc || utc < trans.stdStart ;
566  else
567  return trans.dstStart <= utc && utc < trans.stdStart ;
568 }
569 
570 static bool is_dst( const KTimeZone * caller, const QDateTime & utc ) {
571  assert( caller );
572  assert( caller->isValid() );
573  const int year = utc.date().year();
574  const TIME_ZONE_INFORMATION & tzi = static_cast<const KSystemTimeZoneDataWindows*>( caller->data(true) )->tzi( year );
575  return is_dst( tzi, utc, year );
576 }
577 
578 static int effective_offset( const TIME_ZONE_INFORMATION& tz, bool isDst ) {
579  int bias = tz.Bias;
580  if ( has_transition( tz ) )
581  if ( isDst )
582  bias += tz.DaylightBias;
583  else
584  bias += tz.StandardBias;
585  return bias * -60; // min -> secs
586 }
587 
588 static int offset_at_utc( const KTimeZone * caller, const QDateTime & utc ) {
589  assert( caller );
590  assert( caller->isValid() );
591  const int year = utc.date().year();
592  const TIME_ZONE_INFORMATION & tz = static_cast<const KSystemTimeZoneDataWindows*>( caller->data(true) )->tzi( year );
593  return effective_offset( tz, is_dst( tz, utc, year ) );
594 }
595 
596 static const int OneHour = 3600; //sec
597 
598 static int difference( const SYSTEMTIME & st1, const SYSTEMTIME & st2 ) {
599  return systemtime_to_qdatetime( st1 ).secsTo( systemtime_to_qdatetime( st2 ) );
600 }
601 
602 static int offset_at_zone_time( const KTimeZone * caller, const SYSTEMTIME & zone, int * secondOffset ) {
603  assert( caller );
604  assert( caller->isValid() );
605  assert(caller->data(true));
606  const KSystemTimeZoneDataWindows * const data = static_cast<const KSystemTimeZoneDataWindows*>( caller->data(true) );
607  const TIME_ZONE_INFORMATION & tz = data->tzi( zone.wYear );
608  SYSTEMTIME utc;
609  if ( !TzSpecificLocalTimeToSystemTime_Portable( const_cast<LPTIME_ZONE_INFORMATION>( &tz ), const_cast<LPSYSTEMTIME>( &zone ), &utc ) )
610  return 0;
611  const bool isDst = is_dst( tz, systemtime_to_qdatetime( utc ), utc.wYear );
612  int result = effective_offset( tz, isDst );
613 //FIXME: SystemTimeToTzSpecificLocalTime does not exsit on wince
614 #ifndef _WIN32_WCE
615  if ( secondOffset ) {
616  const SYSTEMTIME utcplus1 = qdatetime_to_systemtime( systemtime_to_qdatetime( utc ).addSecs( OneHour ) );
617  const SYSTEMTIME utcminus1 = qdatetime_to_systemtime( systemtime_to_qdatetime( utc ).addSecs( -OneHour ) );
618  SYSTEMTIME zoneplus1, zoneminus1;
619  if ( !SystemTimeToTzSpecificLocalTime( const_cast<LPTIME_ZONE_INFORMATION>( &tz ), const_cast<LPSYSTEMTIME>( &utcplus1 ), &zoneplus1 ) ||
620  !SystemTimeToTzSpecificLocalTime( const_cast<LPTIME_ZONE_INFORMATION>( &tz ), const_cast<LPSYSTEMTIME>( &utcminus1 ), &zoneminus1 ) )
621  return result;
622  if ( difference( zoneminus1, zone ) != OneHour ||
623  difference( zone, zoneplus1 ) != OneHour )
624  {
625  *secondOffset = effective_offset( tz, !isDst );
626  if ( result < *secondOffset )
627  qSwap( result, *secondOffset );
628  }
629  }
630 #endif
631  return result;
632 }
633 
634 
635 
636 KSystemTimeZoneBackendWindows * KSystemTimeZoneBackendWindows::clone() const
637 {
638  return new KSystemTimeZoneBackendWindows(*this);
639 }
640 
641 QByteArray KSystemTimeZoneBackendWindows::type() const
642 {
643  return "KSystemTimeZoneWindows";
644 }
645 
646 int KSystemTimeZoneBackendWindows::offsetAtZoneTime(const KTimeZone *caller, const QDateTime &zoneDateTime, int *secondOffset) const
647 {
648  if (!caller->isValid() || !zoneDateTime.isValid() || zoneDateTime.timeSpec() != Qt::LocalTime)
649  return 0;
650  if ( !check_local( caller, zoneDateTime ) )
651  return 0;
652 
653  return offset_at_zone_time( caller, qdatetime_to_systemtime( zoneDateTime ), secondOffset );
654 }
655 
656 int KSystemTimeZoneBackendWindows::offsetAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const
657 {
658  if (!caller->isValid() || !utcDateTime.isValid())
659  return 0;
660  if ( !check_utc( caller, utcDateTime ) )
661  return 0;
662  return offset_at_utc( caller, utcDateTime );
663 }
664 
665 int KSystemTimeZoneBackendWindows::offset(const KTimeZone *caller, time_t t) const
666 {
667  if (!caller->isValid() || t == KTimeZone::InvalidTime_t)
668  return 0;
669  return offsetAtUtc( caller, KTimeZone::fromTime_t( t ) );
670 }
671 
672 bool KSystemTimeZoneBackendWindows::isDstAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const
673 {
674  return check_utc( caller, utcDateTime ) && is_dst( caller, utcDateTime );
675 }
676 
677 
678 bool KSystemTimeZoneBackendWindows::isDst(const KTimeZone *caller, time_t t) const
679 {
680  return isDstAtUtc( caller, KTimeZone::fromTime_t( t ) );
681 }
682 
683 KSystemTimeZoneWindows::KSystemTimeZoneWindows(KTimeZoneSource *source, const QString &name)
684 : KTimeZone(new KSystemTimeZoneBackendWindows(source, name))
685 {}
686 
687 QStringList KSystemTimeZoneWindows::listTimeZones()
688 {
689  return list_standard_names();
690 }
691 
list_key
static QStringList list_key(HKEY key)
Definition: ktimezone_win.cpp:378
QTime::minute
int minute() const
lpUniversalTime
LPSYSTEMTIME LPSYSTEMTIME lpUniversalTime
Definition: ktimezone_win.cpp:148
ZoneTbl
static const ZoneKey ZoneTbl[]
Definition: ktimezone_win.cpp:41
effective_offset
static int effective_offset(const TIME_ZONE_INFORMATION &tz, bool isDst)
Definition: ktimezone_win.cpp:578
KSystemTimeZoneWindows::KSystemTimeZoneWindows
KSystemTimeZoneWindows(KTimeZoneSource *source, const QString &name)
Creates a time zone.
Definition: ktimezone_win.cpp:683
KTimeZone::fromTime_t
static QDateTime fromTime_t(time_t t)
Converts a UTC time, measured in seconds since 00:00:00 UTC 1st January 1970 (as returned by time(2))...
Definition: ktimezone.cpp:917
check_local
static bool check_local(const KTimeZone *caller, const QDateTime &dt)
Definition: ktimezone_win.cpp:320
kdebug.h
KTimeZoneBackend::type
virtual QByteArray type() const
Returns the class name of the data represented by this instance.
Definition: ktimezone.cpp:457
QList::push_back
void push_back(const T &value)
QByteArray
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
KTimeZone::isValid
bool isValid() const
Checks whether the instance is valid.
Definition: ktimezone.cpp:644
KTimeZoneBackend::offsetAtZoneTime
virtual int offsetAtZoneTime(const KTimeZone *caller, const QDateTime &zoneDateTime, int *secondOffset) const
Implements KTimeZone::offsetAtZoneTime().
Definition: ktimezone.cpp:467
lpLocalTime
LPSYSTEMTIME lpLocalTime
Definition: ktimezone_win.cpp:148
KSystemTimeZoneWindows::listTimeZones
static QStringList listTimeZones()
Static helper method that lists all availalbe timezones on the system as per the information in the W...
Definition: ktimezone_win.cpp:687
tchar_to_qstring
static QString tchar_to_qstring(const TCHAR *str)
Definition: ktimezone_win.cpp:188
COPY
#define COPY(name)
pTzSpecificLocalTimeToSystemTime
static PtrTzSpecificLocalTimeToSystemTime pTzSpecificLocalTimeToSystemTime
Definition: ktimezone_win.cpp:151
QDateTime::time
QTime time() const
getWinZoneName
static QString getWinZoneName(const QString &name)
Definition: ktimezone_win.cpp:136
systemtime_to_qdatetime
static QDateTime systemtime_to_qdatetime(const SYSTEMTIME &st)
Definition: ktimezone_win.cpp:203
list_standard_names
static QStringList list_standard_names()
Definition: ktimezone_win.cpp:394
QDate::month
int month() const
has_transition
static bool has_transition(const TIME_ZONE_INFORMATION &tz)
Definition: ktimezone_win.cpp:328
QTime
QTime::second
int second() const
QDate::dayOfWeek
int dayOfWeek() const
check_utc
static bool check_utc(const KTimeZone *caller, const QDateTime &dt)
Definition: ktimezone_win.cpp:324
get_string_value
static bool get_string_value(HKEY key, const TCHAR *value, TCHAR *dest, DWORD destSizeInBytes)
Definition: ktimezone_win.cpp:297
QString::fromLocal8Bit
QString fromLocal8Bit(const char *str, int size)
KTimeZone::data
const KTimeZoneData * data(bool create=false) const
Returns the detailed parsed data for the time zone.
Definition: ktimezone.cpp:754
QString::fromUtf16
QString fromUtf16(const ushort *unicode, int size)
difference
static int difference(const SYSTEMTIME &st1, const SYSTEMTIME &st2)
Definition: ktimezone_win.cpp:598
qt_dayofweek_to_win_dayofweek
static int qt_dayofweek_to_win_dayofweek(int qdow)
Definition: ktimezone_win.cpp:337
check_prereq
static bool check_prereq(const KTimeZone *caller, const QDateTime &dt, Qt::TimeSpec spec)
Definition: ktimezone_win.cpp:316
KTimeZoneBackend::clone
virtual KTimeZoneBackend * clone() const
Creates a copy of this instance.
Definition: ktimezone.cpp:462
get_binary_value
static bool get_binary_value(HKEY key, const TCHAR *value, void *data, DWORD numData, DWORD *outNumData=0)
Definition: ktimezone_win.cpp:284
QDate::day
int day() const
QByteArray::constData
const char * constData() const
qstring_to_tcharstring
static std::basic_string< TCHAR > qstring_to_tcharstring(const QString &str)
Definition: ktimezone_win.cpp:196
KTimeZone::InvalidTime_t
static const time_t InvalidTime_t
Indicates an invalid time_t value.
Definition: ktimezone.h:1077
pathFromZoneName
static std::basic_string< TCHAR > pathFromZoneName(const KTimeZone &zone)
Definition: ktimezone_win.cpp:431
KTimeZoneBackend::isDst
virtual bool isDst(const KTimeZone *caller, time_t t) const
Implements KTimeZone::isDst().
Definition: ktimezone.cpp:577
offset_at_utc
static int offset_at_utc(const KTimeZone *caller, const QDateTime &utc)
Definition: ktimezone_win.cpp:588
QDate
OneHour
static const int OneHour
Definition: ktimezone_win.cpp:596
QDate::year
int year() const
QString
qstring_to_tchar
static const TCHAR * qstring_to_tchar(const QString &str)
Definition: ktimezone_win.cpp:192
QStringList
QTime::hour
int hour() const
QString::toLocal8Bit
QByteArray toLocal8Bit() const
QTime::msec
int msec() const
QDateTime::timeSpec
Qt::TimeSpec timeSpec() const
kWarning
#define kWarning
Definition: kdebug.h:322
win_dayofweek_to_qt_dayofweek
static int win_dayofweek_to_qt_dayofweek(int wdow)
Definition: ktimezone_win.cpp:332
KTimeZone
Base class representing a time zone.
Definition: ktimezone.h:416
KSystemTimeZoneSourceWindows::KSystemTimeZoneSourceWindows
KSystemTimeZoneSourceWindows()
Constructs a time zone source.
Definition: ktimezone_win.cpp:512
QDateTime::isValid
bool isValid() const
BOOL
typedef BOOL(WINAPI *PtrTzSpecificLocalTimeToSystemTime)(LPTIME_ZONE_INFORMATION lpTimeZoneInformation
offset_at_zone_time
static int offset_at_zone_time(const KTimeZone *caller, const SYSTEMTIME &zone, int *secondOffset)
Definition: ktimezone_win.cpp:602
QString::utf16
const ushort * utf16() const
QDateTime::date
QDate date() const
QLibrary::resolve
void * resolve(const char *symbol)
QLatin1String
QDateTime::secsTo
int secsTo(const QDateTime &other) const
timeZonesKey
static const TCHAR timeZonesKey[]
Definition: ktimezone_win.cpp:202
QLibrary
find_nth_weekday_in_month_of_year
static QDate find_nth_weekday_in_month_of_year(int nth, int dayOfWeek, int month, int year)
Definition: ktimezone_win.cpp:342
transition
static QDateTime transition(const SYSTEMTIME &st, int year)
Definition: ktimezone_win.cpp:357
qdatetime_to_systemtime
static SYSTEMTIME qdatetime_to_systemtime(const QDateTime &dt)
Definition: ktimezone_win.cpp:208
KTimeZoneBackend::offsetAtUtc
virtual int offsetAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const
Implements KTimeZone::offsetAtUtc().
Definition: ktimezone.cpp:530
TzSpecificLocalTimeToSystemTime_Portable
static bool TzSpecificLocalTimeToSystemTime_Portable(TIME_ZONE_INFORMATION *tz, SYSTEMTIME *i_stLocal, SYSTEMTIME *o_stUniversal)
Definition: ktimezone_win.cpp:224
KSystemTimeZoneSourceWindows::parse
KTimeZoneData * parse(const KTimeZone &zone) const
Retrieves and parses the Windows registry information to extract detailed information for one time zo...
Definition: ktimezone_win.cpp:517
KTimeZone::name
QString name() const
Returns the name of the time zone.
Definition: ktimezone.cpp:669
QDate::addDays
QDate addDays(int ndays) const
ktimezone_win.h
KTimeZoneBackend::offset
virtual int offset(const KTimeZone *caller, time_t t) const
Implements KTimeZone::offset().
Definition: ktimezone.cpp:562
KTimeZoneSource
Base class representing a source of time zone information.
Definition: ktimezone.h:1230
MAX_KEY_LENGTH
static const int MAX_KEY_LENGTH
Definition: ktimezone_win.cpp:376
KTimeZoneBackend::isDstAtUtc
virtual bool isDstAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const
Implements KTimeZone::isDstAtUtc().
Definition: ktimezone.cpp:567
is_dst
static bool is_dst(const TIME_ZONE_INFORMATION &tzi, const QDateTime &utc, int year)
Definition: ktimezone_win.cpp:560
QDateTime
KTimeZoneBackend
Base backend class for KTimeZone classes.
Definition: ktimezone.h:1120
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:22:11 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