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

KDECore

  • 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
36struct ZoneKey {
37 QString zoneOlson;
38 QString zoneWin;
39};
40
41static 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
136static 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
147typedef BOOL (WINAPI *PtrTzSpecificLocalTimeToSystemTime )(LPTIME_ZONE_INFORMATION lpTimeZoneInformation,
148 LPSYSTEMTIME lpLocalTime,
149 LPSYSTEMTIME lpUniversalTime
150);
151static PtrTzSpecificLocalTimeToSystemTime pTzSpecificLocalTimeToSystemTime = 0;
152
153namespace {
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
174static inline QString tchar_to_qstring( const TCHAR * str ) {
175 return QString::fromUtf16( reinterpret_cast<const ushort*>( str ) );
176}
177
178static inline const TCHAR * qstring_to_tchar( const QString& str ) {
179 return reinterpret_cast<const TCHAR*>( str.utf16() );
180}
181
182static 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
188static inline QString tchar_to_qstring( const TCHAR * str ) {
189 return QString::fromLocal8Bit( str );
190}
191
192static inline const TCHAR * qstring_to_tchar( const QString& str ) {
193 return str.toLocal8Bit().constData();
194}
195
196static 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
202static const TCHAR timeZonesKey[] = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones");
203static 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
208static 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
224static 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
284static 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
297static 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
316static bool check_prereq( const KTimeZone * caller, const QDateTime & dt, Qt::TimeSpec spec ) {
317 return caller && caller->isValid() && dt.isValid() && dt.timeSpec() == spec ;
318}
319
320static inline bool check_local( const KTimeZone * caller, const QDateTime & dt ) {
321 return check_prereq( caller, dt, Qt::LocalTime );
322}
323
324static inline bool check_utc( const KTimeZone * caller, const QDateTime & dt ) {
325 return check_prereq( caller, dt, Qt::UTC );
326}
327
328static bool has_transition( const TIME_ZONE_INFORMATION & tz ) {
329 return tz.StandardDate.wMonth != 0 && tz.DaylightDate.wMonth != 0 ;
330}
331
332static int win_dayofweek_to_qt_dayofweek( int wdow ) {
333 // Sun(0)..Sat(6) -> Mon(1)...Sun(7)
334 return wdow ? wdow : 7 ;
335}
336
337static int qt_dayofweek_to_win_dayofweek( int qdow ) {
338 // Mon(1)...Sun(7) -> Sub(0)...Sat(6)
339 return qdow % 7;
340}
341
342static 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
357static 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
364struct Transitions {
365 QDateTime stdStart, dstStart;
366};
367
368Transitions 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
376static const int MAX_KEY_LENGTH = 255;
377
378static 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
394static 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
431static 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
471class KSystemTimeZoneSourceWindowsPrivate
472{
473public:
474 KSystemTimeZoneSourceWindowsPrivate() {}
475 ~KSystemTimeZoneSourceWindowsPrivate() {}
476};
477
478
479class KSystemTimeZoneBackendWindows : public KTimeZoneBackend
480{
481public:
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
498class KSystemTimeZoneDataWindows : public KTimeZoneData
499{
500public:
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
512KSystemTimeZoneSourceWindows::KSystemTimeZoneSourceWindows()
513:d( new KSystemTimeZoneSourceWindowsPrivate )
514{
515}
516
517KTimeZoneData* 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
556Transitions transitions( const KTimeZone * caller, int year ) {
557 return transitions( static_cast<const KSystemTimeZoneDataWindows*>( caller->data(true) )->tzi( year ), year );
558}
559
560static 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
570static 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
578static 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
588static 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
596static const int OneHour = 3600; //sec
597
598static int difference( const SYSTEMTIME & st1, const SYSTEMTIME & st2 ) {
599 return systemtime_to_qdatetime( st1 ).secsTo( systemtime_to_qdatetime( st2 ) );
600}
601
602static 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
636KSystemTimeZoneBackendWindows * KSystemTimeZoneBackendWindows::clone() const
637{
638 return new KSystemTimeZoneBackendWindows(*this);
639}
640
641QByteArray KSystemTimeZoneBackendWindows::type() const
642{
643 return "KSystemTimeZoneWindows";
644}
645
646int 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
656int 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
665int 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
672bool KSystemTimeZoneBackendWindows::isDstAtUtc(const KTimeZone *caller, const QDateTime &utcDateTime) const
673{
674 return check_utc( caller, utcDateTime ) && is_dst( caller, utcDateTime );
675}
676
677
678bool KSystemTimeZoneBackendWindows::isDst(const KTimeZone *caller, time_t t) const
679{
680 return isDstAtUtc( caller, KTimeZone::fromTime_t( t ) );
681}
682
683KSystemTimeZoneWindows::KSystemTimeZoneWindows(KTimeZoneSource *source, const QString &name)
684: KTimeZone(new KSystemTimeZoneBackendWindows(source, name))
685{}
686
687QStringList KSystemTimeZoneWindows::listTimeZones()
688{
689 return list_standard_names();
690}
691
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
KSystemTimeZoneSourceWindows::KSystemTimeZoneSourceWindows
KSystemTimeZoneSourceWindows()
Constructs a time zone source.
Definition: ktimezone_win.cpp:512
KSystemTimeZoneWindows::KSystemTimeZoneWindows
KSystemTimeZoneWindows(KTimeZoneSource *source, const QString &name)
Creates a time zone.
Definition: ktimezone_win.cpp:683
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
KTimeZoneBackend
Base backend class for KTimeZone classes.
Definition: ktimezone.h:1121
KTimeZoneBackend::clone
virtual KTimeZoneBackend * clone() const
Creates a copy of this instance.
Definition: ktimezone.cpp:462
KTimeZoneData
Base class for the parsed data returned by a KTimeZoneSource class.
Definition: ktimezone.h:1303
KTimeZoneSource
Base class representing a source of time zone information.
Definition: ktimezone.h:1231
KTimeZone
Base class representing a time zone.
Definition: ktimezone.h:417
KTimeZone::InvalidTime_t
static const time_t InvalidTime_t
Indicates an invalid time_t value.
Definition: ktimezone.h:1077
KTimeZone::data
const KTimeZoneData * data(bool create=false) const
Returns the detailed parsed data for the time zone.
Definition: ktimezone.cpp:754
KTimeZone::name
QString name() const
Returns the name of the time zone.
Definition: ktimezone.cpp:669
KTimeZone::isValid
bool isValid() const
Checks whether the instance is valid.
Definition: ktimezone.cpp:644
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
QDateTime
QLibrary
QStringList
QString
kWarning
#define kWarning
Definition: kdebug.h:322
kdebug.h
OneHour
static const int OneHour
Definition: ktimezone_win.cpp:596
qdatetime_to_systemtime
static SYSTEMTIME qdatetime_to_systemtime(const QDateTime &dt)
Definition: ktimezone_win.cpp:208
effective_offset
static int effective_offset(const TIME_ZONE_INFORMATION &tz, bool isDst)
Definition: ktimezone_win.cpp:578
MAX_KEY_LENGTH
static const int MAX_KEY_LENGTH
Definition: ktimezone_win.cpp:376
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
qt_dayofweek_to_win_dayofweek
static int qt_dayofweek_to_win_dayofweek(int qdow)
Definition: ktimezone_win.cpp:337
timeZonesKey
static const TCHAR timeZonesKey[]
Definition: ktimezone_win.cpp:202
lpUniversalTime
LPSYSTEMTIME LPSYSTEMTIME lpUniversalTime
Definition: ktimezone_win.cpp:150
COPY
#define COPY(name)
check_prereq
static bool check_prereq(const KTimeZone *caller, const QDateTime &dt, Qt::TimeSpec spec)
Definition: ktimezone_win.cpp:316
list_key
static QStringList list_key(HKEY key)
Definition: ktimezone_win.cpp:378
pathFromZoneName
static std::basic_string< TCHAR > pathFromZoneName(const KTimeZone &zone)
Definition: ktimezone_win.cpp:431
check_utc
static bool check_utc(const KTimeZone *caller, const QDateTime &dt)
Definition: ktimezone_win.cpp:324
list_standard_names
static QStringList list_standard_names()
Definition: ktimezone_win.cpp:394
check_local
static bool check_local(const KTimeZone *caller, const QDateTime &dt)
Definition: ktimezone_win.cpp:320
ZoneTbl
static const ZoneKey ZoneTbl[]
Definition: ktimezone_win.cpp:41
getWinZoneName
static QString getWinZoneName(const QString &name)
Definition: ktimezone_win.cpp:136
is_dst
static bool is_dst(const TIME_ZONE_INFORMATION &tzi, const QDateTime &utc, int year)
Definition: ktimezone_win.cpp:560
win_dayofweek_to_qt_dayofweek
static int win_dayofweek_to_qt_dayofweek(int wdow)
Definition: ktimezone_win.cpp:332
offset_at_zone_time
static int offset_at_zone_time(const KTimeZone *caller, const SYSTEMTIME &zone, int *secondOffset)
Definition: ktimezone_win.cpp:602
difference
static int difference(const SYSTEMTIME &st1, const SYSTEMTIME &st2)
Definition: ktimezone_win.cpp:598
TzSpecificLocalTimeToSystemTime_Portable
static bool TzSpecificLocalTimeToSystemTime_Portable(TIME_ZONE_INFORMATION *tz, SYSTEMTIME *i_stLocal, SYSTEMTIME *o_stUniversal)
Definition: ktimezone_win.cpp:224
get_string_value
static bool get_string_value(HKEY key, const TCHAR *value, TCHAR *dest, DWORD destSizeInBytes)
Definition: ktimezone_win.cpp:297
transition
static QDateTime transition(const SYSTEMTIME &st, int year)
Definition: ktimezone_win.cpp:357
qstring_to_tcharstring
static std::basic_string< TCHAR > qstring_to_tcharstring(const QString &str)
Definition: ktimezone_win.cpp:196
qstring_to_tchar
static const TCHAR * qstring_to_tchar(const QString &str)
Definition: ktimezone_win.cpp:192
BOOL
typedef BOOL(WINAPI *PtrTzSpecificLocalTimeToSystemTime)(LPTIME_ZONE_INFORMATION lpTimeZoneInformation
offset_at_utc
static int offset_at_utc(const KTimeZone *caller, const QDateTime &utc)
Definition: ktimezone_win.cpp:588
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
tchar_to_qstring
static QString tchar_to_qstring(const TCHAR *str)
Definition: ktimezone_win.cpp:188
lpLocalTime
LPSYSTEMTIME lpLocalTime
Definition: ktimezone_win.cpp:148
transitions
Transitions transitions(const TIME_ZONE_INFORMATION &tz, int year)
Definition: ktimezone_win.cpp:368
has_transition
static bool has_transition(const TIME_ZONE_INFORMATION &tz)
Definition: ktimezone_win.cpp:328
systemtime_to_qdatetime
static QDateTime systemtime_to_qdatetime(const SYSTEMTIME &st)
Definition: ktimezone_win.cpp:203
pTzSpecificLocalTimeToSystemTime
static PtrTzSpecificLocalTimeToSystemTime pTzSpecificLocalTimeToSystemTime
Definition: ktimezone_win.cpp:151
ktimezone_win.h
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