2 * Copyright (c) 2009 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 Copyright 1998-2002, Apple, Inc. All rights reserved.
25 Responsibility: Christopher Kane
30 #include <CoreFoundation/CFTimeZone.h>
31 #include <CoreFoundation/CFPropertyList.h>
32 #include <CoreFoundation/CFDateFormatter.h>
33 #include <CoreFoundation/CFPriv.h>
34 #include "CFInternal.h"
41 #include <unicode/ucal.h>
42 #include <CoreFoundation/CFDateFormatter.h>
43 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
46 #include <sys/fcntl.h>
49 #error Unknown or unspecified DEPLOYMENT_TARGET
53 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
54 #define TZZONELINK TZDEFAULT
55 #define TZZONEINFO TZDIR "/"
56 #elif DEPLOYMENT_TARGET_WINDOWS
57 static CFStringRef __tzZoneInfo
= NULL
;
58 static char *__tzDir
= NULL
;
59 static void __InitTZStrings(void);
61 #error Unknown or unspecified DEPLOYMENT_TARGET
64 CONST_STRING_DECL(kCFTimeZoneSystemTimeZoneDidChangeNotification
, "kCFTimeZoneSystemTimeZoneDidChangeNotification")
66 static CFTimeZoneRef __CFTimeZoneSystem
= NULL
;
67 static CFTimeZoneRef __CFTimeZoneDefault
= NULL
;
68 static CFDictionaryRef __CFTimeZoneAbbreviationDict
= NULL
;
69 static CFSpinLock_t __CFTimeZoneAbbreviationLock
= CFSpinLockInit
;
70 static CFMutableDictionaryRef __CFTimeZoneCompatibilityMappingDict
= NULL
;
71 static CFSpinLock_t __CFTimeZoneCompatibilityMappingLock
= CFSpinLockInit
;
72 static CFArrayRef __CFKnownTimeZoneList
= NULL
;
73 static CFMutableDictionaryRef __CFTimeZoneCache
= NULL
;
74 static CFSpinLock_t __CFTimeZoneGlobalLock
= CFSpinLockInit
;
76 #if DEPLOYMENT_TARGET_WINDOWS
77 static CFDictionaryRef __CFTimeZoneWinToOlsonDict
= NULL
;
78 static CFSpinLock_t __CFTimeZoneWinToOlsonLock
= CFSpinLockInit
;
81 CF_INLINE
void __CFTimeZoneLockGlobal(void) {
82 __CFSpinLock(&__CFTimeZoneGlobalLock
);
85 CF_INLINE
void __CFTimeZoneUnlockGlobal(void) {
86 __CFSpinUnlock(&__CFTimeZoneGlobalLock
);
89 CF_INLINE
void __CFTimeZoneLockAbbreviations(void) {
90 __CFSpinLock(&__CFTimeZoneAbbreviationLock
);
93 CF_INLINE
void __CFTimeZoneUnlockAbbreviations(void) {
94 __CFSpinUnlock(&__CFTimeZoneAbbreviationLock
);
97 CF_INLINE
void __CFTimeZoneLockCompatibilityMapping(void) {
98 __CFSpinLock(&__CFTimeZoneCompatibilityMappingLock
);
101 CF_INLINE
void __CFTimeZoneUnlockCompatibilityMapping(void) {
102 __CFSpinUnlock(&__CFTimeZoneCompatibilityMappingLock
);
105 #if DEPLOYMENT_TARGET_WINDOWS
106 /* This function should be used for WIN32 instead of
107 * __CFCopyRecursiveDirectoryList function.
108 * It takes TimeZone names from the registry
109 * (Aleksey Dukhnyakov)
111 static CFMutableArrayRef
__CFCopyWindowsTimeZoneList() {
112 CFMutableArrayRef result
= NULL
;
114 TCHAR lpName
[MAX_PATH
+1];
115 DWORD dwIndex
, retCode
;
117 if (RegOpenKey(HKEY_LOCAL_MACHINE
,_T(TZZONEINFO
),&hkResult
) !=
121 result
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
122 for (dwIndex
=0; (retCode
= RegEnumKey(hkResult
,dwIndex
,lpName
,MAX_PATH
)) != ERROR_NO_MORE_ITEMS
; dwIndex
++) {
123 if (retCode
!= ERROR_SUCCESS
) {
124 RegCloseKey(hkResult
);
129 CFStringRef string
= CFStringCreateWithBytes(kCFAllocatorSystemDefault
, (const UInt8
*)lpName
, (_tcslen(lpName
) * sizeof(UniChar
)), kCFStringEncodingUnicode
, false);
131 CFStringRef string
= CFStringCreateWithBytes(kCFAllocatorSystemDefault
, lpName
, _tcslen(lpName
), CFStringGetSystemEncoding(), false);
133 CFArrayAppendValue(result
, string
);
138 RegCloseKey(hkResult
);
141 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
142 static CFMutableArrayRef
__CFCopyRecursiveDirectoryList() {
143 CFMutableArrayRef result
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
144 #if DEPLOYMENT_TARGET_WINDOWS
145 if (!__tzDir
) __InitTZStrings();
146 if (!__tzDir
) return result
;
147 int fd
= open(__tzDir
, O_RDONLY
);
149 int fd
= open(TZDIR
"/zone.tab", O_RDONLY
);
153 uint8_t buffer
[4096];
154 ssize_t len
= read(fd
, buffer
, sizeof(buffer
));
156 if (len
< sizeof(buffer
)) {
157 // assumes that partial read only occurs at the end of the file
161 const uint8_t *bytes
= buffer
;
163 const uint8_t *nextl
= memchr(bytes
, '\n', len
);
167 len
-= (nextl
- bytes
);
171 const uint8_t *tab1
= memchr(bytes
, '\t', (nextl
- bytes
));
173 len
-= (nextl
- bytes
);
178 len
-= (tab1
- bytes
);
180 const uint8_t *tab2
= memchr(bytes
, '\t', (nextl
- bytes
));
182 len
-= (nextl
- bytes
);
187 len
-= (tab2
- bytes
);
189 const uint8_t *tab3
= memchr(bytes
, '\t', (nextl
- bytes
));
190 int nmlen
= tab3
? (tab3
- bytes
) : (nextl
- 1 - bytes
);
191 CFStringRef string
= CFStringCreateWithBytes(kCFAllocatorSystemDefault
, bytes
, nmlen
, kCFStringEncodingUTF8
, false);
192 CFArrayAppendValue(result
, string
);
194 len
-= (nextl
- bytes
);
197 lseek(fd
, -len
, SEEK_CUR
);
203 #error Unknown or unspecified DEPLOYMENT_TARGET
206 typedef struct _CFTZPeriod
{
212 struct __CFTimeZone
{
214 CFStringRef _name
; /* immutable */
215 CFDataRef _data
; /* immutable */
216 CFTZPeriod
*_periods
; /* immutable */
217 int32_t _periodCnt
; /* immutable */
220 /* startSec is the whole integer seconds from a CFAbsoluteTime, giving dates
221 * between 1933 and 2069; info outside these years is discarded on read-in */
222 /* Bits 31-18 of the info are unused */
223 /* Bit 17 of the info is used for the is-DST state */
224 /* Bit 16 of the info is used for the sign of the offset (1 == negative) */
225 /* Bits 15-0 of the info are used for abs(offset) in seconds from GMT */
227 CF_INLINE
void __CFTZPeriodInit(CFTZPeriod
*period
, int32_t startTime
, CFStringRef abbrev
, int32_t offset
, Boolean isDST
) {
228 period
->startSec
= startTime
;
229 period
->abbrev
= abbrev
? (CFStringRef
)CFRetain(abbrev
) : NULL
;
230 __CFBitfieldSetValue(period
->info
, 15, 0, abs(offset
));
231 __CFBitfieldSetValue(period
->info
, 16, 16, (offset
< 0 ? 1 : 0));
232 __CFBitfieldSetValue(period
->info
, 17, 17, (isDST
? 1 : 0));
235 CF_INLINE
int32_t __CFTZPeriodStartSeconds(const CFTZPeriod
*period
) {
236 return period
->startSec
;
239 CF_INLINE CFStringRef
__CFTZPeriodAbbreviation(const CFTZPeriod
*period
) {
240 return period
->abbrev
;
243 CF_INLINE
int32_t __CFTZPeriodGMTOffset(const CFTZPeriod
*period
) {
244 int32_t v
= __CFBitfieldGetValue(period
->info
, 15, 0);
245 if (__CFBitfieldGetValue(period
->info
, 16, 16)) v
= -v
;
249 CF_INLINE Boolean
__CFTZPeriodIsDST(const CFTZPeriod
*period
) {
250 return (Boolean
)__CFBitfieldGetValue(period
->info
, 17, 17);
253 static CFComparisonResult
__CFCompareTZPeriods(const void *val1
, const void *val2
, void *context
) {
254 CFTZPeriod
*tzp1
= (CFTZPeriod
*)val1
;
255 CFTZPeriod
*tzp2
= (CFTZPeriod
*)val2
;
256 // we treat equal as less than, as the code which uses the
257 // result of the bsearch doesn't expect exact matches
258 // (they're pretty rare, so no point in over-coding for them)
259 if (__CFTZPeriodStartSeconds(tzp1
) <= __CFTZPeriodStartSeconds(tzp2
)) return kCFCompareLessThan
;
260 return kCFCompareGreaterThan
;
263 static CFIndex
__CFBSearchTZPeriods(CFTimeZoneRef tz
, CFAbsoluteTime at
) {
265 __CFTZPeriodInit(&elem
, (int32_t)floor(at
+ 1.0), NULL
, 0, false);
266 CFIndex idx
= CFBSearch(&elem
, sizeof(CFTZPeriod
), tz
->_periods
, tz
->_periodCnt
, __CFCompareTZPeriods
, NULL
);
267 if (tz
->_periodCnt
<= idx
) {
268 idx
= tz
->_periodCnt
;
269 } else if (0 == idx
) {
276 CF_INLINE
int32_t __CFDetzcode(const unsigned char *bufp
) {
277 int32_t result
= (bufp
[0] & 0x80) ? ~0L : 0L;
278 result
= (result
<< 8) | (bufp
[0] & 0xff);
279 result
= (result
<< 8) | (bufp
[1] & 0xff);
280 result
= (result
<< 8) | (bufp
[2] & 0xff);
281 result
= (result
<< 8) | (bufp
[3] & 0xff);
285 CF_INLINE
void __CFEntzcode(int32_t value
, unsigned char *bufp
) {
286 bufp
[0] = (value
>> 24) & 0xff;
287 bufp
[1] = (value
>> 16) & 0xff;
288 bufp
[2] = (value
>> 8) & 0xff;
289 bufp
[3] = (value
>> 0) & 0xff;
292 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
293 static Boolean
__CFParseTimeZoneData(CFAllocatorRef allocator
, CFDataRef data
, CFTZPeriod
**tzpp
, CFIndex
*cntp
) {
294 int32_t len
, timecnt
, typecnt
, charcnt
, idx
, cnt
;
295 const uint8_t *p
, *timep
, *typep
, *ttisp
, *charp
;
297 Boolean result
= true;
299 p
= CFDataGetBytePtr(data
);
300 len
= CFDataGetLength(data
);
301 if (len
< (int32_t)sizeof(struct tzhead
)) {
305 if (!(p
[0] == 'T' && p
[1] == 'Z' && p
[2] == 'i' && p
[3] == 'f')) return false; /* Don't parse without TZif at head of file */
307 p
+= 20 + 4 + 4 + 4; /* skip reserved, ttisgmtcnt, ttisstdcnt, leapcnt */
308 timecnt
= __CFDetzcode(p
);
310 typecnt
= __CFDetzcode(p
);
312 charcnt
= __CFDetzcode(p
);
314 if (typecnt
<= 0 || timecnt
< 0 || charcnt
< 0) {
317 if (1024 < timecnt
|| 32 < typecnt
|| 128 < charcnt
) {
318 // reject excessive timezones to avoid arithmetic overflows for
319 // security reasons and to reject potentially corrupt files
322 if (len
- (int32_t)sizeof(struct tzhead
) < (4 + 1) * timecnt
+ (4 + 1 + 1) * typecnt
+ charcnt
) {
326 typep
= timep
+ 4 * timecnt
;
327 ttisp
= typep
+ timecnt
;
328 charp
= ttisp
+ (4 + 1 + 1) * typecnt
;
329 cnt
= (0 < timecnt
) ? timecnt
: 1;
330 *tzpp
= CFAllocatorAllocate(allocator
, cnt
* sizeof(CFTZPeriod
), 0);
331 if (__CFOASafe
) __CFSetLastAllocationEventName(*tzpp
, "CFTimeZone (store)");
332 memset(*tzpp
, 0, cnt
* sizeof(CFTZPeriod
));
333 abbrs
= CFAllocatorAllocate(allocator
, (charcnt
+ 1) * sizeof(CFStringRef
), 0);
334 if (__CFOASafe
) __CFSetLastAllocationEventName(abbrs
, "CFTimeZone (temp)");
335 for (idx
= 0; idx
< charcnt
+ 1; idx
++) {
338 for (idx
= 0; idx
< cnt
; idx
++) {
340 int32_t itime
, offset
;
341 uint8_t type
, dst
, abbridx
;
343 at
= (CFAbsoluteTime
)(__CFDetzcode(timep
) + 0.0) - kCFAbsoluteTimeIntervalSince1970
;
344 if (0 == timecnt
) itime
= INT_MIN
;
345 else if (at
< (CFAbsoluteTime
)INT_MIN
) itime
= INT_MIN
;
346 else if ((CFAbsoluteTime
)INT_MAX
< at
) itime
= INT_MAX
;
347 else itime
= (int32_t)at
;
348 timep
+= 4; /* harmless if 0 == timecnt */
349 type
= (0 < timecnt
) ? (uint8_t)*typep
++ : 0;
350 if (typecnt
<= type
) {
354 offset
= __CFDetzcode(ttisp
+ 6 * type
);
355 dst
= (uint8_t)*(ttisp
+ 6 * type
+ 4);
356 if (0 != dst
&& 1 != dst
) {
360 abbridx
= (uint8_t)*(ttisp
+ 6 * type
+ 5);
361 if (charcnt
< abbridx
) {
365 if (NULL
== abbrs
[abbridx
]) {
366 abbrs
[abbridx
] = CFStringCreateWithCString(allocator
, (char *)&charp
[abbridx
], kCFStringEncodingASCII
);
368 __CFTZPeriodInit(*tzpp
+ idx
, itime
, abbrs
[abbridx
], offset
, (dst
? true : false));
370 for (idx
= 0; idx
< charcnt
+ 1; idx
++) {
371 if (NULL
!= abbrs
[idx
]) {
372 CFRelease(abbrs
[idx
]);
375 CFAllocatorDeallocate(allocator
, abbrs
);
377 // dump all but the last INT_MIN and the first INT_MAX
378 for (idx
= 0; idx
< cnt
; idx
++) {
379 if (((*tzpp
+ idx
)->startSec
== INT_MIN
) && (idx
+ 1 < cnt
) && (((*tzpp
+ idx
+ 1)->startSec
== INT_MIN
))) {
380 if (NULL
!= (*tzpp
+ idx
)->abbrev
) CFRelease((*tzpp
+ idx
)->abbrev
);
382 memmove((*tzpp
+ idx
), (*tzpp
+ idx
+ 1), sizeof(CFTZPeriod
) * (cnt
- idx
));
386 // Don't combine these loops! Watch the idx decrementing...
387 for (idx
= 0; idx
< cnt
; idx
++) {
388 if (((*tzpp
+ idx
)->startSec
== INT_MAX
) && (0 < idx
) && (((*tzpp
+ idx
- 1)->startSec
== INT_MAX
))) {
389 if (NULL
!= (*tzpp
+ idx
)->abbrev
) CFRelease((*tzpp
+ idx
)->abbrev
);
391 memmove((*tzpp
+ idx
), (*tzpp
+ idx
+ 1), sizeof(CFTZPeriod
) * (cnt
- idx
));
395 CFQSortArray(*tzpp
, cnt
, sizeof(CFTZPeriod
), __CFCompareTZPeriods
, NULL
);
396 // if the first period is in DST and there is more than one period, drop it
397 if (1 < cnt
&& __CFTZPeriodIsDST(*tzpp
+ 0)) {
398 if (NULL
!= (*tzpp
+ 0)->abbrev
) CFRelease((*tzpp
+ 0)->abbrev
);
400 memmove((*tzpp
+ 0), (*tzpp
+ 0 + 1), sizeof(CFTZPeriod
) * (cnt
- 0));
404 CFAllocatorDeallocate(allocator
, *tzpp
);
409 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
410 static Boolean
__CFParseTimeZoneData(CFAllocatorRef allocator
, CFDataRef data
, CFTZPeriod
**tzpp
, CFIndex
*cntp
) {
411 /* We use Win32 function to find TimeZone
412 * (Aleksey Dukhnyakov)
414 *tzpp
= (CFTZPeriod
*)CFAllocatorAllocate(allocator
, sizeof(CFTZPeriod
), 0);
415 memset(*tzpp
, 0, sizeof(CFTZPeriod
));
416 __CFTZPeriodInit(*tzpp
, 0, NULL
, 0, false);
421 #error Unknown or unspecified DEPLOYMENT_TARGET
424 static Boolean
__CFTimeZoneEqual(CFTypeRef cf1
, CFTypeRef cf2
) {
425 CFTimeZoneRef tz1
= (CFTimeZoneRef
)cf1
;
426 CFTimeZoneRef tz2
= (CFTimeZoneRef
)cf2
;
427 if (!CFEqual(CFTimeZoneGetName(tz1
), CFTimeZoneGetName(tz2
))) return false;
428 if (!CFEqual(CFTimeZoneGetData(tz1
), CFTimeZoneGetData(tz2
))) return false;
432 static CFHashCode
__CFTimeZoneHash(CFTypeRef cf
) {
433 CFTimeZoneRef tz
= (CFTimeZoneRef
)cf
;
434 return CFHash(CFTimeZoneGetName(tz
));
437 static CFStringRef
__CFTimeZoneCopyDescription(CFTypeRef cf
) {
438 CFTimeZoneRef tz
= (CFTimeZoneRef
)cf
;
439 CFStringRef result
, abbrev
;
441 at
= CFAbsoluteTimeGetCurrent();
442 abbrev
= CFTimeZoneCopyAbbreviation(tz
, at
);
443 result
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, 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");
448 static void __CFTimeZoneDeallocate(CFTypeRef cf
) {
449 CFTimeZoneRef tz
= (CFTimeZoneRef
)cf
;
450 CFAllocatorRef allocator
= CFGetAllocator(tz
);
452 if (tz
->_name
) CFRelease(tz
->_name
);
453 if (tz
->_data
) CFRelease(tz
->_data
);
454 for (idx
= 0; idx
< tz
->_periodCnt
; idx
++) {
455 if (NULL
!= tz
->_periods
[idx
].abbrev
) CFRelease(tz
->_periods
[idx
].abbrev
);
457 if (NULL
!= tz
->_periods
) CFAllocatorDeallocate(allocator
, tz
->_periods
);
460 static CFTypeID __kCFTimeZoneTypeID
= _kCFRuntimeNotATypeID
;
462 static const CFRuntimeClass __CFTimeZoneClass
= {
467 __CFTimeZoneDeallocate
,
471 __CFTimeZoneCopyDescription
474 __private_extern__
void __CFTimeZoneInitialize(void) {
475 __kCFTimeZoneTypeID
= _CFRuntimeRegisterClass(&__CFTimeZoneClass
);
478 CFTypeID
CFTimeZoneGetTypeID(void) {
479 return __kCFTimeZoneTypeID
;
483 #if DEPLOYMENT_TARGET_WINDOWS_SYNC
484 static const char *__CFTimeZoneWinToOlsonDefaults
=
485 /* Mappings to time zones in Windows Registry are best-guess */
486 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
487 " <!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">"
488 " <plist version=\"1.0\">"
490 " <key>Afghanistan</key> <string>Asia/Kabul</string>"
491 " <key>Afghanistan Standard Time</key> <string>Asia/Kabul</string>"
492 " <key>Alaskan</key> <string>America/Anchorage</string>"
493 " <key>Alaskan Standard Time</key> <string>America/Anchorage</string>"
494 " <key>Arab</key> <string>Asia/Riyadh</string>"
495 " <key>Arab Standard Time</key> <string>Asia/Riyadh</string>"
496 " <key>Arabian</key> <string>Asia/Muscat</string>"
497 " <key>Arabian Standard Time</key> <string>Asia/Muscat</string>"
498 " <key>Arabic Standard Time</key> <string>Asia/Baghdad</string>"
499 " <key>Atlantic</key> <string>America/Halifax</string>"
500 " <key>Atlantic Standard Time</key> <string>America/Halifax</string>"
501 " <key>AUS Central</key> <string>Australia/Darwin</string>"
502 " <key>AUS Central Standard Time</key> <string>Australia/Darwin</string>"
503 " <key>AUS Eastern</key> <string>Australia/Sydney</string>"
504 " <key>AUS Eastern Standard Time</key> <string>Australia/Sydney</string>"
505 " <key>Azerbaijan Standard Time</key> <string>Asia/Baku</string>"
506 " <key>Azores</key> <string>Atlantic/Azores</string>"
507 " <key>Azores Standard Time</key> <string>Atlantic/Azores</string>"
508 " <key>Bangkok</key> <string>Asia/Bangkok</string>"
509 " <key>Bangkok Standard Time</key> <string>Asia/Bangkok</string>"
510 " <key>Beijing</key> <string>Asia/Shanghai</string>"
511 " <key>Canada Central</key> <string>America/Regina</string>"
512 " <key>Canada Central Standard Time</key> <string>America/Regina</string>"
513 " <key>Cape Verde Standard Time</key> <string>Atlantic/Cape_Verde</string>"
514 " <key>Caucasus</key> <string>Asia/Yerevan</string>"
515 " <key>Caucasus Standard Time</key> <string>Asia/Yerevan</string>"
516 " <key>Cen. Australia</key> <string>Australia/Adelaide</string>"
517 " <key>Cen. Australia Standard Time</key> <string>Australia/Adelaide</string>"
518 " <key>Central</key> <string>America/Chicago</string>"
519 " <key>Central America Standard Time</key> <string>America/Regina</string>"
520 " <key>Central Asia</key> <string>Asia/Dhaka</string>"
521 " <key>Central Asia Standard Time</key> <string>Asia/Dhaka</string>"
522 " <key>Central Brazilian Standard Time</key> <string>America/Manaus</string>"
523 " <key>Central Europe</key> <string>Europe/Prague</string>"
524 " <key>Central Europe Standard Time</key> <string>Europe/Prague</string>"
525 " <key>Central European</key> <string>Europe/Belgrade</string>"
526 " <key>Central European Standard Time</key> <string>Europe/Belgrade</string>"
527 " <key>Central Pacific</key> <string>Pacific/Guadalcanal</string>"
528 " <key>Central Pacific Standard Time</key> <string>Pacific/Guadalcanal</string>"
529 " <key>Central Standard Time</key> <string>America/Chicago</string>"
530 " <key>Central Standard Time (Mexico)</key> <string>America/Mexico_City</string>"
531 " <key>China</key> <string>Asia/Shanghai</string>"
532 " <key>China Standard Time</key> <string>Asia/Shanghai</string>"
533 " <key>Dateline</key> <string>GMT-1200</string>"
534 " <key>Dateline Standard Time</key> <string>GMT-1200</string>"
535 " <key>E. Africa</key> <string>Africa/Nairobi</string>"
536 " <key>E. Africa Standard Time</key> <string>Africa/Nairobi</string>"
537 " <key>E. Australia</key> <string>Australia/Brisbane</string>"
538 " <key>E. Australia Standard Time</key> <string>Australia/Brisbane</string>"
539 " <key>E. Europe</key> <string>Europe/Minsk</string>"
540 " <key>E. Europe Standard Time</key> <string>Europe/Minsk</string>"
541 " <key>E. South America</key> <string>America/Sao_Paulo</string>"
542 " <key>E. South America Standard Time</key> <string>America/Sao_Paulo</string>"
543 " <key>Eastern</key> <string>America/New_York</string>"
544 " <key>Eastern Standard Time</key> <string>America/New_York</string>"
545 " <key>Egypt</key> <string>Africa/Cairo</string>"
546 " <key>Egypt Standard Time</key> <string>Africa/Cairo</string>"
547 " <key>Ekaterinburg</key> <string>Asia/Yekaterinburg</string>"
548 " <key>Ekaterinburg Standard Time</key> <string>Asia/Yekaterinburg</string>"
549 " <key>Fiji</key> <string>Pacific/Fiji</string>"
550 " <key>Fiji Standard Time</key> <string>Pacific/Fiji</string>"
551 " <key>FLE</key> <string>Europe/Helsinki</string>"
552 " <key>FLE Standard Time</key> <string>Europe/Helsinki</string>"
553 " <key>Georgian Standard Time</key> <string>Asia/Tbilisi</string>"
554 " <key>GFT</key> <string>Europe/Athens</string>"
555 " <key>GFT Standard Time</key> <string>Europe/Athens</string>"
556 " <key>GMT</key> <string>Europe/London</string>"
557 " <key>GMT Standard Time</key> <string>Europe/London</string>"
558 " <key>Greenland Standard Time</key> <string>America/Godthab</string>"
559 " <key>Greenwich</key> <string>GMT</string>"
560 " <key>Greenwich Standard Time</key> <string>GMT</string>"
561 " <key>GTB</key> <string>Europe/Athens</string>"
562 " <key>GTB Standard Time</key> <string>Europe/Athens</string>"
563 " <key>Hawaiian</key> <string>Pacific/Honolulu</string>"
564 " <key>Hawaiian Standard Time</key> <string>Pacific/Honolulu</string>"
565 " <key>India</key> <string>Asia/Calcutta</string>"
566 " <key>India Standard Time</key> <string>Asia/Calcutta</string>"
567 " <key>Iran</key> <string>Asia/Tehran</string>"
568 " <key>Iran Standard Time</key> <string>Asia/Tehran</string>"
569 " <key>Israel</key> <string>Asia/Jerusalem</string>"
570 " <key>Israel Standard Time</key> <string>Asia/Jerusalem</string>"
571 " <key>Jordan Standard Time</key> <string>Asia/Amman</string>"
572 " <key>Korea</key> <string>Asia/Seoul</string>"
573 " <key>Korea Standard Time</key> <string>Asia/Seoul</string>"
574 " <key>Mexico</key> <string>America/Mexico_City</string>"
575 " <key>Mexico Standard Time</key> <string>America/Mexico_City</string>"
576 " <key>Mexico Standard Time 2</key> <string>America/Chihuahua</string>"
577 " <key>Mid-Atlantic</key> <string>Atlantic/South_Georgia</string>"
578 " <key>Mid-Atlantic Standard Time</key> <string>Atlantic/South_Georgia</string>"
579 " <key>Middle East Standard Time</key> <string>Asia/Beirut</string>"
580 " <key>Mountain</key> <string>America/Denver</string>"
581 " <key>Mountain Standard Time</key> <string>America/Denver</string>"
582 " <key>Mountain Standard Time (Mexico)</key> <string>America/Chihuahua</string>"
583 " <key>Myanmar Standard Time</key> <string>Asia/Rangoon</string>"
584 " <key>N. Central Asia Standard Time</key> <string>Asia/Novosibirsk</string>"
585 " <key>Namibia Standard Time</key> <string>Africa/Windhoek</string>"
586 " <key>Nepal Standard Time</key> <string>Asia/Katmandu</string>"
587 " <key>New Zealand</key> <string>Pacific/Auckland</string>"
588 " <key>New Zealand Standard Time</key> <string>Pacific/Auckland</string>"
589 " <key>Newfoundland</key> <string>America/St_Johns</string>"
590 " <key>Newfoundland Standard Time</key> <string>America/St_Johns</string>"
591 " <key>North Asia East Standard Time</key> <string>Asia/Ulaanbaatar</string>"
592 " <key>North Asia Standard Time</key> <string>Asia/Krasnoyarsk</string>"
593 " <key>Pacific</key> <string>America/Los_Angeles</string>"
594 " <key>Pacific SA</key> <string>America/Santiago</string>"
595 " <key>Pacific SA Standard Time</key> <string>America/Santiago</string>"
596 " <key>Pacific Standard Time</key> <string>America/Los_Angeles</string>"
597 " <key>Pacific Standard Time (Mexico)</key> <string>America/Tijuana</string>"
598 " <key>Prague Bratislava</key> <string>Europe/Prague</string>"
599 " <key>Romance</key> <string>Europe/Paris</string>"
600 " <key>Romance Standard Time</key> <string>Europe/Paris</string>"
601 " <key>Russian</key> <string>Europe/Moscow</string>"
602 " <key>Russian Standard Time</key> <string>Europe/Moscow</string>"
603 " <key>SA Eastern</key> <string>America/Buenos_Aires</string>"
604 " <key>SA Eastern Standard Time</key> <string>America/Buenos_Aires</string>"
605 " <key>SA Pacific</key> <string>America/Bogota</string>"
606 " <key>SA Pacific Standard Time</key> <string>America/Bogota</string>"
607 " <key>SA Western</key> <string>America/Caracas</string>"
608 " <key>SA Western Standard Time</key> <string>America/Caracas</string>"
609 " <key>Samoa</key> <string>Pacific/Apia</string>"
610 " <key>Samoa Standard Time</key> <string>Pacific/Apia</string>"
611 " <key>Saudi Arabia</key> <string>Asia/Riyadh</string>"
612 " <key>Saudi Arabia Standard Time</key> <string>Asia/Riyadh</string>"
613 " <key>SE Asia Standard Time</key> <string>Asia/Bangkok</string>"
614 " <key>Singapore</key> <string>Asia/Singapore</string>"
615 " <key>Singapore Standard Time</key> <string>Asia/Singapore</string>"
616 " <key>South Africa</key> <string>Africa/Harare</string>"
617 " <key>South Africa Standard Time</key> <string>Africa/Harare</string>"
618 " <key>Sri Lanka</key> <string>Asia/Colombo</string>"
619 " <key>Sri Lanka Standard Time</key> <string>Asia/Colombo</string>"
620 " <key>Sydney Standard Time</key> <string>Australia/Sydney</string>"
621 " <key>Taipei</key> <string>Asia/Taipei</string>"
622 " <key>Taipei Standard Time</key> <string>Asia/Taipei</string>"
623 " <key>Tasmania</key> <string>Australia/Hobart</string>"
624 " <key>Tasmania Standard Time</key> <string>Australia/Hobart</string>"
625 " <key>Tasmania Standard Time</key> <string>Australia/Hobart</string>"
626 " <key>Tokyo</key> <string>Asia/Tokyo</string>"
627 " <key>Tokyo Standard Time</key> <string>Asia/Tokyo</string>"
628 " <key>Tonga Standard Time</key> <string>Pacific/Tongatapu</string>"
629 " <key>US Eastern</key> <string>America/Indianapolis</string>"
630 " <key>US Eastern Standard Time</key> <string>America/Indianapolis</string>"
631 " <key>US Mountain</key> <string>America/Phoenix</string>"
632 " <key>US Mountain Standard Time</key> <string>America/Phoenix</string>"
633 " <key>Vladivostok</key> <string>Asia/Vladivostok</string>"
634 " <key>Vladivostok Standard Time</key> <string>Asia/Vladivostok</string>"
635 " <key>W. Australia</key> <string>Australia/Perth</string>"
636 " <key>W. Australia Standard Time</key> <string>Australia/Perth</string>"
637 " <key>W. Central Africa Standard Time</key> <string>Africa/Luanda</string>"
638 " <key>W. Europe</key> <string>Europe/Berlin</string>"
639 " <key>W. Europe Standard Time</key> <string>Europe/Berlin</string>"
640 " <key>Warsaw</key> <string>Europe/Warsaw</string>"
641 " <key>West Asia</key> <string>Asia/Karachi</string>"
642 " <key>West Asia Standard Time</key> <string>Asia/Karachi</string>"
643 " <key>West Pacific</key> <string>Pacific/Guam</string>"
644 " <key>West Pacific Standard Time</key> <string>Pacific/Guam</string>"
645 " <key>Western Brazilian Standard Time</key> <string>America/Rio_Branco</string>"
646 " <key>Yakutsk</key> <string>Asia/Yakutsk</string>"
650 CF_INLINE
void __CFTimeZoneLockWinToOlson(void) {
651 __CFSpinLock(&__CFTimeZoneWinToOlsonLock
);
654 CF_INLINE
void __CFTimeZoneUnlockWinToOlson(void) {
655 __CFSpinUnlock(&__CFTimeZoneWinToOlsonLock
);
658 CFDictionaryRef
CFTimeZoneCopyWinToOlsonDictionary(void) {
659 CFDictionaryRef dict
;
660 __CFTimeZoneLockWinToOlson();
661 if (NULL
== __CFTimeZoneWinToOlsonDict
) {
662 CFDataRef data
= CFDataCreate(kCFAllocatorSystemDefault
, (uint8_t *)__CFTimeZoneWinToOlsonDefaults
, strlen(__CFTimeZoneWinToOlsonDefaults
));
663 __CFTimeZoneWinToOlsonDict
= (CFDictionaryRef
)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault
, data
, kCFPropertyListImmutable
, NULL
);
666 if (NULL
== __CFTimeZoneWinToOlsonDict
) {
667 __CFTimeZoneWinToOlsonDict
= CFDictionaryCreate(kCFAllocatorSystemDefault
, NULL
, NULL
, 0, NULL
, NULL
);
669 dict
= __CFTimeZoneWinToOlsonDict
? (CFDictionaryRef
)CFRetain(__CFTimeZoneWinToOlsonDict
) : NULL
;
670 __CFTimeZoneUnlockWinToOlson();
674 void CFTimeZoneSetWinToOlsonDictionary(CFDictionaryRef dict
) {
675 __CFGenericValidateType(dict
, CFDictionaryGetTypeID());
676 __CFTimeZoneLockWinToOlson();
677 if (dict
!= __CFTimeZoneWinToOlsonDict
) {
678 if (dict
) CFRetain(dict
);
679 if (__CFTimeZoneWinToOlsonDict
) CFRelease(__CFTimeZoneWinToOlsonDict
);
680 __CFTimeZoneWinToOlsonDict
= dict
;
682 __CFTimeZoneUnlockWinToOlson();
685 CFTimeZoneRef
CFTimeZoneCreateWithWindowsName(CFAllocatorRef allocator
, CFStringRef winName
) {
686 if (!winName
) return NULL
;
688 CFDictionaryRef winToOlson
= CFTimeZoneCopyWinToOlsonDictionary();
689 if (!winToOlson
) return NULL
;
691 CFStringRef olsonName
= CFDictionaryGetValue(winToOlson
, winName
);
692 CFTimeZoneRef retval
= NULL
;
694 retval
= CFTimeZoneCreateWithName(allocator
, olsonName
, false);
696 CFRelease(winToOlson
);
700 extern CFStringRef
_CFGetWindowsAppleSystemLibraryDirectory(void);
701 void __InitTZStrings(void) {
702 static CFSpinLock_t __CFTZDirLock
= CFSpinLockInit
;
703 __CFSpinLock(&__CFTZDirLock
);
705 CFStringRef winDir
= _CFGetWindowsAppleSystemLibraryDirectory();
706 __tzZoneInfo
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@\\etc\\zoneinfo"), winDir
);
708 if (!__tzDir
&& __tzZoneInfo
) {
709 int length
= CFStringGetLength(__tzZoneInfo
) + sizeof("\\zone.tab") + 1;
710 __tzDir
= malloc(length
); // If we don't use ascii, we'll need to malloc more space
711 if (!__tzDir
|| !CFStringGetCString(__tzZoneInfo
, __tzDir
, length
, kCFStringEncodingASCII
)) {
714 strcat(__tzDir
, "\\zone.tab");
717 __CFSpinUnlock(&__CFTZDirLock
);
721 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
722 static CFTimeZoneRef
__CFTimeZoneCreateSystem(void) {
723 CFTimeZoneRef result
= NULL
;
725 #if DEPLOYMENT_TARGET_WINDOWS_SYNC
726 CFStringRef name
= NULL
;
727 TIME_ZONE_INFORMATION tzi
= { 0 };
728 DWORD rval
= GetTimeZoneInformation(&tzi
);
729 if (rval
!= TIME_ZONE_ID_INVALID
) {
730 LPWSTR standardName
= (LPWSTR
)&tzi
.StandardName
;
731 CFStringRef cfStandardName
= CFStringCreateWithBytes(kCFAllocatorSystemDefault
, (UInt8
*)standardName
, wcslen(standardName
)*sizeof(WCHAR
), kCFStringEncodingUTF16LE
, false);
732 if (cfStandardName
) {
733 CFDictionaryRef winToOlson
= CFTimeZoneCopyWinToOlsonDictionary();
735 name
= CFDictionaryGetValue(winToOlson
, cfStandardName
);
736 if (name
) CFRetain(name
);
737 CFRelease(winToOlson
);
739 CFRelease(cfStandardName
);
742 CFLog(kCFLogLevelError
, CFSTR("Couldn't get time zone information error %d"), GetLastError());
748 char linkbuf
[CFMaxPathSize
];
750 tzenv
= __CFgetenv("TZFILE");
752 CFStringRef name
= CFStringCreateWithBytes(kCFAllocatorSystemDefault
, (uint8_t *)tzenv
, strlen(tzenv
), kCFStringEncodingUTF8
, false);
753 result
= CFTimeZoneCreateWithName(kCFAllocatorSystemDefault
, name
, false);
755 if (result
) return result
;
757 tzenv
= __CFgetenv("TZ");
759 CFStringRef name
= CFStringCreateWithBytes(kCFAllocatorSystemDefault
, (uint8_t *)tzenv
, strlen(tzenv
), kCFStringEncodingUTF8
, false);
760 result
= CFTimeZoneCreateWithName(kCFAllocatorSystemDefault
, name
, true);
762 if (result
) return result
;
764 ret
= readlink(TZZONELINK
, linkbuf
, sizeof(linkbuf
));
768 if (strncmp(linkbuf
, TZZONEINFO
, sizeof(TZZONEINFO
) - 1) == 0) {
769 name
= CFStringCreateWithBytes(kCFAllocatorSystemDefault
, (uint8_t *)linkbuf
+ sizeof(TZZONEINFO
) - 1, strlen(linkbuf
) - sizeof(TZZONEINFO
) + 1, kCFStringEncodingUTF8
, false);
771 name
= CFStringCreateWithBytes(kCFAllocatorSystemDefault
, (uint8_t *)linkbuf
, strlen(linkbuf
), kCFStringEncodingUTF8
, false);
775 result
= CFTimeZoneCreateWithName(kCFAllocatorSystemDefault
, name
, false);
777 if (result
) return result
;
779 return CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorSystemDefault
, 0.0);
781 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
782 static CFTimeZoneRef
__CFTimeZoneCreateSystem(void) {
783 CFTimeZoneRef result
= NULL
;
784 /* The GetTimeZoneInformation function retrieves the current
785 * time-zone parameters for Win32
786 * (Aleksey Dukhnyakov)
789 TIME_ZONE_INFORMATION tz
;
791 dw_result
=GetTimeZoneInformation(&tz
);
793 if ( dw_result
== TIME_ZONE_ID_STANDARD
||
794 dw_result
== TIME_ZONE_ID_DAYLIGHT
) {
795 CFStringRef name
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (const UniChar
*)tz
.StandardName
, wcslen(tz
.StandardName
));
796 data
= CFDataCreate(kCFAllocatorSystemDefault
, (UInt8
*)&tz
, sizeof(tz
));
797 result
= CFTimeZoneCreate(kCFAllocatorSystemDefault
, name
, data
);
800 if (result
) return result
;
802 return CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorSystemDefault
, 0.0);
805 #error Unknown or unspecified DEPLOYMENT_TARGET
808 CFTimeZoneRef
CFTimeZoneCopySystem(void) {
810 __CFTimeZoneLockGlobal();
811 if (NULL
== __CFTimeZoneSystem
) {
812 __CFTimeZoneUnlockGlobal();
813 tz
= __CFTimeZoneCreateSystem();
814 __CFTimeZoneLockGlobal();
815 if (NULL
== __CFTimeZoneSystem
) {
816 __CFTimeZoneSystem
= tz
;
818 if (tz
) CFRelease(tz
);
821 tz
= __CFTimeZoneSystem
? (CFTimeZoneRef
)CFRetain(__CFTimeZoneSystem
) : NULL
;
822 __CFTimeZoneUnlockGlobal();
826 static CFIndex __noteCount
= 0;
828 void CFTimeZoneResetSystem(void) {
829 __CFTimeZoneLockGlobal();
830 if (__CFTimeZoneDefault
== __CFTimeZoneSystem
) {
831 if (__CFTimeZoneDefault
) CFRelease(__CFTimeZoneDefault
);
832 __CFTimeZoneDefault
= NULL
;
834 CFTimeZoneRef tz
= __CFTimeZoneSystem
;
835 __CFTimeZoneSystem
= NULL
;
836 __CFTimeZoneUnlockGlobal();
837 if (tz
) CFRelease(tz
);
840 CFIndex
_CFTimeZoneGetNoteCount(void) {
844 CFTimeZoneRef
CFTimeZoneCopyDefault(void) {
846 __CFTimeZoneLockGlobal();
847 if (NULL
== __CFTimeZoneDefault
) {
848 __CFTimeZoneUnlockGlobal();
849 tz
= CFTimeZoneCopySystem();
850 __CFTimeZoneLockGlobal();
851 if (NULL
== __CFTimeZoneDefault
) {
852 __CFTimeZoneDefault
= tz
;
854 if (tz
) CFRelease(tz
);
857 tz
= __CFTimeZoneDefault
? (CFTimeZoneRef
)CFRetain(__CFTimeZoneDefault
) : NULL
;
858 __CFTimeZoneUnlockGlobal();
862 void CFTimeZoneSetDefault(CFTimeZoneRef tz
) {
863 if (tz
) __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
864 __CFTimeZoneLockGlobal();
865 if (tz
!= __CFTimeZoneDefault
) {
866 if (tz
) CFRetain(tz
);
867 if (__CFTimeZoneDefault
) CFRelease(__CFTimeZoneDefault
);
868 __CFTimeZoneDefault
= tz
;
870 __CFTimeZoneUnlockGlobal();
873 static CFDictionaryRef
__CFTimeZoneCopyCompatibilityDictionary(void);
875 CFArrayRef
CFTimeZoneCopyKnownNames(void) {
877 __CFTimeZoneLockGlobal();
878 if (NULL
== __CFKnownTimeZoneList
) {
879 CFMutableArrayRef list
;
880 /* TimeZone information locate in the registry for Win32
881 * (Aleksey Dukhnyakov)
883 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
884 list
= __CFCopyRecursiveDirectoryList();
885 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
886 list
= __CFCopyWindowsTimeZoneList();
888 #error Unknown or unspecified DEPLOYMENT_TARGET
890 // Remove undesirable ancient cruft
891 CFDictionaryRef dict
= __CFTimeZoneCopyCompatibilityDictionary();
893 for (idx
= CFArrayGetCount(list
); idx
--; ) {
894 CFStringRef item
= (CFStringRef
)CFArrayGetValueAtIndex(list
, idx
);
895 if (CFDictionaryContainsKey(dict
, item
)) {
896 CFArrayRemoveValueAtIndex(list
, idx
);
899 __CFKnownTimeZoneList
= CFArrayCreateCopy(kCFAllocatorSystemDefault
, list
);
902 tzs
= __CFKnownTimeZoneList
? (CFArrayRef
)CFRetain(__CFKnownTimeZoneList
) : NULL
;
903 __CFTimeZoneUnlockGlobal();
907 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
908 /* The criteria here are sort of: coverage for the U.S. and Europe,
909 * large cities, abbreviation uniqueness, and perhaps a few others.
910 * But do not make the list too large with obscure information.
912 static const char *__CFTimeZoneAbbreviationDefaults
=
913 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
914 " <!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">"
915 " <plist version=\"1.0\">"
917 " <key>ADT</key> <string>America/Halifax</string>"
918 " <key>AKDT</key> <string>America/Juneau</string>"
919 " <key>AKST</key> <string>America/Juneau</string>"
920 " <key>ART</key> <string>America/Argentina/Buenos_Aires</string>"
921 " <key>AST</key> <string>America/Halifax</string>"
922 " <key>BDT</key> <string>Asia/Dhaka</string>"
923 " <key>BRST</key> <string>America/Sao_Paulo</string>"
924 " <key>BRT</key> <string>America/Sao_Paulo</string>"
925 " <key>BST</key> <string>Europe/London</string>"
926 " <key>CAT</key> <string>Africa/Harare</string>"
927 " <key>CDT</key> <string>America/Chicago</string>"
928 " <key>CEST</key> <string>Europe/Paris</string>"
929 " <key>CET</key> <string>Europe/Paris</string>"
930 " <key>CLST</key> <string>America/Santiago</string>"
931 " <key>CLT</key> <string>America/Santiago</string>"
932 " <key>COT</key> <string>America/Bogota</string>"
933 " <key>CST</key> <string>America/Chicago</string>"
934 " <key>EAT</key> <string>Africa/Addis_Ababa</string>"
935 " <key>EDT</key> <string>America/New_York</string>"
936 " <key>EEST</key> <string>Europe/Istanbul</string>"
937 " <key>EET</key> <string>Europe/Istanbul</string>"
938 " <key>EST</key> <string>America/New_York</string>"
939 " <key>GMT</key> <string>GMT</string>"
940 " <key>GST</key> <string>Asia/Dubai</string>"
941 " <key>HKT</key> <string>Asia/Hong_Kong</string>"
942 " <key>HST</key> <string>Pacific/Honolulu</string>"
943 " <key>ICT</key> <string>Asia/Bangkok</string>"
944 " <key>IRST</key> <string>Asia/Tehran</string>"
945 " <key>IST</key> <string>Asia/Calcutta</string>"
946 " <key>JST</key> <string>Asia/Tokyo</string>"
947 " <key>KST</key> <string>Asia/Seoul</string>"
948 " <key>MDT</key> <string>America/Denver</string>"
949 " <key>MSD</key> <string>Europe/Moscow</string>"
950 " <key>MSK</key> <string>Europe/Moscow</string>"
951 " <key>MST</key> <string>America/Denver</string>"
952 " <key>NZDT</key> <string>Pacific/Auckland</string>"
953 " <key>NZST</key> <string>Pacific/Auckland</string>"
954 " <key>PDT</key> <string>America/Los_Angeles</string>"
955 " <key>PET</key> <string>America/Lima</string>"
956 " <key>PHT</key> <string>Asia/Manila</string>"
957 " <key>PKT</key> <string>Asia/Karachi</string>"
958 " <key>PST</key> <string>America/Los_Angeles</string>"
959 " <key>SGT</key> <string>Asia/Singapore</string>"
960 " <key>UTC</key> <string>UTC</string>"
961 " <key>WAT</key> <string>Africa/Lagos</string>"
962 " <key>WEST</key> <string>Europe/Lisbon</string>"
963 " <key>WET</key> <string>Europe/Lisbon</string>"
964 " <key>WIT</key> <string>Asia/Jakarta</string>"
967 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
968 static const char *__CFTimeZoneAbbreviationDefaults
=
969 /* Mappings to time zones in Windows Registry are best-guess */
970 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
971 " <!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">"
972 " <plist version=\"1.0\">"
974 " <key>ADT</key> <string>Atlantic Standard Time</string>"
975 " <key>AKDT</key> <string>Alaskan Standard Time</string>"
976 " <key>AKST</key> <string>Alaskan Standard Time</string>"
977 " <key>ART</key> <string>SA Eastern Standard Time</string>"
978 " <key>AST</key> <string>Atlantic Standard Time</string>"
979 " <key>BDT</key> <string>Central Asia Standard Time</string>"
980 " <key>BRST</key> <string>SA Eastern Standard Time</string>"
981 " <key>BRT</key> <string>SA Eastern Standard Time</string>"
982 " <key>BST</key> <string>GMT Standard Time</string>"
983 " <key>CAT</key> <string>South Africa Standard Time</string>"
984 " <key>CDT</key> <string>Central Standard Time</string>"
985 " <key>CEST</key> <string>Central Europe Standard Time</string>"
986 " <key>CET</key> <string>Central Europe Standard Time</string>"
987 " <key>CLST</key> <string>SA Western Standard Time</string>"
988 " <key>CLT</key> <string>SA Western Standard Time</string>"
989 " <key>COT</key> <string>Central Standard Time</string>"
990 " <key>CST</key> <string>Central Standard Time</string>"
991 " <key>EAT</key> <string>E. Africa Standard Time</string>"
992 " <key>EDT</key> <string>Eastern Standard Time</string>"
993 " <key>EEST</key> <string>E. Europe Standard Time</string>"
994 " <key>EET</key> <string>E. Europe Standard Time</string>"
995 " <key>EST</key> <string>Eastern Standard Time</string>"
996 " <key>GMT</key> <string>Greenwich Standard Time</string>"
997 " <key>GST</key> <string>Arabian Standard Time</string>"
998 " <key>HKT</key> <string>China Standard Time</string>"
999 " <key>HST</key> <string>Hawaiian Standard Time</string>"
1000 " <key>ICT</key> <string>SE Asia Standard Time</string>"
1001 " <key>IRST</key> <string>Iran Standard Time</string>"
1002 " <key>IST</key> <string>India Standard Time</string>"
1003 " <key>JST</key> <string>Tokyo Standard Time</string>"
1004 " <key>KST</key> <string>Korea Standard Time</string>"
1005 " <key>MDT</key> <string>Mountain Standard Time</string>"
1006 " <key>MSD</key> <string>E. Europe Standard Time</string>"
1007 " <key>MSK</key> <string>E. Europe Standard Time</string>"
1008 " <key>MST</key> <string>Mountain Standard Time</string>"
1009 " <key>NZDT</key> <string>New Zealand Standard Time</string>"
1010 " <key>NZST</key> <string>New Zealand Standard Time</string>"
1011 " <key>PDT</key> <string>Pacific Standard Time</string>"
1012 " <key>PET</key> <string>SA Pacific Standard Time</string>"
1013 " <key>PHT</key> <string>Taipei Standard Time</string>"
1014 " <key>PKT</key> <string>West Asia Standard Time</string>"
1015 " <key>PST</key> <string>Pacific Standard Time</string>"
1016 " <key>SGT</key> <string>Singapore Standard Time</string>"
1017 " <key>UTC</key> <string>Greenwich Standard Time</string>"
1018 " <key>WAT</key> <string>W. Central Africa Standard Time</string>"
1019 " <key>WEST</key> <string>W. Europe Standard Time</string>"
1020 " <key>WET</key> <string>W. Europe Standard Time</string>"
1021 " <key>WIT</key> <string>SE Asia Standard Time</string>"
1025 #error Unknown or unspecified DEPLOYMENT_TARGET
1028 CFDictionaryRef
CFTimeZoneCopyAbbreviationDictionary(void) {
1029 CFDictionaryRef dict
;
1030 __CFTimeZoneLockAbbreviations();
1031 if (NULL
== __CFTimeZoneAbbreviationDict
) {
1032 CFDataRef data
= CFDataCreate(kCFAllocatorSystemDefault
, (uint8_t *)__CFTimeZoneAbbreviationDefaults
, strlen(__CFTimeZoneAbbreviationDefaults
));
1033 __CFTimeZoneAbbreviationDict
= (CFDictionaryRef
)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault
, data
, kCFPropertyListImmutable
, NULL
);
1036 if (NULL
== __CFTimeZoneAbbreviationDict
) {
1037 __CFTimeZoneAbbreviationDict
= CFDictionaryCreate(kCFAllocatorSystemDefault
, NULL
, NULL
, 0, NULL
, NULL
);
1039 dict
= __CFTimeZoneAbbreviationDict
? (CFDictionaryRef
)CFRetain(__CFTimeZoneAbbreviationDict
) : NULL
;
1040 __CFTimeZoneUnlockAbbreviations();
1044 void CFTimeZoneSetAbbreviationDictionary(CFDictionaryRef dict
) {
1045 __CFGenericValidateType(dict
, CFDictionaryGetTypeID());
1046 __CFTimeZoneLockGlobal();
1047 if (dict
!= __CFTimeZoneAbbreviationDict
) {
1048 if (dict
) CFRetain(dict
);
1049 if (__CFTimeZoneAbbreviationDict
) {
1050 for (id key
in (id
)__CFTimeZoneAbbreviationDict
) {
1051 CFDictionaryRemoveValue(__CFTimeZoneCache
, (CFStringRef
)key
);
1053 CFRelease(__CFTimeZoneAbbreviationDict
);
1055 __CFTimeZoneAbbreviationDict
= dict
;
1057 __CFTimeZoneUnlockGlobal();
1060 CFTimeZoneRef
CFTimeZoneCreate(CFAllocatorRef allocator
, CFStringRef name
, CFDataRef data
) {
1061 // assert: (NULL != name && NULL != data);
1062 CFTimeZoneRef memory
;
1064 CFTZPeriod
*tzp
= NULL
;
1065 CFIndex idx
, cnt
= 0;
1067 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
1068 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
1069 __CFGenericValidateType(name
, CFStringGetTypeID());
1070 __CFGenericValidateType(data
, CFDataGetTypeID());
1071 __CFTimeZoneLockGlobal();
1072 if (NULL
!= __CFTimeZoneCache
&& CFDictionaryGetValueIfPresent(__CFTimeZoneCache
, name
, (const void **)&memory
)) {
1073 __CFTimeZoneUnlockGlobal();
1074 return (CFTimeZoneRef
)CFRetain(memory
);
1076 if (!__CFParseTimeZoneData(allocator
, data
, &tzp
, &cnt
)) {
1077 __CFTimeZoneUnlockGlobal();
1080 size
= sizeof(struct __CFTimeZone
) - sizeof(CFRuntimeBase
);
1081 memory
= (CFTimeZoneRef
)_CFRuntimeCreateInstance(allocator
, CFTimeZoneGetTypeID(), size
, NULL
);
1082 if (NULL
== memory
) {
1083 __CFTimeZoneUnlockGlobal();
1084 for (idx
= 0; idx
< cnt
; idx
++) {
1085 if (NULL
!= tzp
[idx
].abbrev
) CFRelease(tzp
[idx
].abbrev
);
1087 if (NULL
!= tzp
) CFAllocatorDeallocate(allocator
, tzp
);
1090 ((struct __CFTimeZone
*)memory
)->_name
= (CFStringRef
)CFStringCreateCopy(allocator
, name
);
1091 ((struct __CFTimeZone
*)memory
)->_data
= CFDataCreateCopy(allocator
, data
);
1092 ((struct __CFTimeZone
*)memory
)->_periods
= tzp
;
1093 ((struct __CFTimeZone
*)memory
)->_periodCnt
= cnt
;
1094 if (NULL
== __CFTimeZoneCache
) {
1095 __CFTimeZoneCache
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
1097 CFDictionaryAddValue(__CFTimeZoneCache
, ((struct __CFTimeZone
*)memory
)->_name
, memory
);
1098 __CFTimeZoneUnlockGlobal();
1102 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
1103 static CFTimeZoneRef
__CFTimeZoneCreateFixed(CFAllocatorRef allocator
, int32_t seconds
, CFStringRef name
, int isDST
) {
1104 CFTimeZoneRef result
;
1106 int32_t nameLen
= CFStringGetLength(name
);
1107 unsigned char dataBytes
[52 + nameLen
+ 1];
1108 memset(dataBytes
, 0, sizeof(dataBytes
));
1110 // Put in correct magic bytes for timezone structures
1116 __CFEntzcode(1, dataBytes
+ 20);
1117 __CFEntzcode(1, dataBytes
+ 24);
1118 __CFEntzcode(1, dataBytes
+ 36);
1119 __CFEntzcode(nameLen
+ 1, dataBytes
+ 40);
1120 __CFEntzcode(seconds
, dataBytes
+ 44);
1121 dataBytes
[48] = isDST
? 1 : 0;
1122 CFStringGetCString(name
, (char *)dataBytes
+ 50, nameLen
+ 1, kCFStringEncodingASCII
);
1123 data
= CFDataCreate(allocator
, dataBytes
, 52 + nameLen
+ 1);
1124 result
= CFTimeZoneCreate(allocator
, name
, data
);
1128 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
1129 static CFTimeZoneRef
__CFTimeZoneCreateFixed(CFAllocatorRef allocator
, int32_t seconds
, CFStringRef name
, int isDST
) {
1130 /* CFTimeZoneRef->_data will contain TIME_ZONE_INFORMATION structure
1131 * to find current timezone
1132 * (Aleksey Dukhnyakov)
1134 CFTimeZoneRef result
;
1135 TIME_ZONE_INFORMATION tzi
;
1137 CFIndex length
= CFStringGetLength(name
);
1139 memset(&tzi
,0,sizeof(tzi
));
1140 tzi
.Bias
=(long)(-seconds
/60);
1141 CFStringGetCharacters(name
, CFRangeMake(0, length
< 31 ? length
: 31 ), (UniChar
*)tzi
.StandardName
);
1142 data
= CFDataCreate(allocator
,(UInt8
*)&tzi
, sizeof(tzi
));
1143 result
= CFTimeZoneCreate(allocator
, name
, data
);
1148 #error Unknown or unspecified DEPLOYMENT_TARGET
1151 // rounds offset to nearest minute
1152 CFTimeZoneRef
CFTimeZoneCreateWithTimeIntervalFromGMT(CFAllocatorRef allocator
, CFTimeInterval ti
) {
1153 CFTimeZoneRef result
;
1155 int32_t seconds
, minute
, hour
;
1156 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
1157 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
1158 if (ti
< -18.0 * 3600 || 18.0 * 3600 < ti
) return NULL
;
1159 ti
= (ti
< 0.0) ? ceil((ti
/ 60.0) - 0.5) * 60.0 : floor((ti
/ 60.0) + 0.5) * 60.0;
1160 seconds
= (int32_t)ti
;
1161 hour
= (ti
< 0) ? (-seconds
/ 3600) : (seconds
/ 3600);
1162 seconds
-= ((ti
< 0) ? -hour
: hour
) * 3600;
1163 minute
= (ti
< 0) ? (-seconds
/ 60) : (seconds
/ 60);
1164 if (fabs(ti
) < 1.0) {
1165 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
1166 name
= (CFStringRef
)CFRetain(CFSTR("GMT"));
1167 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
1168 name
= (CFStringRef
)CFRetain(CFSTR("Greenwich Standard Time"));
1170 #error Unknown or unspecified DEPLOYMENT_TARGET
1173 name
= CFStringCreateWithFormat(allocator
, NULL
, CFSTR("GMT%c%02d%02d"), (ti
< 0.0 ? '-' : '+'), hour
, minute
);
1175 result
= __CFTimeZoneCreateFixed(allocator
, (int32_t)ti
, name
, 0);
1180 CFTimeZoneRef
CFTimeZoneCreateWithName(CFAllocatorRef allocator
, CFStringRef name
, Boolean tryAbbrev
) {
1181 CFTimeZoneRef result
= NULL
;
1182 CFStringRef tzName
= NULL
;
1183 CFDataRef data
= NULL
;
1185 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
1186 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
1187 __CFGenericValidateType(name
, CFStringGetTypeID());
1188 if (CFEqual(CFSTR(""), name
)) {
1189 // empty string is not a time zone name, just abort now,
1190 // following stuff will fail anyway
1193 __CFTimeZoneLockGlobal();
1194 if (NULL
!= __CFTimeZoneCache
&& CFDictionaryGetValueIfPresent(__CFTimeZoneCache
, name
, (const void **)&result
)) {
1195 __CFTimeZoneUnlockGlobal();
1196 return (CFTimeZoneRef
)CFRetain(result
);
1198 __CFTimeZoneUnlockGlobal();
1199 CFIndex len
= CFStringGetLength(name
);
1200 if (6 == len
|| 8 == len
) {
1202 CFStringGetCharacters(name
, CFRangeMake(0, len
), buffer
);
1203 if ('G' == buffer
[0] && 'M' == buffer
[1] && 'T' == buffer
[2] && ('+' == buffer
[3] || '-' == buffer
[3])) {
1204 if (('0' <= buffer
[4] && buffer
[4] <= '9') && ('0' <= buffer
[5] && buffer
[5] <= '9')) {
1205 int32_t hours
= (buffer
[4] - '0') * 10 + (buffer
[5] - '0');
1206 if (-14 <= hours
&& hours
<= 14) {
1207 CFTimeInterval ti
= hours
* 3600.0;
1209 return CFTimeZoneCreateWithTimeIntervalFromGMT(allocator
, ('-' == buffer
[3] ? -1.0 : 1.0) * ti
);
1211 if (('0' <= buffer
[6] && buffer
[6] <= '9') && ('0' <= buffer
[7] && buffer
[7] <= '9')) {
1212 int32_t minutes
= (buffer
[6] - '0') * 10 + (buffer
[7] - '0');
1213 if ((-14 == hours
&& 0 == minutes
) || (14 == hours
&& 0 == minutes
) || (0 <= minutes
&& minutes
<= 59)) {
1214 ti
= ti
+ minutes
* 60.0;
1215 return CFTimeZoneCreateWithTimeIntervalFromGMT(allocator
, ('-' == buffer
[3] ? -1.0 : 1.0) * ti
);
1223 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
1224 CFURLRef baseURL
, tempURL
;
1228 #if DEPLOYMENT_TARGET_WINDOWS_SYNC
1229 if (!__tzZoneInfo
) __InitTZStrings();
1230 if (!__tzZoneInfo
) return NULL
;
1231 baseURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, __tzZoneInfo
, kCFURLWindowsPathStyle
, true);
1233 baseURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, CFSTR(TZZONEINFO
), kCFURLPOSIXPathStyle
, true);
1236 CFDictionaryRef abbrevs
= CFTimeZoneCopyAbbreviationDictionary();
1237 tzName
= CFDictionaryGetValue(abbrevs
, name
);
1238 if (NULL
!= tzName
) {
1239 tempURL
= CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault
, baseURL
, tzName
, false);
1240 if (NULL
!= tempURL
) {
1241 if (_CFReadBytesFromFile(kCFAllocatorSystemDefault
, tempURL
, &bytes
, &length
, 0)) {
1242 data
= CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault
, bytes
, length
, kCFAllocatorSystemDefault
);
1250 CFDictionaryRef dict
= __CFTimeZoneCopyCompatibilityDictionary();
1251 CFStringRef mapping
= CFDictionaryGetValue(dict
, name
);
1254 #if DEPLOYMENT_TARGET_WINDOWS_SYNC
1255 } else if (CFStringHasPrefix(name
, __tzZoneInfo
)) {
1256 CFMutableStringRef unprefixed
= CFStringCreateMutableCopy(kCFAllocatorSystemDefault
, CFStringGetLength(name
), name
);
1257 CFStringDelete(unprefixed
, CFRangeMake(0, CFStringGetLength(__tzZoneInfo
)));
1259 } else if (CFStringHasPrefix(name
, CFSTR(TZZONEINFO
))) {
1260 CFMutableStringRef unprefixed
= CFStringCreateMutableCopy(kCFAllocatorSystemDefault
, CFStringGetLength(name
), name
);
1261 CFStringDelete(unprefixed
, CFRangeMake(0, sizeof(TZZONEINFO
)));
1263 mapping
= CFDictionaryGetValue(dict
, unprefixed
);
1267 CFRelease(unprefixed
);
1270 if (CFEqual(CFSTR(""), name
)) {
1276 tempURL
= CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault
, baseURL
, tzName
, false);
1277 if (NULL
!= tempURL
) {
1278 if (_CFReadBytesFromFile(kCFAllocatorSystemDefault
, tempURL
, &bytes
, &length
, 0)) {
1279 data
= CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault
, bytes
, length
, kCFAllocatorSystemDefault
);
1286 result
= CFTimeZoneCreate(allocator
, tzName
, data
);
1287 if (name
!= tzName
) {
1288 CFStringRef nameCopy
= (CFStringRef
)CFStringCreateCopy(allocator
, name
);
1289 __CFTimeZoneLockGlobal();
1290 CFDictionaryAddValue(__CFTimeZoneCache
, nameCopy
, result
);
1291 __CFTimeZoneUnlockGlobal();
1292 CFRelease(nameCopy
);
1298 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
1299 /* Reading GMT offset and daylight flag from the registry
1301 * (Aleksey Dukhnyakov)
1304 CFStringRef safeName
= name
;
1309 SYSTEMTIME StandardDate
;
1310 SYSTEMTIME DaylightDate
;
1312 TIME_ZONE_INFORMATION tzi_system
;
1315 DWORD dwType
, dwSize
=sizeof(tzi
),
1316 dwSize_name1
=sizeof(tzi_system
.StandardName
),
1317 dwSize_name2
=sizeof(tzi_system
.DaylightName
);
1320 CFDictionaryRef abbrevs
= CFTimeZoneCopyAbbreviationDictionary();
1321 tzName
= (CFStringRef
)CFDictionaryGetValue(abbrevs
, name
);
1322 if (NULL
== tzName
) {
1330 /* Open regestry and move down to the TimeZone information
1332 if (RegOpenKey(HKEY_LOCAL_MACHINE
,_T(TZZONEINFO
),&hkResult
) !=
1336 /* Move down to specific TimeZone name
1338 #if defined(UNICODE)
1339 UniChar
*uniTimeZone
= (UniChar
*)CFStringGetCharactersPtr(name
);
1340 if (uniTimeZone
== NULL
) {
1341 // We need to extract the bytes out of the CFStringRef and create our own
1342 // UNICODE string to pass to the Win32 API - RegOpenKey.
1343 UInt8 uniBuff
[MAX_PATH
+2]; // adding +2 to handle Unicode-null termination /0/0.
1344 CFIndex usedBuff
= 0;
1345 CFIndex numChars
= CFStringGetBytes(name
, CFRangeMake(0, CFStringGetLength(name
)), kCFStringEncodingUnicode
, 0, FALSE
, uniBuff
, MAX_PATH
, &usedBuff
);
1346 if (numChars
== 0) {
1349 // NULL-terminate the newly created Unicode string.
1350 uniBuff
[usedBuff
] = '\0';
1351 uniBuff
[usedBuff
+1] = '\0';
1354 if (RegOpenKey(hkResult
, (LPCWSTR
)uniBuff
,&hkResult
) != ERROR_SUCCESS
) {
1358 if (RegOpenKey(hkResult
, (LPCWSTR
)uniTimeZone
,&hkResult
) != ERROR_SUCCESS
) {
1363 if (RegOpenKey(hkResult
,CFStringGetCStringPtr(name
, CFStringGetSystemEncoding()),&hkResult
) != ERROR_SUCCESS
) {
1368 /* TimeZone information(offsets, daylight flag, ...) assign to tzi structure
1370 if ( RegQueryValueEx(hkResult
,_T("TZI"),NULL
,&dwType
,(LPBYTE
)&tzi
,&dwSize
) != ERROR_SUCCESS
&&
1371 RegQueryValueEx(hkResult
,_T("Std"),NULL
,&dwType
,(LPBYTE
)&tzi_system
.StandardName
,&dwSize_name1
) != ERROR_SUCCESS
&&
1372 RegQueryValueEx(hkResult
,_T("Dlt"),NULL
,&dwType
,(LPBYTE
)&tzi_system
.DaylightName
,&dwSize_name2
) != ERROR_SUCCESS
)
1377 tzi_system
.Bias
=tzi
.Bias
;
1378 tzi_system
.StandardBias
=tzi
.StandardBias
;
1379 tzi_system
.DaylightBias
=tzi
.DaylightBias
;
1380 tzi_system
.StandardDate
=tzi
.StandardDate
;
1381 tzi_system
.DaylightDate
=tzi
.DaylightDate
;
1383 /* CFTimeZoneRef->_data will contain TIME_ZONE_INFORMATION structure
1384 * to find current timezone
1385 * (Aleksey Dukhnyakov)
1387 data
= CFDataCreate(allocator
,(UInt8
*)&tzi_system
, sizeof(tzi_system
));
1389 RegCloseKey(hkResult
);
1390 result
= CFTimeZoneCreate(allocator
, name
, data
);
1393 result
->_periods
->abbrev
= (CFStringRef
)CFStringCreateCopy(allocator
,safeName
);
1402 #error Unknown or unspecified DEPLOYMENT_TARGET
1405 CFStringRef
CFTimeZoneGetName(CFTimeZoneRef tz
) {
1406 CF_OBJC_FUNCDISPATCH0(CFTimeZoneGetTypeID(), CFStringRef
, tz
, "name");
1407 __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
1411 CFDataRef
CFTimeZoneGetData(CFTimeZoneRef tz
) {
1412 CF_OBJC_FUNCDISPATCH0(CFTimeZoneGetTypeID(), CFDataRef
, tz
, "data");
1413 __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
1417 /* This function converts CFAbsoluteTime to (Win32) SYSTEMTIME
1418 * (Aleksey Dukhnyakov)
1420 #if DEPLOYMENT_TARGET_WINDOWS
1421 BOOL
__CFTimeZoneGetWin32SystemTime(SYSTEMTIME
* sys_time
, CFAbsoluteTime time
)
1424 FILETIME
* ftime
=(FILETIME
*)&l
;
1426 /* seconds between 1601 and 1970 : 11644473600,
1427 * seconds between 1970 and 2001 : 978307200,
1428 * FILETIME - number of 100-nanosecond intervals since January 1, 1601
1430 l
=(LONGLONG
)(time
+11644473600LL+978307200)*10000000;
1431 if (FileTimeToSystemTime(ftime
,sys_time
))
1436 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
1438 #error Unknown or unspecified DEPLOYMENT_TARGET
1441 CFTimeInterval
CFTimeZoneGetSecondsFromGMT(CFTimeZoneRef tz
, CFAbsoluteTime at
) {
1442 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
1444 CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), CFTimeInterval
, tz
, "_secondsFromGMTForAbsoluteTime:", at
);
1445 __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
1446 idx
= __CFBSearchTZPeriods(tz
, at
);
1447 return __CFTZPeriodGMTOffset(&(tz
->_periods
[idx
]));
1448 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
1449 /* To calculate seconds from GMT, calculate current timezone time and
1450 * subtract GMT timnezone time
1451 * (Aleksey Dukhnyakov)
1453 TIME_ZONE_INFORMATION tzi
;
1454 FILETIME ftime1
,ftime2
;
1455 SYSTEMTIME stime0
,stime1
,stime2
;
1456 LONGLONG
* l1
= (LONGLONG
*)&ftime1
;
1457 LONGLONG
* l2
= (LONGLONG
*)&ftime2
;
1458 CFRange range
={0,sizeof(TIME_ZONE_INFORMATION
)};
1461 CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), CFTimeInterval
, tz
, "_secondsFromGMTForAbsoluteTime:", at
);
1463 CFDataGetBytes(tz
->_data
,range
,(UInt8
*)&tzi
);
1465 if (!__CFTimeZoneGetWin32SystemTime(&stime0
,at
) ||
1466 !SystemTimeToTzSpecificLocalTime(&tzi
,&stime0
,&stime1
) ||
1467 !SystemTimeToFileTime(&stime1
,&ftime1
) )
1469 CFAssert(0, __kCFLogAssertion
, "Win32 system time/timezone failed !\n");
1473 tzi
.DaylightDate
.wMonth
=0;
1474 tzi
.StandardDate
.wMonth
=0;
1479 if ( !SystemTimeToTzSpecificLocalTime(&tzi
,&stime0
,&stime2
) ||
1480 !SystemTimeToFileTime(&stime2
,&ftime2
))
1482 CFAssert(0, __kCFLogAssertion
, "Win32 system time/timezone failed !\n");
1485 result
=(double)((*l1
-*l2
)/10000000);
1488 #error Unknown or unspecified DEPLOYMENT_TARGET
1492 #if DEPLOYMENT_TARGET_WINDOWS_SAFARI
1494 * Get abbreviation for name for WIN32 platform
1495 * (Aleksey Dukhnyakov)
1503 static void _CFFindKeyForValue(const void *key
, const void *value
, void *context
) {
1504 if ( ((_CFAbbrFind
*)context
)->tzAbbr
!= NULL
) {
1505 if ( ((_CFAbbrFind
*)context
)->tzName
== (CFStringRef
) value
) {
1506 ((_CFAbbrFind
*)context
)->tzAbbr
= (CFStringRef
)key
;
1511 CFIndex
__CFTimeZoneInitAbbrev(CFTimeZoneRef tz
) {
1513 if ( tz
->_periods
->abbrev
== NULL
) {
1514 _CFAbbrFind abbr
= { NULL
, NULL
};
1515 CFDictionaryRef abbrevs
= CFTimeZoneCopyAbbreviationDictionary();
1517 CFDictionaryApplyFunction(abbrevs
, _CFFindKeyForValue
, &abbr
);
1519 if ( abbr
.tzAbbr
!= NULL
)
1520 tz
->_periods
->abbrev
= (CFStringRef
)CFStringCreateCopy(kCFAllocatorSystemDefault
, abbr
.tzAbbr
);
1522 tz
->_periods
->abbrev
= (CFStringRef
)CFStringCreateCopy(kCFAllocatorSystemDefault
, tz
->_name
);
1523 /* We should return name of TimeZone if couldn't find abbrevation.
1526 * (Aleksey Dukhnyakov)
1528 CFRelease( abbrevs
);
1533 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
1535 #error Unknown or unspecified DEPLOYMENT_TARGET
1538 CFStringRef
CFTimeZoneCopyAbbreviation(CFTimeZoneRef tz
, CFAbsoluteTime at
) {
1541 CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), CFStringRef
, tz
, "_abbreviationForAbsoluteTime:", at
);
1542 __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
1543 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
1544 idx
= __CFBSearchTZPeriods(tz
, at
);
1545 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
1547 * Initialize abbreviation for this TimeZone
1548 * (Aleksey Dukhnyakov)
1550 idx
= __CFTimeZoneInitAbbrev(tz
);
1552 #error Unknown or unspecified DEPLOYMENT_TARGET
1554 result
= __CFTZPeriodAbbreviation(&(tz
->_periods
[idx
]));
1555 return result
? (CFStringRef
)CFRetain(result
) : NULL
;
1558 Boolean
CFTimeZoneIsDaylightSavingTime(CFTimeZoneRef tz
, CFAbsoluteTime at
) {
1559 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
1561 CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), Boolean
, tz
, "_isDaylightSavingTimeForAbsoluteTime:", at
);
1562 __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
1563 idx
= __CFBSearchTZPeriods(tz
, at
);
1564 return __CFTZPeriodIsDST(&(tz
->_periods
[idx
]));
1565 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
1566 /* Compare current timezone time and current timezone time without
1567 * transition to day light saving time
1568 * (Aleskey Dukhnyakov)
1570 TIME_ZONE_INFORMATION tzi
;
1571 SYSTEMTIME stime0
,stime1
,stime2
;
1572 CFRange range
={0,sizeof(TIME_ZONE_INFORMATION
)};
1574 CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), Boolean
, tz
, "_isDaylightSavingTimeForAbsoluteTime:", at
);
1576 CFDataGetBytes(tz
->_data
,range
,(UInt8
*)&tzi
);
1578 if ( !__CFTimeZoneGetWin32SystemTime(&stime0
,at
) ||
1579 !SystemTimeToTzSpecificLocalTime(&tzi
,&stime0
,&stime1
)) {
1580 CFAssert(0, __kCFLogAssertion
, "Win32 system time/timezone failed !\n");
1584 tzi
.DaylightDate
.wMonth
=0;
1585 tzi
.StandardDate
.wMonth
=0;
1587 if ( !SystemTimeToTzSpecificLocalTime(&tzi
,&stime0
,&stime2
)) {
1588 CFAssert(0, __kCFLogAssertion
, "Win32 system time/timezone failed !\n");
1592 if ( !memcmp(&stime1
,&stime2
,sizeof(stime1
)) )
1597 #error Unknown or unspecified DEPLOYMENT_TARGET
1601 CFTimeInterval
CFTimeZoneGetDaylightSavingTimeOffset(CFTimeZoneRef tz
, CFAbsoluteTime at
) {
1602 CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), CFTimeInterval
, tz
, "_daylightSavingTimeOffsetForAbsoluteTime:", at
);
1603 __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
1604 CFIndex idx
= __CFBSearchTZPeriods(tz
, at
);
1605 if (__CFTZPeriodIsDST(&(tz
->_periods
[idx
]))) {
1606 CFTimeInterval offset
= __CFTZPeriodGMTOffset(&(tz
->_periods
[idx
]));
1607 if (idx
+ 1 < tz
->_periodCnt
) {
1608 return offset
- __CFTZPeriodGMTOffset(&(tz
->_periods
[idx
+ 1]));
1609 } else if (0 < idx
) {
1610 return offset
- __CFTZPeriodGMTOffset(&(tz
->_periods
[idx
- 1]));
1616 CFAbsoluteTime
CFTimeZoneGetNextDaylightSavingTimeTransition(CFTimeZoneRef tz
, CFAbsoluteTime at
) {
1617 CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), CFTimeInterval
, tz
, "_nextDaylightSavingTimeTransitionAfterAbsoluteTime:", at
);
1618 __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
1619 CFIndex idx
= __CFBSearchTZPeriods(tz
, at
);
1620 if (tz
->_periodCnt
<= idx
+ 1) {
1623 return (CFAbsoluteTime
)__CFTZPeriodStartSeconds(&(tz
->_periods
[idx
+ 1]));
1626 extern UCalendar
*__CFCalendarCreateUCalendar(CFStringRef calendarID
, CFStringRef localeID
, CFTimeZoneRef tz
);
1628 #define BUFFER_SIZE 768
1630 CFStringRef
CFTimeZoneCopyLocalizedName(CFTimeZoneRef tz
, CFTimeZoneNameStyle style
, CFLocaleRef locale
) {
1631 CF_OBJC_FUNCDISPATCH2(CFTimeZoneGetTypeID(), CFStringRef
, tz
, "localizedName:locale:", style
, locale
);
1632 __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
1633 __CFGenericValidateType(locale
, CFLocaleGetTypeID());
1635 if (style
== kCFTimeZoneNameStyleGeneric
|| style
== kCFTimeZoneNameStyleShortGeneric
) {
1636 CFDateFormatterRef df
= CFDateFormatterCreate(kCFAllocatorSystemDefault
, locale
, kCFDateFormatterNoStyle
, kCFDateFormatterNoStyle
);
1637 CFDateFormatterSetProperty(df
, kCFDateFormatterTimeZone
, tz
);
1638 CFDateFormatterSetFormat(df
, (style
== kCFTimeZoneNameStyleGeneric
) ? CFSTR("vvvv") : CFSTR("v"));
1639 CFStringRef str
= CFDateFormatterCreateStringWithAbsoluteTime(CFGetAllocator(tz
), df
, 0.0);
1644 CFStringRef localeID
= CFLocaleGetIdentifier(locale
);
1645 UCalendar
*cal
= __CFCalendarCreateUCalendar(NULL
, localeID
, tz
);
1650 char buffer
[BUFFER_SIZE
];
1651 const char *cstr
= CFStringGetCStringPtr(localeID
, kCFStringEncodingASCII
);
1653 if (CFStringGetCString(localeID
, buffer
, BUFFER_SIZE
, kCFStringEncodingASCII
)) cstr
= buffer
;
1660 UChar ubuffer
[BUFFER_SIZE
];
1661 UErrorCode status
= U_ZERO_ERROR
;
1662 int32_t cnt
= ucal_getTimeZoneDisplayName(cal
, (UCalendarDisplayNameType
)style
, cstr
, ubuffer
, BUFFER_SIZE
, &status
);
1664 if (U_SUCCESS(status
) && cnt
<= BUFFER_SIZE
) {
1665 return CFStringCreateWithCharacters(CFGetAllocator(tz
), (const UniChar
*)ubuffer
, cnt
);
1670 static CFDictionaryRef
__CFTimeZoneCopyCompatibilityDictionary(void) {
1671 CFDictionaryRef dict
;
1672 __CFTimeZoneLockCompatibilityMapping();
1673 if (NULL
== __CFTimeZoneCompatibilityMappingDict
) {
1674 __CFTimeZoneCompatibilityMappingDict
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 112, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
1676 // Empty string means delete/ignore these
1678 dict
= __CFTimeZoneCompatibilityMappingDict
? (CFDictionaryRef
)CFRetain(__CFTimeZoneCompatibilityMappingDict
) : NULL
;
1679 __CFTimeZoneUnlockCompatibilityMapping();