2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 Copyright 1998-2002, Apple, Inc. All rights reserved.
27 Responsibility: Christopher Kane
30 #include <CoreFoundation/CFTimeZone.h>
31 #include <CoreFoundation/CFPropertyList.h>
32 #include "CFUtilities.h"
33 #include "CFInternal.h"
37 #if !defined(__WIN32__)
49 #if defined(__WIN32__)
53 // For Windows(TM) time zone information, see registry key:
54 // HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Time Zones
56 #if defined(__WIN32__)
57 #define TZZONEINFO "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones"
59 #define TZZONELINK "/etc/localtime"
60 #define TZZONEINFO "/usr/share/zoneinfo/"
63 static CFTimeZoneRef __CFTimeZoneSystem
= NULL
;
64 static CFTimeZoneRef __CFTimeZoneDefault
= NULL
;
65 static CFDictionaryRef __CFTimeZoneAbbreviationDict
= NULL
;
66 static CFSpinLock_t __CFTimeZoneAbbreviationLock
= 0;
67 static CFDictionaryRef __CFTimeZoneCompatibilityMappingDict
= NULL
;
68 static CFDictionaryRef __CFTimeZoneCompatibilityMappingDict2
= NULL
;
69 static CFSpinLock_t __CFTimeZoneCompatibilityMappingLock
= 0;
70 static CFArrayRef __CFKnownTimeZoneList
= NULL
;
71 static CFMutableDictionaryRef __CFTimeZoneCache
= NULL
;
72 static CFSpinLock_t __CFTimeZoneGlobalLock
= 0;
74 CF_INLINE
void __CFTimeZoneLockGlobal(void) {
75 __CFSpinLock(&__CFTimeZoneGlobalLock
);
78 CF_INLINE
void __CFTimeZoneUnlockGlobal(void) {
79 __CFSpinUnlock(&__CFTimeZoneGlobalLock
);
82 CF_INLINE
void __CFTimeZoneLockAbbreviations(void) {
83 __CFSpinLock(&__CFTimeZoneAbbreviationLock
);
86 CF_INLINE
void __CFTimeZoneUnlockAbbreviations(void) {
87 __CFSpinUnlock(&__CFTimeZoneAbbreviationLock
);
90 CF_INLINE
void __CFTimeZoneLockCompatibilityMapping(void) {
91 __CFSpinLock(&__CFTimeZoneCompatibilityMappingLock
);
94 CF_INLINE
void __CFTimeZoneUnlockCompatibilityMapping(void) {
95 __CFSpinUnlock(&__CFTimeZoneCompatibilityMappingLock
);
98 /* This function should be used for WIN32 instead of
99 * __CFCopyRecursiveDirectoryList function.
100 * It takes TimeZone names from the registry
101 * (Aleksey Dukhnyakov)
103 #if defined(__WIN32__)
104 static CFMutableArrayRef
__CFCopyWindowsTimeZoneList() {
105 CFMutableArrayRef result
= NULL
;
107 TCHAR lpName
[MAX_PATH
+1];
108 DWORD dwIndex
, retCode
;
110 if (RegOpenKey(HKEY_LOCAL_MACHINE
,_T(TZZONEINFO
),&hkResult
) !=
114 result
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
116 for (dwIndex
=0; (retCode
= RegEnumKey(hkResult
,dwIndex
,lpName
,MAX_PATH
)) != ERROR_NO_MORE_ITEMS
; dwIndex
++) {
118 if (retCode
!= ERROR_SUCCESS
) {
119 RegCloseKey(hkResult
);
125 CFStringRef string
= CFStringCreateWithBytes(kCFAllocatorDefault
, lpName
, _tcslen(lpName
), kCFStringEncodingUnicode
, false);
127 CFStringRef string
= CFStringCreateWithBytes(kCFAllocatorDefault
, lpName
, _tcslen(lpName
), CFStringGetSystemEncoding(), false);
129 CFArrayAppendValue(result
, string
);
134 RegCloseKey(hkResult
);
139 static CFMutableArrayRef
__CFCopyRecursiveDirectoryList(const char *topDir
) {
140 CFMutableArrayRef result
= NULL
, temp
;
141 long fd
, numread
, plen
, basep
= 0;
142 CFIndex idx
, cnt
, usedLen
;
143 char *dirge
, path
[CFMaxPathSize
];
145 #if !defined(__WIN32__)
146 // No d_namlen in dirent struct on Linux
147 #if defined(__LINUX__)
148 #define dentDNameLen strlen(dent->d_name)
150 #define dentDNameLen dent->d_namlen
152 fd
= open(topDir
, O_RDONLY
, 0);
156 dirge
= malloc(8192);
157 result
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
158 numread
= getdirentries(fd
, dirge
, 8192, &basep
);
159 while (0 < numread
) {
160 struct dirent
*dent
= (struct dirent
*)dirge
;
161 for (; dent
< (struct dirent
*)(dirge
+ numread
); dent
= (struct dirent
*)((char *)dent
+ dent
->d_reclen
)) {
162 if (0 == dent
->d_fileno
) continue;
163 if (1 == dentDNameLen
&& '.' == dent
->d_name
[0]) continue;
164 if (2 == dentDNameLen
&& '.' == dent
->d_name
[0] && '.' == dent
->d_name
[1]) continue;
165 if (dent
->d_type
== DT_UNKNOWN
) {
167 strcpy(path
, topDir
);
170 memmove(path
+ plen
, dent
->d_name
, dentDNameLen
);
171 path
[plen
+ dentDNameLen
] = '\0';
172 if (0 <= stat(path
, &statbuf
) && (statbuf
.st_mode
& S_IFMT
) == S_IFDIR
) {
173 dent
->d_type
= DT_DIR
;
176 if (DT_DIR
== dent
->d_type
) {
177 strcpy(path
, topDir
);
180 memmove(path
+ plen
, dent
->d_name
, dentDNameLen
);
181 path
[plen
+ dentDNameLen
] = '\0';
182 temp
= __CFCopyRecursiveDirectoryList(path
);
183 for (idx
= 0, cnt
= CFArrayGetCount(temp
); idx
< cnt
; idx
++) {
184 CFStringRef string
, item
= CFArrayGetValueAtIndex(temp
, idx
);
185 memmove(path
, dent
->d_name
, dentDNameLen
);
186 path
[dentDNameLen
] = '/';
187 CFStringGetBytes(item
, CFRangeMake(0, CFStringGetLength(item
)), kCFStringEncodingUTF8
, 0, false, path
+ dentDNameLen
+ 1, CFMaxPathLength
- dentDNameLen
- 2, &usedLen
);
188 string
= CFStringCreateWithBytes(kCFAllocatorDefault
, path
, dentDNameLen
+ 1 + usedLen
, kCFStringEncodingUTF8
, false);
189 CFArrayAppendValue(result
, string
);
194 CFStringRef string
= CFStringCreateWithBytes(kCFAllocatorDefault
, dent
->d_name
, dentDNameLen
, kCFStringEncodingUTF8
, false);
195 CFArrayAppendValue(result
, string
);
199 numread
= getdirentries(fd
, dirge
, 8192, &basep
);
211 typedef struct _CFTZPeriod
{
217 struct __CFTimeZone
{
219 CFStringRef _name
; /* immutable */
220 CFDataRef _data
; /* immutable */
221 CFTZPeriod
*_periods
; /* immutable */
222 int32_t _periodCnt
; /* immutable */
225 /* startSec is the whole integer seconds from a CFAbsoluteTime, giving dates
226 * between 1933 and 2069; info outside these years is discarded on read-in */
227 /* Bits 31-18 of the info are unused */
228 /* Bit 17 of the info is used for the is-DST state */
229 /* Bit 16 of the info is used for the sign of the offset (1 == negative) */
230 /* Bits 15-0 of the info are used for abs(offset) in seconds from GMT */
232 CF_INLINE
void __CFTZPeriodInit(CFTZPeriod
*period
, int32_t startTime
, CFStringRef abbrev
, int32_t offset
, Boolean isDST
) {
233 period
->startSec
= startTime
;
234 period
->abbrev
= abbrev
? CFRetain(abbrev
) : NULL
;
235 __CFBitfieldSetValue(period
->info
, 15, 0, abs(offset
));
236 __CFBitfieldSetValue(period
->info
, 16, 16, (offset
< 0 ? 1 : 0));
237 __CFBitfieldSetValue(period
->info
, 17, 17, (isDST
? 1 : 0));
240 CF_INLINE
int32_t __CFTZPeriodStartSeconds(const CFTZPeriod
*period
) {
241 return period
->startSec
;
244 CF_INLINE CFStringRef
__CFTZPeriodAbbreviation(const CFTZPeriod
*period
) {
245 return period
->abbrev
;
248 CF_INLINE
int32_t __CFTZPeriodGMTOffset(const CFTZPeriod
*period
) {
249 int32_t v
= __CFBitfieldGetValue(period
->info
, 15, 0);
250 if (__CFBitfieldGetValue(period
->info
, 16, 16)) v
= -v
;
254 CF_INLINE Boolean
__CFTZPeriodIsDST(const CFTZPeriod
*period
) {
255 return (Boolean
)__CFBitfieldGetValue(period
->info
, 17, 17);
258 static CFComparisonResult
__CFCompareTZPeriods(const void *val1
, const void *val2
, void *context
) {
259 CFTZPeriod
*tzp1
= (CFTZPeriod
*)val1
;
260 CFTZPeriod
*tzp2
= (CFTZPeriod
*)val2
;
261 // we treat equal as less than, as the code which uses the
262 // result of the bsearch doesn't expect exact matches
263 // (they're pretty rare, so no point in over-coding for them)
264 if (__CFTZPeriodStartSeconds(tzp1
) <= __CFTZPeriodStartSeconds(tzp2
)) return kCFCompareLessThan
;
265 return kCFCompareGreaterThan
;
268 CF_INLINE CFIndex
__CFBSearchTZPeriods(CFTimeZoneRef tz
, CFAbsoluteTime at
) {
271 __CFTZPeriodInit(&elem
, (int32_t)(float)floor(at
), NULL
, 0, false);
272 idx
= CFBSearch(&elem
, sizeof(CFTZPeriod
), tz
->_periods
, tz
->_periodCnt
, __CFCompareTZPeriods
, NULL
);
273 if (tz
->_periodCnt
<= idx
) {
274 idx
= tz
->_periodCnt
;
275 } else if (0 == idx
) {
276 // We want anything before the time zone records start to be not in DST;
277 // we assume that if period[0] is DST, then period[1] is not; could do a search instead.
278 idx
= __CFTZPeriodIsDST(&(tz
->_periods
[0])) ? 2 : 1;
284 ** Each time zone data file begins with. . .
288 char tzh_reserved
[20]; /* reserved for future use */
289 char tzh_ttisgmtcnt
[4]; /* coded number of trans. time flags */
290 char tzh_ttisstdcnt
[4]; /* coded number of trans. time flags */
291 char tzh_leapcnt
[4]; /* coded number of leap seconds */
292 char tzh_timecnt
[4]; /* coded number of transition times */
293 char tzh_typecnt
[4]; /* coded number of local time types */
294 char tzh_charcnt
[4]; /* coded number of abbr. chars */
298 ** . . .followed by. . .
300 ** tzh_timecnt (char [4])s coded transition times a la time(2)
301 ** tzh_timecnt (UInt8)s types of local time starting at above
302 ** tzh_typecnt repetitions of
303 ** one (char [4]) coded GMT offset in seconds
304 ** one (UInt8) used to set tm_isdst
305 ** one (UInt8) that's an abbreviation list index
306 ** tzh_charcnt (char)s '\0'-terminated zone abbreviations
307 ** tzh_leapcnt repetitions of
308 ** one (char [4]) coded leap second transition times
309 ** one (char [4]) total correction after above
310 ** tzh_ttisstdcnt (char)s indexed by type; if 1, transition
311 ** time is standard time, if 0,
312 ** transition time is wall clock time
313 ** if absent, transition times are
314 ** assumed to be wall clock time
315 ** tzh_ttisgmtcnt (char)s indexed by type; if 1, transition
316 ** time is GMT, if 0,
317 ** transition time is local time
318 ** if absent, transition times are
319 ** assumed to be local time
322 CF_INLINE
int32_t __CFDetzcode(const unsigned char *bufp
) {
323 int32_t result
= (bufp
[0] & 0x80) ? ~0L : 0L;
324 result
= (result
<< 8) | (bufp
[0] & 0xff);
325 result
= (result
<< 8) | (bufp
[1] & 0xff);
326 result
= (result
<< 8) | (bufp
[2] & 0xff);
327 result
= (result
<< 8) | (bufp
[3] & 0xff);
331 CF_INLINE
void __CFEntzcode(int32_t value
, unsigned char *bufp
) {
332 bufp
[0] = (value
>> 24) & 0xff;
333 bufp
[1] = (value
>> 16) & 0xff;
334 bufp
[2] = (value
>> 8) & 0xff;
335 bufp
[3] = (value
>> 0) & 0xff;
338 static Boolean
__CFParseTimeZoneData(CFAllocatorRef allocator
, CFDataRef data
, CFTZPeriod
**tzpp
, CFIndex
*cntp
) {
339 #if !defined(__WIN32__)
340 int32_t len
, timecnt
, typecnt
, charcnt
, idx
, cnt
;
341 const char *p
, *timep
, *typep
, *ttisp
, *charp
;
343 Boolean result
= true;
345 p
= CFDataGetBytePtr(data
);
346 len
= CFDataGetLength(data
);
347 if (len
< (int32_t)sizeof(struct tzhead
)) {
350 p
+= 20 + 4 + 4 + 4; /* skip reserved, ttisgmtcnt, ttisstdcnt, leapcnt */
351 timecnt
= __CFDetzcode(p
);
353 typecnt
= __CFDetzcode(p
);
355 charcnt
= __CFDetzcode(p
);
357 if (typecnt
<= 0 || timecnt
< 0 || charcnt
< 0) {
360 if (len
- (int32_t)sizeof(struct tzhead
) < (4 + 1) * timecnt
+ (4 + 1 + 1) * typecnt
+ charcnt
) {
364 typep
= timep
+ 4 * timecnt
;
365 ttisp
= typep
+ timecnt
;
366 charp
= ttisp
+ (4 + 1 + 1) * typecnt
;
367 cnt
= (0 < timecnt
) ? timecnt
: 1;
368 *tzpp
= CFAllocatorAllocate(allocator
, cnt
* sizeof(CFTZPeriod
), 0);
369 if (__CFOASafe
) __CFSetLastAllocationEventName(*tzpp
, "CFTimeZone (store)");
370 memset(*tzpp
, 0, cnt
* sizeof(CFTZPeriod
));
371 abbrs
= CFAllocatorAllocate(allocator
, (charcnt
+ 1) * sizeof(CFStringRef
), 0);
372 if (__CFOASafe
) __CFSetLastAllocationEventName(*tzpp
, "CFTimeZone (temp)");
373 for (idx
= 0; idx
< charcnt
+ 1; idx
++) {
376 for (idx
= 0; idx
< cnt
; idx
++) {
378 int32_t itime
, offset
;
379 uint8_t type
, dst
, abbridx
;
381 at
= (CFAbsoluteTime
)(__CFDetzcode(timep
) + 0.0) - kCFAbsoluteTimeIntervalSince1970
;
382 if (0 == timecnt
) itime
= INT_MIN
;
383 else if (at
< (CFAbsoluteTime
)INT_MIN
) itime
= INT_MIN
;
384 else if ((CFAbsoluteTime
)INT_MAX
< at
) itime
= INT_MAX
;
385 else itime
= (int32_t)at
;
386 timep
+= 4; /* harmless if 0 == timecnt */
387 type
= (0 < timecnt
) ? (uint8_t)*typep
++ : 0;
388 if (typecnt
<= type
) {
392 offset
= __CFDetzcode(ttisp
+ 6 * type
);
393 dst
= (uint8_t)*(ttisp
+ 6 * type
+ 4);
394 if (0 != dst
&& 1 != dst
) {
398 abbridx
= (uint8_t)*(ttisp
+ 6 * type
+ 5);
399 if (charcnt
< abbridx
) {
403 if (NULL
== abbrs
[abbridx
]) {
404 abbrs
[abbridx
] = CFStringCreateWithCString(allocator
, &charp
[abbridx
], kCFStringEncodingASCII
);
406 __CFTZPeriodInit(*tzpp
+ idx
, itime
, abbrs
[abbridx
], offset
, (dst
? true : false));
408 for (idx
= 0; idx
< charcnt
+ 1; idx
++) {
409 if (NULL
!= abbrs
[idx
]) {
410 CFRelease(abbrs
[idx
]);
413 CFAllocatorDeallocate(allocator
, abbrs
);
415 // dump all but the last INT_MIN and the first INT_MAX
416 for (idx
= 0; idx
< cnt
; idx
++) {
417 if (((*tzpp
+ idx
)->startSec
== INT_MIN
) && (idx
+ 1 < cnt
) && (((*tzpp
+ idx
+ 1)->startSec
== INT_MIN
))) {
419 memmove((*tzpp
+ idx
), (*tzpp
+ idx
+ 1), sizeof(CFTZPeriod
) * (cnt
- idx
));
423 // Don't combine these loops! Watch the idx decrementing...
424 for (idx
= 0; idx
< cnt
; idx
++) {
425 if (((*tzpp
+ idx
)->startSec
== INT_MAX
) && (0 < idx
) && (((*tzpp
+ idx
- 1)->startSec
== INT_MAX
))) {
427 memmove((*tzpp
+ idx
), (*tzpp
+ idx
+ 1), sizeof(CFTZPeriod
) * (cnt
- idx
));
431 CFQSortArray(*tzpp
, cnt
, sizeof(CFTZPeriod
), __CFCompareTZPeriods
, NULL
);
434 CFAllocatorDeallocate(allocator
, *tzpp
);
439 /* We use Win32 function to find TimeZone
440 * (Aleksey Dukhnyakov)
442 *tzpp
= CFAllocatorAllocate(allocator
, sizeof(CFTZPeriod
), 0);
443 __CFTZPeriodInit(*tzpp
, 0, NULL
, 0, false);
449 static Boolean
__CFTimeZoneEqual(CFTypeRef cf1
, CFTypeRef cf2
) {
450 CFTimeZoneRef tz1
= (CFTimeZoneRef
)cf1
;
451 CFTimeZoneRef tz2
= (CFTimeZoneRef
)cf2
;
452 if (!CFEqual(CFTimeZoneGetName(tz1
), CFTimeZoneGetName(tz2
))) return false;
453 if (!CFEqual(CFTimeZoneGetData(tz1
), CFTimeZoneGetData(tz2
))) return false;
457 static CFHashCode
__CFTimeZoneHash(CFTypeRef cf
) {
458 CFTimeZoneRef tz
= (CFTimeZoneRef
)cf
;
459 return CFHash(CFTimeZoneGetName(tz
));
462 static CFStringRef
__CFTimeZoneCopyDescription(CFTypeRef cf
) {
463 CFTimeZoneRef tz
= (CFTimeZoneRef
)cf
;
464 CFStringRef result
, abbrev
;
466 at
= CFAbsoluteTimeGetCurrent();
467 abbrev
= CFTimeZoneCopyAbbreviation(tz
, at
);
468 result
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("<CFTimeZone %p [%p]>{name = %@; abbreviation = %@; GMT offset = %g; is DST = %s}"), cf
, CFGetAllocator(tz
), tz
->_name
, abbrev
, CFTimeZoneGetSecondsFromGMT(tz
, at
), CFTimeZoneIsDaylightSavingTime(tz
, at
) ? "true" : "false");
473 static void __CFTimeZoneDeallocate(CFTypeRef cf
) {
474 CFTimeZoneRef tz
= (CFTimeZoneRef
)cf
;
475 CFAllocatorRef allocator
= CFGetAllocator(tz
);
477 if (tz
->_name
) CFRelease(tz
->_name
);
478 if (tz
->_data
) CFRelease(tz
->_data
);
479 for (idx
= 0; idx
< tz
->_periodCnt
; idx
++) {
480 if (NULL
!= tz
->_periods
[idx
].abbrev
) CFRelease(tz
->_periods
[idx
].abbrev
);
482 if (NULL
!= tz
->_periods
) CFAllocatorDeallocate(allocator
, tz
->_periods
);
485 static CFTypeID __kCFTimeZoneTypeID
= _kCFRuntimeNotATypeID
;
487 static const CFRuntimeClass __CFTimeZoneClass
= {
492 __CFTimeZoneDeallocate
,
496 __CFTimeZoneCopyDescription
499 __private_extern__
void __CFTimeZoneInitialize(void) {
500 __kCFTimeZoneTypeID
= _CFRuntimeRegisterClass(&__CFTimeZoneClass
);
503 CFTypeID
CFTimeZoneGetTypeID(void) {
504 return __kCFTimeZoneTypeID
;
507 static CFTimeZoneRef
__CFTimeZoneCreateSystem(void) {
508 CFTimeZoneRef result
= NULL
;
509 #if defined(__WIN32__)
510 /* The GetTimeZoneInformation function retrieves the current
511 * time-zone parameters for Win32
512 * (Aleksey Dukhnyakov)
515 TIME_ZONE_INFORMATION tz
;
517 dw_result
=GetTimeZoneInformation(&tz
);
519 if ( dw_result
== TIME_ZONE_ID_STANDARD
||
520 dw_result
== TIME_ZONE_ID_DAYLIGHT
) {
521 CFStringRef name
= CFStringCreateWithCharacters(kCFAllocatorDefault
, tz
.StandardName
, wcslen(tz
.StandardName
));
522 data
= CFDataCreate(kCFAllocatorDefault
, (UInt8
*)&tz
, sizeof(tz
));
523 result
= CFTimeZoneCreate(kCFAllocatorSystemDefault
, name
, data
);
526 if (result
) return result
;
531 char linkbuf
[CFMaxPathSize
];
533 tzenv
= getenv("TZFILE");
535 CFStringRef name
= CFStringCreateWithBytes(kCFAllocatorDefault
, tzenv
, strlen(tzenv
), kCFStringEncodingUTF8
, false);
536 result
= CFTimeZoneCreateWithName(kCFAllocatorSystemDefault
, name
, false);
538 if (result
) return result
;
540 tzenv
= getenv("TZ");
542 CFStringRef name
= CFStringCreateWithBytes(kCFAllocatorDefault
, tzenv
, strlen(tzenv
), kCFStringEncodingUTF8
, false);
543 result
= CFTimeZoneCreateWithName(kCFAllocatorSystemDefault
, name
, true);
545 if (result
) return result
;
547 ret
= readlink(TZZONELINK
, linkbuf
, sizeof(linkbuf
));
551 if (strncmp(linkbuf
, TZZONEINFO
, sizeof(TZZONEINFO
) - 1) == 0) {
552 name
= CFStringCreateWithBytes(kCFAllocatorDefault
, linkbuf
+ sizeof(TZZONEINFO
) - 1, strlen(linkbuf
) - sizeof(TZZONEINFO
) + 1, kCFStringEncodingUTF8
, false);
554 name
= CFStringCreateWithBytes(kCFAllocatorDefault
, linkbuf
, strlen(linkbuf
), kCFStringEncodingUTF8
, false);
556 result
= CFTimeZoneCreateWithName(kCFAllocatorSystemDefault
, name
, false);
558 if (result
) return result
;
561 return CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorSystemDefault
, 0.0);
564 CFTimeZoneRef
CFTimeZoneCopySystem(void) {
566 __CFTimeZoneLockGlobal();
567 if (NULL
== __CFTimeZoneSystem
) {
568 __CFTimeZoneUnlockGlobal();
569 tz
= __CFTimeZoneCreateSystem();
570 __CFTimeZoneLockGlobal();
571 if (NULL
== __CFTimeZoneSystem
) {
572 __CFTimeZoneSystem
= tz
;
574 if (tz
) CFRelease(tz
);
577 tz
= __CFTimeZoneSystem
? CFRetain(__CFTimeZoneSystem
) : NULL
;
578 __CFTimeZoneUnlockGlobal();
582 void CFTimeZoneResetSystem(void) {
583 __CFTimeZoneLockGlobal();
584 if (__CFTimeZoneDefault
== __CFTimeZoneSystem
) {
585 if (__CFTimeZoneDefault
) CFRelease(__CFTimeZoneDefault
);
586 __CFTimeZoneDefault
= NULL
;
588 if (__CFTimeZoneSystem
) CFRelease(__CFTimeZoneSystem
);
589 __CFTimeZoneSystem
= NULL
;
590 __CFTimeZoneUnlockGlobal();
593 CFTimeZoneRef
CFTimeZoneCopyDefault(void) {
595 __CFTimeZoneLockGlobal();
596 if (NULL
== __CFTimeZoneDefault
) {
597 __CFTimeZoneUnlockGlobal();
598 tz
= CFTimeZoneCopySystem();
599 __CFTimeZoneLockGlobal();
600 if (NULL
== __CFTimeZoneDefault
) {
601 __CFTimeZoneDefault
= tz
;
603 if (tz
) CFRelease(tz
);
606 tz
= __CFTimeZoneDefault
? CFRetain(__CFTimeZoneDefault
) : NULL
;
607 __CFTimeZoneUnlockGlobal();
611 void CFTimeZoneSetDefault(CFTimeZoneRef tz
) {
612 __CFGenericValidateType(tz
, __kCFTimeZoneTypeID
);
613 __CFTimeZoneLockGlobal();
614 if (tz
!= __CFTimeZoneDefault
) {
615 if (tz
) CFRetain(tz
);
616 if (__CFTimeZoneDefault
) CFRelease(__CFTimeZoneDefault
);
617 __CFTimeZoneDefault
= tz
;
619 __CFTimeZoneUnlockGlobal();
622 static CFDictionaryRef
__CFTimeZoneCopyCompatibilityDictionary(void);
624 CFArrayRef
CFTimeZoneCopyKnownNames(void) {
626 __CFTimeZoneLockGlobal();
627 if (NULL
== __CFKnownTimeZoneList
) {
628 CFMutableArrayRef list
;
629 /* TimeZone information locate in the registry for Win32
630 * (Aleksey Dukhnyakov)
632 #if !defined(__WIN32__)
633 list
= __CFCopyRecursiveDirectoryList(TZZONEINFO
);
635 list
= __CFCopyWindowsTimeZoneList();
637 // Remove undesirable ancient cruft
638 CFDictionaryRef dict
= __CFTimeZoneCopyCompatibilityDictionary();
640 for (idx
= CFArrayGetCount(list
); idx
--; ) {
641 CFStringRef item
= CFArrayGetValueAtIndex(list
, idx
);
642 if (CFDictionaryContainsKey(dict
, item
)) {
643 CFArrayRemoveValueAtIndex(list
, idx
);
646 __CFKnownTimeZoneList
= CFArrayCreateCopy(kCFAllocatorSystemDefault
, list
);
649 tzs
= __CFKnownTimeZoneList
? CFRetain(__CFKnownTimeZoneList
) : NULL
;
650 __CFTimeZoneUnlockGlobal();
654 static const unsigned char *__CFTimeZoneAbbreviationDefaults
=
655 #if defined(__WIN32__)
657 * TimeZone abbreviations for Win32
658 * (Andrew Dzubandovsky)
661 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
662 " <!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">"
663 " <plist version=\"1.0\">"
665 " <key>AFG</key> <string>Afghanistan Standard Time</string>"
666 " <key>ALS</key> <string>Alaskan Standard Time</string>"
667 " <key>ARA</key> <string>Arab Standard Time</string>"
668 " <key>ARB</key> <string>Arabian Standard Time</string>"
669 " <key>ARC</key> <string>Arabic Standard Time</string>"
670 " <key>ATL</key> <string>Atlantic Standard Time</string>"
671 " <key>ASC</key> <string>AUS Central Standard Time</string>"
672 " <key>ASE</key> <string>AUS Eastern Standard Time</string>"
673 " <key>AZS</key> <string>Azores Standard Time</string>"
674 " <key>CND</key> <string>Canada Central Standard Time</string>"
675 " <key>CPV</key> <string>Cape Verde Standard Time</string>"
676 " <key>CCS</key> <string>Caucasus Standard Time</string>"
677 " <key>CNAS</key> <string>Cen. Australia Standard Time</string>"
678 " <key>CAMR</key> <string>Central America Standard Time</string>"
679 " <key>CAS</key> <string>Central Asia Standard Time</string>"
680 " <key>CER</key> <string>Central Europe Standard Time</string>"
681 " <key>CEPN</key> <string>Central European Standard Time</string>"
682 " <key>CPC</key> <string>Central Pacific Standard Time</string>"
683 " <key>CSTD</key> <string>Central Standard Time</string>"
684 " <key>CHN</key> <string>China Standard Time</string>"
685 " <key>DTLN</key> <string>Dateline Standard Time</string>"
686 " <key>EAFR</key> <string>E. Africa Standard Time</string>"
687 " <key>EAS</key> <string>E. Australia Standard Time</string>"
688 " <key>ERP</key> <string>E. Europe Standard Time</string>"
689 " <key>ESTH</key> <string>E. South America Standard Time</string>"
690 " <key>ESTM</key> <string>Eastern Standard Time</string>"
691 " <key>EGP</key> <string>Egypt Standard Time</string>"
692 " <key>EKT</key> <string>Ekaterinburg Standard Time</string>"
693 " <key>FST</key> <string>Fiji Standard Time</string>"
694 " <key>FLE</key> <string>FLE Standard Time</string>"
695 " <key>GMT</key> <string>GMT Standard Time</string>"
696 " <key>GRLD</key> <string>Greenland Standard Time</string>"
697 " <key>GRW</key> <string>Greenwich Standard Time</string>"
698 " <key>GTB</key> <string>GTB Standard Time</string>"
699 " <key>HWT</key> <string>Hawaiian Standard Time</string>"
700 " <key>INT</key> <string>India Standard Time</string>"
701 " <key>IRT</key> <string>Iran Standard Time</string>"
702 " <key>ISL</key> <string>Israel Standard Time</string>"
703 " <key>KRT</key> <string>Korea Standard Time</string>"
704 " <key>MXST</key> <string>Mexico Standard Time</string>"
705 " <key>MTL</key> <string>Mid-Atlantic Standard Time</string>"
706 " <key>MNT</key> <string>Mountain Standard Time</string>"
707 " <key>MNM</key> <string>Myanmar Standard Time</string>"
708 " <key>NCNA</key> <string>N. Central Asia Standard Time</string>"
709 " <key>MPL</key> <string>Nepal Standard Time</string>"
710 " <key>NWZ</key> <string>New Zealand Standard Time</string>"
711 " <key>NWF</key> <string>Newfoundland Standard Time</string>"
712 " <key>NTAE</key> <string>North Asia East Standard Time</string>"
713 " <key>NTAS</key> <string>North Asia Standard Time</string>"
714 " <key>HSAT</key> <string>Pacific SA Standard Time</string>"
715 " <key>PST</key> <string>Pacific Standard Time</string>"
716 " <key>RMC</key> <string>Romance Standard Time</string>"
717 " <key>MSK</key> <string>Russian Standard Time</string>"
718 " <key>SSS</key> <string>SA Eastern Standard Time</string>"
719 " <key>SPS</key> <string>SA Pacific Standard Time</string>"
720 " <key>SWS</key> <string>SA Western Standard Time</string>"
721 " <key>SMS</key> <string>Samoa Standard Time</string>"
722 " <key>SAS</key> <string>SE Asia Standard Time</string>"
723 " <key>SNG</key> <string>Singapore Standard Time</string>"
724 " <key>STAF</key> <string>South Africa Standard Time</string>"
725 " <key>SRLK</key> <string>Sri Lanka Standard Time</string>"
726 " <key>TPS</key> <string>Taipei Standard Time</string>"
727 " <key>TSM</key> <string>Tasmania Standard Time</string>"
728 " <key>JPN</key> <string>Tokyo Standard Time</string>"
729 " <key>TNG</key> <string>Tonga Standard Time</string>"
730 " <key>AEST</key> <string>US Eastern Standard Time</string>"
731 " <key>AMST</key> <string>US Mountain Standard Time</string>"
732 " <key>VLD</key> <string>Vladivostok Standard Time</string>"
733 " <key>AUSW</key> <string>W. Australia Standard Time</string>"
734 " <key>AFCW</key> <string>W. Central Africa Standard Time</string>"
735 " <key>EWS</key> <string>W. Europe Standard Time</string>"
736 " <key>ASW</key> <string>West Asia Standard Time</string>"
737 " <key>PWS</key> <string>West Pacific Standard Time</string>"
738 " <key>RKS</key> <string>Yakutsk Standard Time</string>"
742 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
743 " <!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">"
744 " <plist version=\"1.0\">"
746 " <key>ADT</key> <string>America/Halifax</string>"
747 " <key>AFT</key> <string>Asia/Kabul</string>"
748 " <key>AKDT</key> <string>America/Juneau</string>"
749 " <key>AKST</key> <string>America/Juneau</string>"
750 " <key>AST</key> <string>America/Halifax</string>"
751 " <key>CDT</key> <string>America/Chicago</string>"
752 " <key>CEST</key> <string>Europe/Rome</string>"
753 " <key>CET</key> <string>Europe/Rome</string>"
754 " <key>CST</key> <string>America/Chicago</string>"
755 " <key>EDT</key> <string>America/New_York</string>"
756 " <key>EEST</key> <string>Europe/Warsaw</string>"
757 " <key>EET</key> <string>Europe/Warsaw</string>"
758 " <key>EST</key> <string>America/New_York</string>"
759 " <key>GMT</key> <string>GMT</string>"
760 " <key>HKST</key> <string>Asia/Hong_Kong</string>"
761 " <key>HST</key> <string>Pacific/Honolulu</string>"
762 " <key>JST</key> <string>Asia/Tokyo</string>"
763 " <key>MDT</key> <string>America/Denver</string>"
764 " <key>MSD</key> <string>Europe/Moscow</string>"
765 " <key>MSK</key> <string>Europe/Moscow</string>"
766 " <key>MST</key> <string>America/Denver</string>"
767 " <key>NZDT</key> <string>Pacific/Auckland</string>"
768 " <key>NZST</key> <string>Pacific/Auckland</string>"
769 " <key>PDT</key> <string>America/Los_Angeles</string>"
770 " <key>PST</key> <string>America/Los_Angeles</string>"
771 " <key>UTC</key> <string>UTC</string>"
772 " <key>WEST</key> <string>Europe/Paris</string>"
773 " <key>WET</key> <string>Europe/Paris</string>"
774 " <key>YDT</key> <string>America/Yakutat</string>"
775 " <key>YST</key> <string>America/Yakutat</string>"
780 CFDictionaryRef
CFTimeZoneCopyAbbreviationDictionary(void) {
781 CFDictionaryRef dict
;
782 __CFTimeZoneLockAbbreviations();
783 if (NULL
== __CFTimeZoneAbbreviationDict
) {
784 CFDataRef data
= CFDataCreate(kCFAllocatorDefault
, __CFTimeZoneAbbreviationDefaults
, strlen(__CFTimeZoneAbbreviationDefaults
));
785 __CFTimeZoneAbbreviationDict
= CFPropertyListCreateFromXMLData(kCFAllocatorDefault
, data
, kCFPropertyListImmutable
, NULL
);
788 if (NULL
== __CFTimeZoneAbbreviationDict
) {
789 __CFTimeZoneAbbreviationDict
= CFDictionaryCreate(kCFAllocatorDefault
, NULL
, NULL
, 0, NULL
, NULL
);
791 dict
= __CFTimeZoneAbbreviationDict
? CFRetain(__CFTimeZoneAbbreviationDict
) : NULL
;
792 __CFTimeZoneUnlockAbbreviations();
796 void CFTimeZoneSetAbbreviationDictionary(CFDictionaryRef dict
) {
797 __CFGenericValidateType(dict
, CFDictionaryGetTypeID());
798 __CFTimeZoneLockGlobal();
799 if (dict
!= __CFTimeZoneAbbreviationDict
) {
800 if (dict
) CFRetain(dict
);
801 if (__CFTimeZoneAbbreviationDict
) CFRelease(__CFTimeZoneAbbreviationDict
);
802 __CFTimeZoneAbbreviationDict
= dict
;
804 __CFTimeZoneUnlockGlobal();
807 CFTimeZoneRef
CFTimeZoneCreate(CFAllocatorRef allocator
, CFStringRef name
, CFDataRef data
) {
808 // assert: (NULL != name && NULL != data);
809 CFTimeZoneRef memory
;
814 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
815 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
816 __CFGenericValidateType(name
, CFStringGetTypeID());
817 __CFGenericValidateType(data
, CFDataGetTypeID());
818 __CFTimeZoneLockGlobal();
819 if (NULL
!= __CFTimeZoneCache
&& CFDictionaryGetValueIfPresent(__CFTimeZoneCache
, name
, (const void **)&memory
)) {
820 __CFTimeZoneUnlockGlobal();
821 return (CFTimeZoneRef
)CFRetain(memory
);
823 if (!__CFParseTimeZoneData(allocator
, data
, &tzp
, &cnt
)) {
824 __CFTimeZoneUnlockGlobal();
827 size
= sizeof(struct __CFTimeZone
) - sizeof(CFRuntimeBase
);
828 memory
= _CFRuntimeCreateInstance(allocator
, __kCFTimeZoneTypeID
, size
, NULL
);
829 if (NULL
== memory
) {
830 __CFTimeZoneUnlockGlobal();
831 for (idx
= 0; idx
< cnt
; idx
++) {
832 if (NULL
!= tzp
[idx
].abbrev
) CFRelease(tzp
[idx
].abbrev
);
834 if (NULL
!= tzp
) CFAllocatorDeallocate(allocator
, tzp
);
837 ((struct __CFTimeZone
*)memory
)->_name
= CFRetain(name
);
838 ((struct __CFTimeZone
*)memory
)->_data
= CFRetain(data
);
839 ((struct __CFTimeZone
*)memory
)->_periods
= tzp
;
840 ((struct __CFTimeZone
*)memory
)->_periodCnt
= cnt
;
841 if (NULL
== __CFTimeZoneCache
) {
842 __CFTimeZoneCache
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
844 CFDictionaryAddValue(__CFTimeZoneCache
, name
, memory
);
845 __CFTimeZoneUnlockGlobal();
849 static CFTimeZoneRef
__CFTimeZoneCreateFixed(CFAllocatorRef allocator
, int32_t seconds
, CFStringRef name
, int isDST
) {
850 CFTimeZoneRef result
;
852 int32_t nameLen
= CFStringGetLength(name
);
853 #if defined(__WIN32__)
854 unsigned char *dataBytes
= CFAllocatorAllocate(allocator
, 52 + nameLen
+ 1, 0);
855 if (!dataBytes
) return NULL
;
856 if (__CFOASafe
) __CFSetLastAllocationEventName(*tzpp
, "CFTimeZone (temp)");
858 unsigned char dataBytes
[52 + nameLen
+ 1];
860 memset(dataBytes
, 0, sizeof(dataBytes
));
861 __CFEntzcode(1, dataBytes
+ 20);
862 __CFEntzcode(1, dataBytes
+ 24);
863 __CFEntzcode(1, dataBytes
+ 36);
864 __CFEntzcode(nameLen
+ 1, dataBytes
+ 40);
865 __CFEntzcode(seconds
, dataBytes
+ 44);
866 dataBytes
[48] = isDST
? 1 : 0;
867 CFStringGetCString(name
, dataBytes
+ 50, nameLen
+ 1, kCFStringEncodingASCII
);
868 data
= CFDataCreate(allocator
, dataBytes
, 52 + nameLen
+ 1);
869 result
= CFTimeZoneCreate(allocator
, name
, data
);
871 #if defined(__WIN32__)
872 CFAllocatorDeallocate(allocator
, dataBytes
);
877 // rounds offset to nearest minute
878 CFTimeZoneRef
CFTimeZoneCreateWithTimeIntervalFromGMT(CFAllocatorRef allocator
, CFTimeInterval ti
) {
879 CFTimeZoneRef result
;
881 int32_t seconds
, minute
, hour
;
882 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
883 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
884 if (ti
< -18.0 * 3600 || 18.0 * 3600 < ti
) return NULL
;
885 ti
= (ti
< 0.0) ? ceil((ti
/ 60.0) - 0.5) * 60.0 : floor((ti
/ 60.0) + 0.5) * 60.0;
886 seconds
= (int32_t)ti
;
887 hour
= (ti
< 0) ? (-seconds
/ 3600) : (seconds
/ 3600);
888 seconds
-= ((ti
< 0) ? -hour
: hour
) * 3600;
889 minute
= (ti
< 0) ? (-seconds
/ 60) : (seconds
/ 60);
890 if (fabs(ti
) < 1.0) {
891 name
= CFRetain(CFSTR("GMT"));
893 name
= CFStringCreateWithFormat(allocator
, NULL
, CFSTR("GMT%c%02d%02d"), (ti
< 0.0 ? '-' : '+'), hour
, minute
);
895 #if !defined(__WIN32__)
896 result
= __CFTimeZoneCreateFixed(allocator
, (int32_t)ti
, name
, 0);
898 /* CFTimeZoneRef->_data will contain TIME_ZONE_INFORMATION structure
899 * to find current timezone
900 * (Aleksey Dukhnyakov)
903 TIME_ZONE_INFORMATION tzi
;
905 CFIndex length
= CFStringGetLength(name
);
907 memset(&tzi
,0,sizeof(tzi
));
908 tzi
.Bias
=(long)(-ti
/60);
909 CFStringGetCharacters(name
, CFRangeMake(0, length
< 31 ? length
: 31 ), tzi
.StandardName
);
910 data
= CFDataCreate(allocator
,(UInt8
*)&tzi
, sizeof(tzi
));
911 result
= CFTimeZoneCreate(allocator
, name
, data
);
919 CFTimeZoneRef
CFTimeZoneCreateWithName(CFAllocatorRef allocator
, CFStringRef name
, Boolean tryAbbrev
) {
920 CFTimeZoneRef result
= NULL
;
921 CFStringRef tzName
= NULL
;
922 CFDataRef data
= NULL
;
923 CFURLRef baseURL
, tempURL
;
927 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
928 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
929 __CFGenericValidateType(name
, CFStringGetTypeID());
930 if (CFEqual(CFSTR(""), name
)) {
931 // empty string is not a time zone name, just abort now,
932 // following stuff will fail anyway
935 __CFTimeZoneLockGlobal();
936 if (NULL
!= __CFTimeZoneCache
&& CFDictionaryGetValueIfPresent(__CFTimeZoneCache
, name
, (const void **)&result
)) {
937 __CFTimeZoneUnlockGlobal();
938 return (CFTimeZoneRef
)CFRetain(result
);
940 __CFTimeZoneUnlockGlobal();
941 #if !defined(__WIN32__)
942 baseURL
= CFURLCreateWithFileSystemPath(kCFAllocatorDefault
, CFSTR(TZZONEINFO
), kCFURLPOSIXPathStyle
, true);
944 CFDictionaryRef abbrevs
= CFTimeZoneCopyAbbreviationDictionary();
945 tzName
= CFDictionaryGetValue(abbrevs
, name
);
946 if (NULL
!= tzName
) {
947 tempURL
= CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault
, baseURL
, tzName
, false);
948 if (NULL
!= tempURL
) {
949 if (_CFReadBytesFromFile(kCFAllocatorDefault
, tempURL
, &bytes
, &length
, 0)) {
950 data
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, bytes
, length
, kCFAllocatorDefault
);
958 CFDictionaryRef dict
= __CFTimeZoneCopyCompatibilityDictionary();
959 CFStringRef mapping
= CFDictionaryGetValue(dict
, name
);
962 } else if (CFStringHasPrefix(name
, CFSTR(TZZONEINFO
))) {
963 CFMutableStringRef unprefixed
= CFStringCreateMutableCopy(kCFAllocatorDefault
, CFStringGetLength(name
), name
);
964 CFStringDelete(unprefixed
, CFRangeMake(0, sizeof(TZZONEINFO
)));
965 mapping
= CFDictionaryGetValue(dict
, unprefixed
);
969 CFRelease(unprefixed
);
972 if (CFEqual(CFSTR(""), name
)) {
978 tempURL
= CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault
, baseURL
, tzName
, false);
979 if (NULL
!= tempURL
) {
980 if (_CFReadBytesFromFile(kCFAllocatorDefault
, tempURL
, &bytes
, &length
, 0)) {
981 data
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, bytes
, length
, kCFAllocatorDefault
);
989 tempURL
= CFURLCreateWithFileSystemPath(kCFAllocatorDefault
, tzName
, kCFURLPOSIXPathStyle
, false);
990 if (NULL
!= tempURL
) {
991 if (_CFReadBytesFromFile(kCFAllocatorDefault
, tempURL
, &bytes
, &length
, 0)) {
992 data
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, bytes
, length
, kCFAllocatorDefault
);
998 result
= CFTimeZoneCreate(allocator
, tzName
, data
);
1002 /* Reading GMT offset and daylight flag from the registry
1004 * (Aleksey Dukhnyakov)
1007 CFStringRef safeName
= name
;
1012 SYSTEMTIME StandardDate
;
1013 SYSTEMTIME DaylightDate
;
1015 TIME_ZONE_INFORMATION tzi_system
;
1018 DWORD dwType
, dwSize
=sizeof(tzi
),
1019 dwSize_name1
=sizeof(tzi_system
.StandardName
),
1020 dwSize_name2
=sizeof(tzi_system
.DaylightName
);
1023 CFDictionaryRef abbrevs
= CFTimeZoneCopyAbbreviationDictionary();
1024 tzName
= CFDictionaryGetValue(abbrevs
, name
);
1025 if (NULL
== tzName
) {
1032 /* Open regestry and move down to the TimeZone information
1034 if (RegOpenKey(HKEY_LOCAL_MACHINE
,_T(TZZONEINFO
),&hkResult
) !=
1038 /* Move down to specific TimeZone name
1040 #if defined(UNICODE)
1041 if (RegOpenKey(hkResult
,CFStringGetCharactersPtr(name
) ,&hkResult
) !=
1044 if (RegOpenKey(hkResult
,CFStringGetCStringPtr(name
, CFStringGetSystemEncoding()),&hkResult
) != ERROR_SUCCESS
) {
1048 /* TimeZone information(offsets, daylight flag, ...) assign to tzi structure
1050 if ( RegQueryValueEx(hkResult
,_T("TZI"),NULL
,&dwType
,(LPBYTE
)&tzi
,&dwSize
) != ERROR_SUCCESS
&&
1051 RegQueryValueEx(hkResult
,_T("Std"),NULL
,&dwType
,(LPBYTE
)&tzi_system
.StandardName
,&dwSize_name1
) != ERROR_SUCCESS
&&
1052 RegQueryValueEx(hkResult
,_T("Dlt"),NULL
,&dwType
,(LPBYTE
)&tzi_system
.DaylightName
,&dwSize_name2
) != ERROR_SUCCESS
)
1057 tzi_system
.Bias
=tzi
.Bias
;
1058 tzi_system
.StandardBias
=tzi
.StandardBias
;
1059 tzi_system
.DaylightBias
=tzi
.DaylightBias
;
1060 tzi_system
.StandardDate
=tzi
.StandardDate
;
1061 tzi_system
.DaylightDate
=tzi
.DaylightDate
;
1063 /* CFTimeZoneRef->_data will contain TIME_ZONE_INFORMATION structure
1064 * to find current timezone
1065 * (Aleksey Dukhnyakov)
1067 data
= CFDataCreate(allocator
,(UInt8
*)&tzi_system
, sizeof(tzi_system
));
1069 RegCloseKey(hkResult
);
1070 result
= CFTimeZoneCreate(allocator
, name
, data
);
1073 result
->_periods
->abbrev
= CFStringCreateCopy(allocator
,safeName
);
1083 CFStringRef
CFTimeZoneGetName(CFTimeZoneRef tz
) {
1084 CF_OBJC_FUNCDISPATCH0(__kCFTimeZoneTypeID
, CFStringRef
, tz
, "name");
1085 __CFGenericValidateType(tz
, __kCFTimeZoneTypeID
);
1089 CFDataRef
CFTimeZoneGetData(CFTimeZoneRef tz
) {
1090 CF_OBJC_FUNCDISPATCH0(__kCFTimeZoneTypeID
, CFDataRef
, tz
, "data");
1091 __CFGenericValidateType(tz
, __kCFTimeZoneTypeID
);
1095 /* This function converts CFAbsoluteTime to (Win32) SYSTEMTIME
1096 * (Aleksey Dukhnyakov)
1098 #if defined(__WIN32__)
1099 BOOL
__CFTimeZoneGetWin32SystemTime(SYSTEMTIME
* sys_time
, CFAbsoluteTime time
)
1102 FILETIME
* ftime
=(FILETIME
*)&l
;
1104 /* seconds between 1601 and 1970 : 11644473600,
1105 * seconds between 1970 and 2001 : 978307200,
1106 * FILETIME - number of 100-nanosecond intervals since January 1, 1601
1108 l
=(time
+11644473600+978307200)*10000000;
1109 if (FileTimeToSystemTime(ftime
,sys_time
))
1116 CFTimeInterval
CFTimeZoneGetSecondsFromGMT(CFTimeZoneRef tz
, CFAbsoluteTime at
) {
1117 #if !defined(__WIN32__)
1119 CF_OBJC_FUNCDISPATCH1(__kCFTimeZoneTypeID
, CFTimeInterval
, tz
, "_secondsFromGMTForAbsoluteTime:", at
);
1120 __CFGenericValidateType(tz
, __kCFTimeZoneTypeID
);
1121 idx
= __CFBSearchTZPeriods(tz
, at
);
1122 return __CFTZPeriodGMTOffset(&(tz
->_periods
[idx
]));
1124 /* To calculate seconds from GMT, calculate current timezone time and
1125 * subtract GMT timnezone time
1126 * (Aleksey Dukhnyakov)
1128 TIME_ZONE_INFORMATION tzi
;
1129 FILETIME ftime1
,ftime2
;
1130 SYSTEMTIME stime0
,stime1
,stime2
;
1131 LONGLONG
* l1
= (LONGLONG
*)&ftime1
;
1132 LONGLONG
* l2
= (LONGLONG
*)&ftime2
;
1133 CFRange range
={0,sizeof(TIME_ZONE_INFORMATION
)};
1136 CF_OBJC_FUNCDISPATCH1(__kCFTimeZoneTypeID
, CFTimeInterval
, tz
, "_secondsFromGMTForAbsoluteTime:", at
);
1138 CFDataGetBytes(tz
->_data
,range
,(UInt8
*)&tzi
);
1140 if (!__CFTimeZoneGetWin32SystemTime(&stime0
,at
) ||
1141 !SystemTimeToTzSpecificLocalTime(&tzi
,&stime0
,&stime1
) ||
1142 !SystemTimeToFileTime(&stime1
,&ftime1
) )
1144 CFAssert(0, __kCFLogAssertion
, "Win32 system time/timezone failed !\n");
1148 tzi
.DaylightDate
.wMonth
=0;
1149 tzi
.StandardDate
.wMonth
=0;
1154 if ( !SystemTimeToTzSpecificLocalTime(&tzi
,&stime0
,&stime2
) ||
1155 !SystemTimeToFileTime(&stime2
,&ftime2
))
1157 CFAssert(0, __kCFLogAssertion
, "Win32 system time/timezone failed !\n");
1160 result
=(double)((*l1
-*l2
)/10000000);
1165 #if defined(__WIN32__)
1167 * Get abbreviation for name for WIN32 platform
1168 * (Aleksey Dukhnyakov)
1176 static void _CFFindKeyForValue(const void *key
, const void *value
, void *context
) {
1177 if ( ((_CFAbbrFind
*)context
)->tzAbbr
!= NULL
) {
1178 if ( ((_CFAbbrFind
*)context
)->tzName
== (CFStringRef
) value
) {
1179 ((_CFAbbrFind
*)context
)->tzAbbr
= key
;
1184 CFIndex
__CFTimeZoneInitAbbrev(CFTimeZoneRef tz
) {
1186 if ( tz
->_periods
->abbrev
== NULL
) {
1187 _CFAbbrFind abbr
= { NULL
, NULL
};
1188 CFDictionaryRef abbrevs
= CFTimeZoneCopyAbbreviationDictionary();
1190 CFDictionaryApplyFunction(abbrevs
, _CFFindKeyForValue
, &abbr
);
1192 if ( abbr
.tzAbbr
!= NULL
)
1193 tz
->_periods
->abbrev
= CFStringCreateCopy(kCFAllocatorDefault
, abbr
.tzAbbr
);
1195 tz
->_periods
->abbrev
= CFStringCreateCopy(kCFAllocatorDefault
, tz
->_name
);
1196 /* We should return name of TimeZone if couldn't find abbrevation.
1199 * old line : tz->_periods->abbrev =
1200 * CFStringCreateWithCString(kCFAllocatorDefault,"UNKNOWN",
1201 * CFStringGetSystemEncoding());
1203 * (Aleksey Dukhnyakov)
1205 CFRelease( abbrevs
);
1212 CFStringRef
CFTimeZoneCopyAbbreviation(CFTimeZoneRef tz
, CFAbsoluteTime at
) {
1215 CF_OBJC_FUNCDISPATCH1(__kCFTimeZoneTypeID
, CFStringRef
, tz
, "_abbreviationForAbsoluteTime:", at
);
1216 __CFGenericValidateType(tz
, __kCFTimeZoneTypeID
);
1217 #if !defined(__WIN32__)
1218 idx
= __CFBSearchTZPeriods(tz
, at
);
1221 * Initialize abbreviation for this TimeZone
1222 * (Aleksey Dukhnyakov)
1224 idx
= __CFTimeZoneInitAbbrev(tz
);
1226 result
= __CFTZPeriodAbbreviation(&(tz
->_periods
[idx
]));
1227 return result
? CFRetain(result
) : NULL
;
1230 Boolean
CFTimeZoneIsDaylightSavingTime(CFTimeZoneRef tz
, CFAbsoluteTime at
) {
1231 #if !defined(__WIN32__)
1233 CF_OBJC_FUNCDISPATCH1(__kCFTimeZoneTypeID
, Boolean
, tz
, "_isDaylightSavingTimeForAbsoluteTime:", at
);
1234 __CFGenericValidateType(tz
, __kCFTimeZoneTypeID
);
1235 idx
= __CFBSearchTZPeriods(tz
, at
);
1236 return __CFTZPeriodIsDST(&(tz
->_periods
[idx
]));
1238 /* Compare current timezone time and current timezone time without
1239 * transition to day light saving time
1240 * (Aleskey Dukhnyakov)
1242 TIME_ZONE_INFORMATION tzi
;
1243 SYSTEMTIME stime0
,stime1
,stime2
;
1244 CFRange range
={0,sizeof(TIME_ZONE_INFORMATION
)};
1246 CF_OBJC_FUNCDISPATCH1(__kCFTimeZoneTypeID
, Boolean
, tz
, "_isDaylightSavingTimeForAbsoluteTime:", at
);
1248 CFDataGetBytes(tz
->_data
,range
,(UInt8
*)&tzi
);
1250 if ( !__CFTimeZoneGetWin32SystemTime(&stime0
,at
) ||
1251 !SystemTimeToTzSpecificLocalTime(&tzi
,&stime0
,&stime1
)) {
1252 CFAssert(0, __kCFLogAssertion
, "Win32 system time/timezone failed !\n");
1256 tzi
.DaylightDate
.wMonth
=0;
1257 tzi
.StandardDate
.wMonth
=0;
1259 if ( !SystemTimeToTzSpecificLocalTime(&tzi
,&stime0
,&stime2
)) {
1260 CFAssert(0, __kCFLogAssertion
, "Win32 system time/timezone failed !\n");
1264 if ( !memcmp(&stime1
,&stime2
,sizeof(stime1
)) )
1271 CFTimeInterval
_CFTimeZoneGetDSTDelta(CFTimeZoneRef tz
, CFAbsoluteTime at
) {
1273 __CFGenericValidateType(tz
, __kCFTimeZoneTypeID
);
1274 idx
= __CFBSearchTZPeriods(tz
, at
);
1275 CFTimeInterval delta
= __CFTZPeriodGMTOffset(&(tz
->_periods
[idx
]));
1276 if (idx
+ 1 < tz
->_periodCnt
) {
1277 return fabs(delta
- __CFTZPeriodGMTOffset(&(tz
->_periods
[idx
+ 1])));
1278 } else if (0 < idx
) {
1279 return fabs(delta
- __CFTZPeriodGMTOffset(&(tz
->_periods
[idx
- 1])));
1284 static const unsigned char *__CFTimeZoneCompatibilityMapping
=
1285 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
1286 " <!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">"
1287 " <plist version=\"1.0\">"
1290 // Empty string means delete/ignore these
1291 " <key>Factory</key> <string></string>"
1292 " <key>US/Pacific-New</key> <string></string>"
1293 " <key>Mideast/Riyadh87</key> <string></string>"
1294 " <key>Mideast/Riyadh88</key> <string></string>"
1295 " <key>Mideast/Riyadh89</key> <string></string>"
1296 " <key>SystemV/AST4</key> <string></string>"
1297 " <key>SystemV/AST4ADT</key> <string></string>"
1298 " <key>SystemV/CST6</key> <string></string>"
1299 " <key>SystemV/CST6CDT</key> <string></string>"
1300 " <key>SystemV/EST5</key> <string></string>"
1301 " <key>SystemV/EST5EDT</key> <string></string>"
1302 " <key>SystemV/HST10</key> <string></string>"
1303 " <key>SystemV/MST7</key> <string></string>"
1304 " <key>SystemV/MST7MDT</key> <string></string>"
1305 " <key>SystemV/PST8</key> <string></string>"
1306 " <key>SystemV/PST8PDT</key> <string></string>"
1307 " <key>SystemV/YST9</key> <string></string>"
1308 " <key>SystemV/YST9YDT</key> <string></string>"
1310 " <key>America/Atka</key> <string>America/Adak</string>"
1311 " <key>America/Ensenada</key> <string>America/Tijuana</string>"
1312 " <key>America/Fort_Wayne</key> <string>America/Indianapolis</string>"
1313 " <key>America/Indiana/Indianapolis</key> <string>America/Indianapolis</string>"
1314 " <key>America/Kentucky/Louisville</key> <string>America/Louisville</string>"
1315 " <key>America/Knox_IN</key> <string>America/Indiana/Knox</string>"
1316 " <key>America/Porto_Acre</key> <string>America/Rio_Branco</string>"
1317 " <key>America/Rosario</key> <string>America/Cordoba</string>"
1318 " <key>America/Shiprock</key> <string>America/Denver</string>"
1319 " <key>America/Virgin</key> <string>America/St_Thomas</string>"
1320 " <key>Antarctica/South_Pole</key> <string>Antarctica/McMurdo</string>"
1321 " <key>Asia/Ashkhabad</key> <string>Asia/Ashgabat</string>"
1322 " <key>Asia/Chungking</key> <string>Asia/Chongqing</string>"
1323 //" <key>Asia/Dacca</key> <string>Asia/Dhaka</string>"
1324 //" <key>Asia/Istanbul</key> <string>Europe/Istanbul</string>"
1325 " <key>Asia/Macao</key> <string>Asia/Macau</string>"
1326 " <key>Asia/Tel_Aviv</key> <string>Asia/Jerusalem</string>"
1327 " <key>Asia/Thimbu</key> <string>Asia/Thimphu</string>"
1328 " <key>Asia/Ujung_Pandang</key> <string>Asia/Makassar</string>"
1329 " <key>Asia/Ulan_Bator</key> <string>Asia/Ulaanbaatar</string>"
1330 " <key>Australia/ACT</key> <string>Australia/Sydney</string>"
1331 //" <key>Australia/Canberra</key> <string>Australia/Sydney</string>"
1332 " <key>Australia/LHI</key> <string>Australia/Lord_Howe</string>"
1333 " <key>Australia/NSW</key> <string>Australia/Sydney</string>"
1334 " <key>Australia/North</key> <string>Australia/Darwin</string>"
1335 " <key>Australia/Queensland</key> <string>Australia/Brisbane</string>"
1336 " <key>Australia/South</key> <string>Australia/Adelaide</string>"
1337 " <key>Australia/Tasmania</key> <string>Australia/Hobart</string>"
1338 " <key>Australia/Victoria</key> <string>Australia/Melbourne</string>"
1339 " <key>Australia/West</key> <string>Australia/Perth</string>"
1340 " <key>Australia/Yancowinna</key> <string>Australia/Broken_Hill</string>"
1341 " <key>Brazil/Acre</key> <string>America/Porto_Acre</string>"
1342 " <key>Brazil/DeNoronha</key> <string>America/Noronha</string>"
1343 //" <key>Brazil/East</key> <string>America/Sao_Paulo</string>"
1344 " <key>Brazil/West</key> <string>America/Manaus</string>"
1345 " <key>CST6CDT</key> <string>America/Chicago</string>"
1346 //" <key>Canada/Atlantic</key> <string>America/Halifax</string>"
1347 " <key>Canada/Central</key> <string>America/Winnipeg</string>"
1348 " <key>Canada/East-Saskatchewan</key> <string>America/Regina</string>"
1349 //" <key>Canada/Eastern</key> <string>America/Montreal</string>"
1350 //" <key>Canada/Mountain</key> <string>America/Edmonton</string>"
1351 //" <key>Canada/Newfoundland</key> <string>America/St_Johns</string>"
1352 " <key>Canada/Pacific</key> <string>America/Vancouver</string>"
1353 //" <key>Canada/Saskatchewan</key> <string>America/Regina</string>"
1354 " <key>Canada/Yukon</key> <string>America/Whitehorse</string>"
1355 " <key>Chile/Continental</key> <string>America/Santiago</string>"
1356 " <key>Chile/EasterIsland</key> <string>Pacific/Easter</string>"
1357 " <key>Cuba</key> <string>America/Havana</string>"
1358 " <key>EST5EDT</key> <string>America/New_York</string>"
1359 " <key>Egypt</key> <string>Africa/Cairo</string>"
1360 " <key>Eire</key> <string>Europe/Dublin</string>"
1361 " <key>Etc/GMT+0</key> <string>GMT</string>"
1362 " <key>Etc/GMT-0</key> <string>GMT</string>"
1363 " <key>Etc/GMT0</key> <string>GMT</string>"
1364 " <key>Etc/Greenwich</key> <string>GMT</string>"
1365 " <key>Etc/Universal</key> <string>UTC</string>"
1366 " <key>Etc/Zulu</key> <string>UTC</string>"
1367 " <key>Europe/Nicosia</key> <string>Asia/Nicosia</string>"
1368 " <key>Europe/Tiraspol</key> <string>Europe/Chisinau</string>"
1369 " <key>GB-Eire</key> <string>Europe/London</string>"
1370 " <key>GB</key> <string>Europe/London</string>"
1371 " <key>GMT+0</key> <string>GMT</string>"
1372 " <key>GMT-0</key> <string>GMT</string>"
1373 " <key>GMT0</key> <string>GMT</string>"
1374 " <key>Greenwich</key> <string>GMT</string>"
1375 " <key>Hongkong</key> <string>Asia/Hong_Kong</string>"
1376 " <key>Iceland</key> <string>Atlantic/Reykjavik</string>"
1377 " <key>Iran</key> <string>Asia/Tehran</string>"
1378 " <key>Israel</key> <string>Asia/Jerusalem</string>"
1379 " <key>Jamaica</key> <string>America/Jamaica</string>"
1380 //" <key>Japan</key> <string>Asia/Tokyo</string>"
1381 " <key>Kwajalein</key> <string>Pacific/Kwajalein</string>"
1382 " <key>Libya</key> <string>Africa/Tripoli</string>"
1383 " <key>MST7MDT</key> <string>America/Denver</string>"
1384 " <key>Mexico/BajaNorte</key> <string>America/Tijuana</string>"
1385 " <key>Mexico/BajaSur</key> <string>America/Mazatlan</string>"
1386 " <key>Mexico/General</key> <string>America/Mexico_City</string>"
1387 " <key>NZ-CHAT</key> <string>Pacific/Chatham</string>"
1388 " <key>NZ</key> <string>Pacific/Auckland</string>"
1389 " <key>Navajo</key> <string>America/Denver</string>"
1390 " <key>PRC</key> <string>Asia/Shanghai</string>"
1391 " <key>PST8PDT</key> <string>America/Los_Angeles</string>"
1392 " <key>Pacific/Samoa</key> <string>Pacific/Pago_Pago</string>"
1393 " <key>Poland</key> <string>Europe/Warsaw</string>"
1394 " <key>Portugal</key> <string>Europe/Lisbon</string>"
1395 " <key>ROC</key> <string>Asia/Taipei</string>"
1396 " <key>ROK</key> <string>Asia/Seoul</string>"
1397 " <key>Singapore</key> <string>Asia/Singapore</string>"
1398 " <key>Turkey</key> <string>Europe/Istanbul</string>"
1399 " <key>UCT</key> <string>UTC</string>"
1400 " <key>US/Alaska</key> <string>America/Anchorage</string>"
1401 " <key>US/Aleutian</key> <string>America/Adak</string>"
1402 " <key>US/Arizona</key> <string>America/Phoenix</string>"
1403 //" <key>US/Central</key> <string>America/Chicago</string>"
1404 " <key>US/East-Indiana</key> <string>America/Indianapolis</string>"
1405 //" <key>US/Eastern</key> <string>America/New_York</string>"
1406 " <key>US/Hawaii</key> <string>Pacific/Honolulu</string>"
1407 " <key>US/Indiana-Starke</key> <string>America/Indiana/Knox</string>"
1408 " <key>US/Michigan</key> <string>America/Detroit</string>"
1409 //" <key>US/Mountain</key> <string>America/Denver</string>"
1410 //" <key>US/Pacific</key> <string>America/Los_Angeles</string>"
1411 " <key>US/Samoa</key> <string>Pacific/Pago_Pago</string>"
1412 " <key>Universal</key> <string>UTC</string>"
1413 " <key>W-SU</key> <string>Europe/Moscow</string>"
1414 " <key>Zulu</key> <string>UTC</string>"
1418 static CFDictionaryRef
__CFTimeZoneCopyCompatibilityDictionary(void) {
1419 CFDictionaryRef dict
;
1420 __CFTimeZoneLockCompatibilityMapping();
1421 if (NULL
== __CFTimeZoneCompatibilityMappingDict
) {
1422 CFDataRef data
= CFDataCreate(kCFAllocatorDefault
, __CFTimeZoneCompatibilityMapping
, strlen(__CFTimeZoneCompatibilityMapping
));
1423 __CFTimeZoneCompatibilityMappingDict
= CFPropertyListCreateFromXMLData(kCFAllocatorDefault
, data
, kCFPropertyListImmutable
, NULL
);
1426 if (NULL
== __CFTimeZoneCompatibilityMappingDict
) {
1427 __CFTimeZoneCompatibilityMappingDict
= CFDictionaryCreate(kCFAllocatorDefault
, NULL
, NULL
, 0, NULL
, NULL
);
1429 dict
= __CFTimeZoneCompatibilityMappingDict
? CFRetain(__CFTimeZoneCompatibilityMappingDict
) : NULL
;
1430 __CFTimeZoneUnlockCompatibilityMapping();
1434 static const unsigned char *__CFTimeZoneCompatibilityMapping2
=
1435 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
1436 " <!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">"
1437 " <plist version=\"1.0\">"
1439 " <key>Asia/Dacca</key> <string>Asia/Dhaka</string>"
1440 " <key>Asia/Istanbul</key> <string>Europe/Istanbul</string>"
1441 " <key>Australia/Canberra</key> <string>Australia/Sydney</string>"
1442 " <key>Brazil/East</key> <string>America/Sao_Paulo</string>"
1443 " <key>Canada/Atlantic</key> <string>America/Halifax</string>"
1444 " <key>Canada/Eastern</key> <string>America/Montreal</string>"
1445 " <key>Canada/Mountain</key> <string>America/Edmonton</string>"
1446 " <key>Canada/Newfoundland</key> <string>America/St_Johns</string>"
1447 " <key>Canada/Saskatchewan</key> <string>America/Regina</string>"
1448 " <key>Japan</key> <string>Asia/Tokyo</string>"
1449 " <key>US/Central</key> <string>America/Chicago</string>"
1450 " <key>US/Eastern</key> <string>America/New_York</string>"
1451 " <key>US/Mountain</key> <string>America/Denver</string>"
1452 " <key>US/Pacific</key> <string>America/Los_Angeles</string>"
1456 __private_extern__ CFDictionaryRef
__CFTimeZoneCopyCompatibilityDictionary2(void) {
1457 CFDictionaryRef dict
;
1458 __CFTimeZoneLockCompatibilityMapping();
1459 if (NULL
== __CFTimeZoneCompatibilityMappingDict2
) {
1460 CFDataRef data
= CFDataCreate(kCFAllocatorDefault
, __CFTimeZoneCompatibilityMapping2
, strlen(__CFTimeZoneCompatibilityMapping2
));
1461 __CFTimeZoneCompatibilityMappingDict2
= CFPropertyListCreateFromXMLData(kCFAllocatorDefault
, data
, kCFPropertyListImmutable
, NULL
);
1464 if (NULL
== __CFTimeZoneCompatibilityMappingDict2
) {
1465 __CFTimeZoneCompatibilityMappingDict2
= CFDictionaryCreate(kCFAllocatorDefault
, NULL
, NULL
, 0, NULL
, NULL
);
1467 dict
= __CFTimeZoneCompatibilityMappingDict2
? CFRetain(__CFTimeZoneCompatibilityMappingDict2
) : NULL
;
1468 __CFTimeZoneUnlockCompatibilityMapping();