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@
25 Copyright 1998-2002, Apple, Inc. All rights reserved.
26 Responsibility: Christopher Kane
31 #include <CoreFoundation/CFTimeZone.h>
32 #include <CoreFoundation/CFPropertyList.h>
33 #include <CoreFoundation/CFDateFormatter.h>
34 #include <CoreFoundation/CFPriv.h>
35 #include "CFInternal.h"
42 #include <unicode/ucal.h>
43 #include <CoreFoundation/CFDateFormatter.h>
44 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
47 #include <sys/fcntl.h>
50 #error Unknown or unspecified DEPLOYMENT_TARGET
54 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
55 #define TZZONELINK TZDEFAULT
56 #define TZZONEINFO TZDIR "/"
57 #elif DEPLOYMENT_TARGET_WINDOWS
58 static CFStringRef __tzZoneInfo
= NULL
;
59 static char *__tzDir
= NULL
;
60 static void __InitTZStrings(void);
62 #error Unknown or unspecified DEPLOYMENT_TARGET
65 CONST_STRING_DECL(kCFTimeZoneSystemTimeZoneDidChangeNotification
, "kCFTimeZoneSystemTimeZoneDidChangeNotification")
67 static CFTimeZoneRef __CFTimeZoneSystem
= NULL
;
68 static CFTimeZoneRef __CFTimeZoneDefault
= NULL
;
69 static CFDictionaryRef __CFTimeZoneAbbreviationDict
= NULL
;
70 static CFSpinLock_t __CFTimeZoneAbbreviationLock
= CFSpinLockInit
;
71 static CFMutableDictionaryRef __CFTimeZoneCompatibilityMappingDict
= NULL
;
72 static CFSpinLock_t __CFTimeZoneCompatibilityMappingLock
= CFSpinLockInit
;
73 static CFArrayRef __CFKnownTimeZoneList
= NULL
;
74 static CFMutableDictionaryRef __CFTimeZoneCache
= NULL
;
75 static CFSpinLock_t __CFTimeZoneGlobalLock
= CFSpinLockInit
;
77 #if DEPLOYMENT_TARGET_WINDOWS
78 static CFDictionaryRef __CFTimeZoneWinToOlsonDict
= NULL
;
79 static CFSpinLock_t __CFTimeZoneWinToOlsonLock
= CFSpinLockInit
;
82 CF_INLINE
void __CFTimeZoneLockGlobal(void) {
83 __CFSpinLock(&__CFTimeZoneGlobalLock
);
86 CF_INLINE
void __CFTimeZoneUnlockGlobal(void) {
87 __CFSpinUnlock(&__CFTimeZoneGlobalLock
);
90 CF_INLINE
void __CFTimeZoneLockAbbreviations(void) {
91 __CFSpinLock(&__CFTimeZoneAbbreviationLock
);
94 CF_INLINE
void __CFTimeZoneUnlockAbbreviations(void) {
95 __CFSpinUnlock(&__CFTimeZoneAbbreviationLock
);
98 CF_INLINE
void __CFTimeZoneLockCompatibilityMapping(void) {
99 __CFSpinLock(&__CFTimeZoneCompatibilityMappingLock
);
102 CF_INLINE
void __CFTimeZoneUnlockCompatibilityMapping(void) {
103 __CFSpinUnlock(&__CFTimeZoneCompatibilityMappingLock
);
106 #if DEPLOYMENT_TARGET_WINDOWS
107 /* This function should be used for WIN32 instead of
108 * __CFCopyRecursiveDirectoryList function.
109 * It takes TimeZone names from the registry
110 * (Aleksey Dukhnyakov)
112 static CFMutableArrayRef
__CFCopyWindowsTimeZoneList() {
113 CFMutableArrayRef result
= NULL
;
115 TCHAR lpName
[MAX_PATH
+1];
116 DWORD dwIndex
, retCode
;
118 if (RegOpenKey(HKEY_LOCAL_MACHINE
,_T(TZZONEINFO
),&hkResult
) !=
122 result
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
123 for (dwIndex
=0; (retCode
= RegEnumKey(hkResult
,dwIndex
,lpName
,MAX_PATH
)) != ERROR_NO_MORE_ITEMS
; dwIndex
++) {
124 if (retCode
!= ERROR_SUCCESS
) {
125 RegCloseKey(hkResult
);
130 CFStringRef string
= CFStringCreateWithBytes(kCFAllocatorSystemDefault
, (const UInt8
*)lpName
, (_tcslen(lpName
) * sizeof(UniChar
)), kCFStringEncodingUnicode
, false);
132 CFStringRef string
= CFStringCreateWithBytes(kCFAllocatorSystemDefault
, lpName
, _tcslen(lpName
), CFStringGetSystemEncoding(), false);
134 CFArrayAppendValue(result
, string
);
139 RegCloseKey(hkResult
);
142 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
143 static CFMutableArrayRef
__CFCopyRecursiveDirectoryList() {
144 CFMutableArrayRef result
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
145 #if DEPLOYMENT_TARGET_WINDOWS
146 if (!__tzDir
) __InitTZStrings();
147 if (!__tzDir
) return result
;
148 int fd
= open(__tzDir
, O_RDONLY
);
150 int fd
= open(TZDIR
"/zone.tab", O_RDONLY
);
154 uint8_t buffer
[4096];
155 ssize_t len
= read(fd
, buffer
, sizeof(buffer
));
157 if (len
< sizeof(buffer
)) {
158 // assumes that partial read only occurs at the end of the file
162 const uint8_t *bytes
= buffer
;
164 const uint8_t *nextl
= memchr(bytes
, '\n', len
);
168 len
-= (nextl
- bytes
);
172 const uint8_t *tab1
= memchr(bytes
, '\t', (nextl
- bytes
));
174 len
-= (nextl
- bytes
);
179 len
-= (tab1
- bytes
);
181 const uint8_t *tab2
= memchr(bytes
, '\t', (nextl
- bytes
));
183 len
-= (nextl
- bytes
);
188 len
-= (tab2
- bytes
);
190 const uint8_t *tab3
= memchr(bytes
, '\t', (nextl
- bytes
));
191 int nmlen
= tab3
? (tab3
- bytes
) : (nextl
- 1 - bytes
);
192 CFStringRef string
= CFStringCreateWithBytes(kCFAllocatorSystemDefault
, bytes
, nmlen
, kCFStringEncodingUTF8
, false);
193 CFArrayAppendValue(result
, string
);
195 len
-= (nextl
- bytes
);
198 lseek(fd
, -len
, SEEK_CUR
);
204 #error Unknown or unspecified DEPLOYMENT_TARGET
207 typedef struct _CFTZPeriod
{
213 struct __CFTimeZone
{
215 CFStringRef _name
; /* immutable */
216 CFDataRef _data
; /* immutable */
217 CFTZPeriod
*_periods
; /* immutable */
218 int32_t _periodCnt
; /* immutable */
221 /* startSec is the whole integer seconds from a CFAbsoluteTime, giving dates
222 * between 1933 and 2069; info outside these years is discarded on read-in */
223 /* Bits 31-18 of the info are unused */
224 /* Bit 17 of the info is used for the is-DST state */
225 /* Bit 16 of the info is used for the sign of the offset (1 == negative) */
226 /* Bits 15-0 of the info are used for abs(offset) in seconds from GMT */
228 CF_INLINE
void __CFTZPeriodInit(CFTZPeriod
*period
, int32_t startTime
, CFStringRef abbrev
, int32_t offset
, Boolean isDST
) {
229 period
->startSec
= startTime
;
230 period
->abbrev
= abbrev
? (CFStringRef
)CFRetain(abbrev
) : NULL
;
231 __CFBitfieldSetValue(period
->info
, 15, 0, abs(offset
));
232 __CFBitfieldSetValue(period
->info
, 16, 16, (offset
< 0 ? 1 : 0));
233 __CFBitfieldSetValue(period
->info
, 17, 17, (isDST
? 1 : 0));
236 CF_INLINE
int32_t __CFTZPeriodStartSeconds(const CFTZPeriod
*period
) {
237 return period
->startSec
;
240 CF_INLINE CFStringRef
__CFTZPeriodAbbreviation(const CFTZPeriod
*period
) {
241 return period
->abbrev
;
244 CF_INLINE
int32_t __CFTZPeriodGMTOffset(const CFTZPeriod
*period
) {
245 int32_t v
= __CFBitfieldGetValue(period
->info
, 15, 0);
246 if (__CFBitfieldGetValue(period
->info
, 16, 16)) v
= -v
;
250 CF_INLINE Boolean
__CFTZPeriodIsDST(const CFTZPeriod
*period
) {
251 return (Boolean
)__CFBitfieldGetValue(period
->info
, 17, 17);
254 static CFComparisonResult
__CFCompareTZPeriods(const void *val1
, const void *val2
, void *context
) {
255 CFTZPeriod
*tzp1
= (CFTZPeriod
*)val1
;
256 CFTZPeriod
*tzp2
= (CFTZPeriod
*)val2
;
257 // we treat equal as less than, as the code which uses the
258 // result of the bsearch doesn't expect exact matches
259 // (they're pretty rare, so no point in over-coding for them)
260 if (__CFTZPeriodStartSeconds(tzp1
) <= __CFTZPeriodStartSeconds(tzp2
)) return kCFCompareLessThan
;
261 return kCFCompareGreaterThan
;
264 static CFIndex
__CFBSearchTZPeriods(CFTimeZoneRef tz
, CFAbsoluteTime at
) {
266 __CFTZPeriodInit(&elem
, (int32_t)floor(at
+ 1.0), NULL
, 0, false);
267 CFIndex idx
= CFBSearch(&elem
, sizeof(CFTZPeriod
), tz
->_periods
, tz
->_periodCnt
, __CFCompareTZPeriods
, NULL
);
268 if (tz
->_periodCnt
<= idx
) {
269 idx
= tz
->_periodCnt
;
270 } else if (0 == idx
) {
277 CF_INLINE
int32_t __CFDetzcode(const unsigned char *bufp
) {
278 int32_t result
= (bufp
[0] & 0x80) ? ~0L : 0L;
279 result
= (result
<< 8) | (bufp
[0] & 0xff);
280 result
= (result
<< 8) | (bufp
[1] & 0xff);
281 result
= (result
<< 8) | (bufp
[2] & 0xff);
282 result
= (result
<< 8) | (bufp
[3] & 0xff);
286 CF_INLINE
void __CFEntzcode(int32_t value
, unsigned char *bufp
) {
287 bufp
[0] = (value
>> 24) & 0xff;
288 bufp
[1] = (value
>> 16) & 0xff;
289 bufp
[2] = (value
>> 8) & 0xff;
290 bufp
[3] = (value
>> 0) & 0xff;
293 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
294 static Boolean
__CFParseTimeZoneData(CFAllocatorRef allocator
, CFDataRef data
, CFTZPeriod
**tzpp
, CFIndex
*cntp
) {
295 int32_t len
, timecnt
, typecnt
, charcnt
, idx
, cnt
;
296 const uint8_t *p
, *timep
, *typep
, *ttisp
, *charp
;
298 Boolean result
= true;
300 p
= CFDataGetBytePtr(data
);
301 len
= CFDataGetLength(data
);
302 if (len
< (int32_t)sizeof(struct tzhead
)) {
306 if (!(p
[0] == 'T' && p
[1] == 'Z' && p
[2] == 'i' && p
[3] == 'f')) return false; /* Don't parse without TZif at head of file */
308 p
+= 20 + 4 + 4 + 4; /* skip reserved, ttisgmtcnt, ttisstdcnt, leapcnt */
309 timecnt
= __CFDetzcode(p
);
311 typecnt
= __CFDetzcode(p
);
313 charcnt
= __CFDetzcode(p
);
315 if (typecnt
<= 0 || timecnt
< 0 || charcnt
< 0) {
318 if (1024 < timecnt
|| 32 < typecnt
|| 128 < charcnt
) {
319 // reject excessive timezones to avoid arithmetic overflows for
320 // security reasons and to reject potentially corrupt files
323 if (len
- (int32_t)sizeof(struct tzhead
) < (4 + 1) * timecnt
+ (4 + 1 + 1) * typecnt
+ charcnt
) {
327 typep
= timep
+ 4 * timecnt
;
328 ttisp
= typep
+ timecnt
;
329 charp
= ttisp
+ (4 + 1 + 1) * typecnt
;
330 cnt
= (0 < timecnt
) ? timecnt
: 1;
331 *tzpp
= CFAllocatorAllocate(allocator
, cnt
* sizeof(CFTZPeriod
), 0);
332 if (__CFOASafe
) __CFSetLastAllocationEventName(*tzpp
, "CFTimeZone (store)");
333 memset(*tzpp
, 0, cnt
* sizeof(CFTZPeriod
));
334 abbrs
= CFAllocatorAllocate(allocator
, (charcnt
+ 1) * sizeof(CFStringRef
), 0);
335 if (__CFOASafe
) __CFSetLastAllocationEventName(abbrs
, "CFTimeZone (temp)");
336 for (idx
= 0; idx
< charcnt
+ 1; idx
++) {
339 for (idx
= 0; idx
< cnt
; idx
++) {
341 int32_t itime
, offset
;
342 uint8_t type
, dst
, abbridx
;
344 at
= (CFAbsoluteTime
)(__CFDetzcode(timep
) + 0.0) - kCFAbsoluteTimeIntervalSince1970
;
345 if (0 == timecnt
) itime
= INT_MIN
;
346 else if (at
< (CFAbsoluteTime
)INT_MIN
) itime
= INT_MIN
;
347 else if ((CFAbsoluteTime
)INT_MAX
< at
) itime
= INT_MAX
;
348 else itime
= (int32_t)at
;
349 timep
+= 4; /* harmless if 0 == timecnt */
350 type
= (0 < timecnt
) ? (uint8_t)*typep
++ : 0;
351 if (typecnt
<= type
) {
355 offset
= __CFDetzcode(ttisp
+ 6 * type
);
356 dst
= (uint8_t)*(ttisp
+ 6 * type
+ 4);
357 if (0 != dst
&& 1 != dst
) {
361 abbridx
= (uint8_t)*(ttisp
+ 6 * type
+ 5);
362 if (charcnt
< abbridx
) {
366 if (NULL
== abbrs
[abbridx
]) {
367 abbrs
[abbridx
] = CFStringCreateWithCString(allocator
, (char *)&charp
[abbridx
], kCFStringEncodingASCII
);
369 __CFTZPeriodInit(*tzpp
+ idx
, itime
, abbrs
[abbridx
], offset
, (dst
? true : false));
371 for (idx
= 0; idx
< charcnt
+ 1; idx
++) {
372 if (NULL
!= abbrs
[idx
]) {
373 CFRelease(abbrs
[idx
]);
376 CFAllocatorDeallocate(allocator
, abbrs
);
378 // dump all but the last INT_MIN and the first INT_MAX
379 for (idx
= 0; idx
< cnt
; idx
++) {
380 if (((*tzpp
+ idx
)->startSec
== INT_MIN
) && (idx
+ 1 < cnt
) && (((*tzpp
+ idx
+ 1)->startSec
== INT_MIN
))) {
381 if (NULL
!= (*tzpp
+ idx
)->abbrev
) CFRelease((*tzpp
+ idx
)->abbrev
);
383 memmove((*tzpp
+ idx
), (*tzpp
+ idx
+ 1), sizeof(CFTZPeriod
) * (cnt
- idx
));
387 // Don't combine these loops! Watch the idx decrementing...
388 for (idx
= 0; idx
< cnt
; idx
++) {
389 if (((*tzpp
+ idx
)->startSec
== INT_MAX
) && (0 < idx
) && (((*tzpp
+ idx
- 1)->startSec
== INT_MAX
))) {
390 if (NULL
!= (*tzpp
+ idx
)->abbrev
) CFRelease((*tzpp
+ idx
)->abbrev
);
392 memmove((*tzpp
+ idx
), (*tzpp
+ idx
+ 1), sizeof(CFTZPeriod
) * (cnt
- idx
));
396 CFQSortArray(*tzpp
, cnt
, sizeof(CFTZPeriod
), __CFCompareTZPeriods
, NULL
);
397 // if the first period is in DST and there is more than one period, drop it
398 if (1 < cnt
&& __CFTZPeriodIsDST(*tzpp
+ 0)) {
399 if (NULL
!= (*tzpp
+ 0)->abbrev
) CFRelease((*tzpp
+ 0)->abbrev
);
401 memmove((*tzpp
+ 0), (*tzpp
+ 0 + 1), sizeof(CFTZPeriod
) * (cnt
- 0));
405 CFAllocatorDeallocate(allocator
, *tzpp
);
410 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
411 static Boolean
__CFParseTimeZoneData(CFAllocatorRef allocator
, CFDataRef data
, CFTZPeriod
**tzpp
, CFIndex
*cntp
) {
412 /* We use Win32 function to find TimeZone
413 * (Aleksey Dukhnyakov)
415 *tzpp
= (CFTZPeriod
*)CFAllocatorAllocate(allocator
, sizeof(CFTZPeriod
), 0);
416 memset(*tzpp
, 0, sizeof(CFTZPeriod
));
417 __CFTZPeriodInit(*tzpp
, 0, NULL
, 0, false);
422 #error Unknown or unspecified DEPLOYMENT_TARGET
425 static Boolean
__CFTimeZoneEqual(CFTypeRef cf1
, CFTypeRef cf2
) {
426 CFTimeZoneRef tz1
= (CFTimeZoneRef
)cf1
;
427 CFTimeZoneRef tz2
= (CFTimeZoneRef
)cf2
;
428 if (!CFEqual(CFTimeZoneGetName(tz1
), CFTimeZoneGetName(tz2
))) return false;
429 if (!CFEqual(CFTimeZoneGetData(tz1
), CFTimeZoneGetData(tz2
))) return false;
433 static CFHashCode
__CFTimeZoneHash(CFTypeRef cf
) {
434 CFTimeZoneRef tz
= (CFTimeZoneRef
)cf
;
435 return CFHash(CFTimeZoneGetName(tz
));
438 static CFStringRef
__CFTimeZoneCopyDescription(CFTypeRef cf
) {
439 CFTimeZoneRef tz
= (CFTimeZoneRef
)cf
;
440 CFStringRef result
, abbrev
;
442 at
= CFAbsoluteTimeGetCurrent();
443 abbrev
= CFTimeZoneCopyAbbreviation(tz
, at
);
444 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");
449 static void __CFTimeZoneDeallocate(CFTypeRef cf
) {
450 CFTimeZoneRef tz
= (CFTimeZoneRef
)cf
;
451 CFAllocatorRef allocator
= CFGetAllocator(tz
);
453 if (tz
->_name
) CFRelease(tz
->_name
);
454 if (tz
->_data
) CFRelease(tz
->_data
);
455 for (idx
= 0; idx
< tz
->_periodCnt
; idx
++) {
456 if (NULL
!= tz
->_periods
[idx
].abbrev
) CFRelease(tz
->_periods
[idx
].abbrev
);
458 if (NULL
!= tz
->_periods
) CFAllocatorDeallocate(allocator
, tz
->_periods
);
461 static CFTypeID __kCFTimeZoneTypeID
= _kCFRuntimeNotATypeID
;
463 static const CFRuntimeClass __CFTimeZoneClass
= {
468 __CFTimeZoneDeallocate
,
472 __CFTimeZoneCopyDescription
475 __private_extern__
void __CFTimeZoneInitialize(void) {
476 __kCFTimeZoneTypeID
= _CFRuntimeRegisterClass(&__CFTimeZoneClass
);
479 CFTypeID
CFTimeZoneGetTypeID(void) {
480 return __kCFTimeZoneTypeID
;
484 #if DEPLOYMENT_TARGET_WINDOWS_SYNC
485 static const char *__CFTimeZoneWinToOlsonDefaults
=
486 /* Mappings to time zones in Windows Registry are best-guess */
487 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
488 " <!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">"
489 " <plist version=\"1.0\">"
491 " <key>Afghanistan</key> <string>Asia/Kabul</string>"
492 " <key>Afghanistan Standard Time</key> <string>Asia/Kabul</string>"
493 " <key>Alaskan</key> <string>America/Anchorage</string>"
494 " <key>Alaskan Standard Time</key> <string>America/Anchorage</string>"
495 " <key>Arab</key> <string>Asia/Riyadh</string>"
496 " <key>Arab Standard Time</key> <string>Asia/Riyadh</string>"
497 " <key>Arabian</key> <string>Asia/Muscat</string>"
498 " <key>Arabian Standard Time</key> <string>Asia/Muscat</string>"
499 " <key>Arabic Standard Time</key> <string>Asia/Baghdad</string>"
500 " <key>Atlantic</key> <string>America/Halifax</string>"
501 " <key>Atlantic Standard Time</key> <string>America/Halifax</string>"
502 " <key>AUS Central</key> <string>Australia/Darwin</string>"
503 " <key>AUS Central Standard Time</key> <string>Australia/Darwin</string>"
504 " <key>AUS Eastern</key> <string>Australia/Sydney</string>"
505 " <key>AUS Eastern Standard Time</key> <string>Australia/Sydney</string>"
506 " <key>Azerbaijan Standard Time</key> <string>Asia/Baku</string>"
507 " <key>Azores</key> <string>Atlantic/Azores</string>"
508 " <key>Azores Standard Time</key> <string>Atlantic/Azores</string>"
509 " <key>Bangkok</key> <string>Asia/Bangkok</string>"
510 " <key>Bangkok Standard Time</key> <string>Asia/Bangkok</string>"
511 " <key>Beijing</key> <string>Asia/Shanghai</string>"
512 " <key>Canada Central</key> <string>America/Regina</string>"
513 " <key>Canada Central Standard Time</key> <string>America/Regina</string>"
514 " <key>Cape Verde Standard Time</key> <string>Atlantic/Cape_Verde</string>"
515 " <key>Caucasus</key> <string>Asia/Yerevan</string>"
516 " <key>Caucasus Standard Time</key> <string>Asia/Yerevan</string>"
517 " <key>Cen. Australia</key> <string>Australia/Adelaide</string>"
518 " <key>Cen. Australia Standard Time</key> <string>Australia/Adelaide</string>"
519 " <key>Central</key> <string>America/Chicago</string>"
520 " <key>Central America Standard Time</key> <string>America/Regina</string>"
521 " <key>Central Asia</key> <string>Asia/Dhaka</string>"
522 " <key>Central Asia Standard Time</key> <string>Asia/Dhaka</string>"
523 " <key>Central Brazilian Standard Time</key> <string>America/Manaus</string>"
524 " <key>Central Europe</key> <string>Europe/Prague</string>"
525 " <key>Central Europe Standard Time</key> <string>Europe/Prague</string>"
526 " <key>Central European</key> <string>Europe/Belgrade</string>"
527 " <key>Central European Standard Time</key> <string>Europe/Belgrade</string>"
528 " <key>Central Pacific</key> <string>Pacific/Guadalcanal</string>"
529 " <key>Central Pacific Standard Time</key> <string>Pacific/Guadalcanal</string>"
530 " <key>Central Standard Time</key> <string>America/Chicago</string>"
531 " <key>Central Standard Time (Mexico)</key> <string>America/Mexico_City</string>"
532 " <key>China</key> <string>Asia/Shanghai</string>"
533 " <key>China Standard Time</key> <string>Asia/Shanghai</string>"
534 " <key>Dateline</key> <string>GMT-1200</string>"
535 " <key>Dateline Standard Time</key> <string>GMT-1200</string>"
536 " <key>E. Africa</key> <string>Africa/Nairobi</string>"
537 " <key>E. Africa Standard Time</key> <string>Africa/Nairobi</string>"
538 " <key>E. Australia</key> <string>Australia/Brisbane</string>"
539 " <key>E. Australia Standard Time</key> <string>Australia/Brisbane</string>"
540 " <key>E. Europe</key> <string>Europe/Minsk</string>"
541 " <key>E. Europe Standard Time</key> <string>Europe/Minsk</string>"
542 " <key>E. South America</key> <string>America/Sao_Paulo</string>"
543 " <key>E. South America Standard Time</key> <string>America/Sao_Paulo</string>"
544 " <key>Eastern</key> <string>America/New_York</string>"
545 " <key>Eastern Standard Time</key> <string>America/New_York</string>"
546 " <key>Egypt</key> <string>Africa/Cairo</string>"
547 " <key>Egypt Standard Time</key> <string>Africa/Cairo</string>"
548 " <key>Ekaterinburg</key> <string>Asia/Yekaterinburg</string>"
549 " <key>Ekaterinburg Standard Time</key> <string>Asia/Yekaterinburg</string>"
550 " <key>Fiji</key> <string>Pacific/Fiji</string>"
551 " <key>Fiji Standard Time</key> <string>Pacific/Fiji</string>"
552 " <key>FLE</key> <string>Europe/Helsinki</string>"
553 " <key>FLE Standard Time</key> <string>Europe/Helsinki</string>"
554 " <key>Georgian Standard Time</key> <string>Asia/Tbilisi</string>"
555 " <key>GFT</key> <string>Europe/Athens</string>"
556 " <key>GFT Standard Time</key> <string>Europe/Athens</string>"
557 " <key>GMT</key> <string>Europe/London</string>"
558 " <key>GMT Standard Time</key> <string>Europe/London</string>"
559 " <key>Greenland Standard Time</key> <string>America/Godthab</string>"
560 " <key>Greenwich</key> <string>GMT</string>"
561 " <key>Greenwich Standard Time</key> <string>GMT</string>"
562 " <key>GTB</key> <string>Europe/Athens</string>"
563 " <key>GTB Standard Time</key> <string>Europe/Athens</string>"
564 " <key>Hawaiian</key> <string>Pacific/Honolulu</string>"
565 " <key>Hawaiian Standard Time</key> <string>Pacific/Honolulu</string>"
566 " <key>India</key> <string>Asia/Calcutta</string>"
567 " <key>India Standard Time</key> <string>Asia/Calcutta</string>"
568 " <key>Iran</key> <string>Asia/Tehran</string>"
569 " <key>Iran Standard Time</key> <string>Asia/Tehran</string>"
570 " <key>Israel</key> <string>Asia/Jerusalem</string>"
571 " <key>Israel Standard Time</key> <string>Asia/Jerusalem</string>"
572 " <key>Jordan Standard Time</key> <string>Asia/Amman</string>"
573 " <key>Korea</key> <string>Asia/Seoul</string>"
574 " <key>Korea Standard Time</key> <string>Asia/Seoul</string>"
575 " <key>Mexico</key> <string>America/Mexico_City</string>"
576 " <key>Mexico Standard Time</key> <string>America/Mexico_City</string>"
577 " <key>Mexico Standard Time 2</key> <string>America/Chihuahua</string>"
578 " <key>Mid-Atlantic</key> <string>Atlantic/South_Georgia</string>"
579 " <key>Mid-Atlantic Standard Time</key> <string>Atlantic/South_Georgia</string>"
580 " <key>Middle East Standard Time</key> <string>Asia/Beirut</string>"
581 " <key>Mountain</key> <string>America/Denver</string>"
582 " <key>Mountain Standard Time</key> <string>America/Denver</string>"
583 " <key>Mountain Standard Time (Mexico)</key> <string>America/Chihuahua</string>"
584 " <key>Myanmar Standard Time</key> <string>Asia/Rangoon</string>"
585 " <key>N. Central Asia Standard Time</key> <string>Asia/Novosibirsk</string>"
586 " <key>Namibia Standard Time</key> <string>Africa/Windhoek</string>"
587 " <key>Nepal Standard Time</key> <string>Asia/Katmandu</string>"
588 " <key>New Zealand</key> <string>Pacific/Auckland</string>"
589 " <key>New Zealand Standard Time</key> <string>Pacific/Auckland</string>"
590 " <key>Newfoundland</key> <string>America/St_Johns</string>"
591 " <key>Newfoundland Standard Time</key> <string>America/St_Johns</string>"
592 " <key>North Asia East Standard Time</key> <string>Asia/Ulaanbaatar</string>"
593 " <key>North Asia Standard Time</key> <string>Asia/Krasnoyarsk</string>"
594 " <key>Pacific</key> <string>America/Los_Angeles</string>"
595 " <key>Pacific SA</key> <string>America/Santiago</string>"
596 " <key>Pacific SA Standard Time</key> <string>America/Santiago</string>"
597 " <key>Pacific Standard Time</key> <string>America/Los_Angeles</string>"
598 " <key>Pacific Standard Time (Mexico)</key> <string>America/Tijuana</string>"
599 " <key>Prague Bratislava</key> <string>Europe/Prague</string>"
600 " <key>Romance</key> <string>Europe/Paris</string>"
601 " <key>Romance Standard Time</key> <string>Europe/Paris</string>"
602 " <key>Russian</key> <string>Europe/Moscow</string>"
603 " <key>Russian Standard Time</key> <string>Europe/Moscow</string>"
604 " <key>SA Eastern</key> <string>America/Buenos_Aires</string>"
605 " <key>SA Eastern Standard Time</key> <string>America/Buenos_Aires</string>"
606 " <key>SA Pacific</key> <string>America/Bogota</string>"
607 " <key>SA Pacific Standard Time</key> <string>America/Bogota</string>"
608 " <key>SA Western</key> <string>America/Caracas</string>"
609 " <key>SA Western Standard Time</key> <string>America/Caracas</string>"
610 " <key>Samoa</key> <string>Pacific/Apia</string>"
611 " <key>Samoa Standard Time</key> <string>Pacific/Apia</string>"
612 " <key>Saudi Arabia</key> <string>Asia/Riyadh</string>"
613 " <key>Saudi Arabia Standard Time</key> <string>Asia/Riyadh</string>"
614 " <key>SE Asia Standard Time</key> <string>Asia/Bangkok</string>"
615 " <key>Singapore</key> <string>Asia/Singapore</string>"
616 " <key>Singapore Standard Time</key> <string>Asia/Singapore</string>"
617 " <key>South Africa</key> <string>Africa/Harare</string>"
618 " <key>South Africa Standard Time</key> <string>Africa/Harare</string>"
619 " <key>Sri Lanka</key> <string>Asia/Colombo</string>"
620 " <key>Sri Lanka Standard Time</key> <string>Asia/Colombo</string>"
621 " <key>Sydney Standard Time</key> <string>Australia/Sydney</string>"
622 " <key>Taipei</key> <string>Asia/Taipei</string>"
623 " <key>Taipei Standard Time</key> <string>Asia/Taipei</string>"
624 " <key>Tasmania</key> <string>Australia/Hobart</string>"
625 " <key>Tasmania Standard Time</key> <string>Australia/Hobart</string>"
626 " <key>Tasmania Standard Time</key> <string>Australia/Hobart</string>"
627 " <key>Tokyo</key> <string>Asia/Tokyo</string>"
628 " <key>Tokyo Standard Time</key> <string>Asia/Tokyo</string>"
629 " <key>Tonga Standard Time</key> <string>Pacific/Tongatapu</string>"
630 " <key>US Eastern</key> <string>America/Indianapolis</string>"
631 " <key>US Eastern Standard Time</key> <string>America/Indianapolis</string>"
632 " <key>US Mountain</key> <string>America/Phoenix</string>"
633 " <key>US Mountain Standard Time</key> <string>America/Phoenix</string>"
634 " <key>Vladivostok</key> <string>Asia/Vladivostok</string>"
635 " <key>Vladivostok Standard Time</key> <string>Asia/Vladivostok</string>"
636 " <key>W. Australia</key> <string>Australia/Perth</string>"
637 " <key>W. Australia Standard Time</key> <string>Australia/Perth</string>"
638 " <key>W. Central Africa Standard Time</key> <string>Africa/Luanda</string>"
639 " <key>W. Europe</key> <string>Europe/Berlin</string>"
640 " <key>W. Europe Standard Time</key> <string>Europe/Berlin</string>"
641 " <key>Warsaw</key> <string>Europe/Warsaw</string>"
642 " <key>West Asia</key> <string>Asia/Karachi</string>"
643 " <key>West Asia Standard Time</key> <string>Asia/Karachi</string>"
644 " <key>West Pacific</key> <string>Pacific/Guam</string>"
645 " <key>West Pacific Standard Time</key> <string>Pacific/Guam</string>"
646 " <key>Western Brazilian Standard Time</key> <string>America/Rio_Branco</string>"
647 " <key>Yakutsk</key> <string>Asia/Yakutsk</string>"
651 CF_INLINE
void __CFTimeZoneLockWinToOlson(void) {
652 __CFSpinLock(&__CFTimeZoneWinToOlsonLock
);
655 CF_INLINE
void __CFTimeZoneUnlockWinToOlson(void) {
656 __CFSpinUnlock(&__CFTimeZoneWinToOlsonLock
);
659 CFDictionaryRef
CFTimeZoneCopyWinToOlsonDictionary(void) {
660 CFDictionaryRef dict
;
661 __CFTimeZoneLockWinToOlson();
662 if (NULL
== __CFTimeZoneWinToOlsonDict
) {
663 CFDataRef data
= CFDataCreate(kCFAllocatorSystemDefault
, (uint8_t *)__CFTimeZoneWinToOlsonDefaults
, strlen(__CFTimeZoneWinToOlsonDefaults
));
664 __CFTimeZoneWinToOlsonDict
= (CFDictionaryRef
)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault
, data
, kCFPropertyListImmutable
, NULL
);
667 if (NULL
== __CFTimeZoneWinToOlsonDict
) {
668 __CFTimeZoneWinToOlsonDict
= CFDictionaryCreate(kCFAllocatorSystemDefault
, NULL
, NULL
, 0, NULL
, NULL
);
670 dict
= __CFTimeZoneWinToOlsonDict
? (CFDictionaryRef
)CFRetain(__CFTimeZoneWinToOlsonDict
) : NULL
;
671 __CFTimeZoneUnlockWinToOlson();
675 void CFTimeZoneSetWinToOlsonDictionary(CFDictionaryRef dict
) {
676 __CFGenericValidateType(dict
, CFDictionaryGetTypeID());
677 __CFTimeZoneLockWinToOlson();
678 if (dict
!= __CFTimeZoneWinToOlsonDict
) {
679 if (dict
) CFRetain(dict
);
680 if (__CFTimeZoneWinToOlsonDict
) CFRelease(__CFTimeZoneWinToOlsonDict
);
681 __CFTimeZoneWinToOlsonDict
= dict
;
683 __CFTimeZoneUnlockWinToOlson();
686 CFTimeZoneRef
CFTimeZoneCreateWithWindowsName(CFAllocatorRef allocator
, CFStringRef winName
) {
687 if (!winName
) return NULL
;
689 CFDictionaryRef winToOlson
= CFTimeZoneCopyWinToOlsonDictionary();
690 if (!winToOlson
) return NULL
;
692 CFStringRef olsonName
= CFDictionaryGetValue(winToOlson
, winName
);
693 CFTimeZoneRef retval
= NULL
;
695 retval
= CFTimeZoneCreateWithName(allocator
, olsonName
, false);
697 CFRelease(winToOlson
);
701 extern CFStringRef
_CFGetWindowsAppleSystemLibraryDirectory(void);
702 void __InitTZStrings(void) {
703 static CFSpinLock_t __CFTZDirLock
= CFSpinLockInit
;
704 __CFSpinLock(&__CFTZDirLock
);
706 CFStringRef winDir
= _CFGetWindowsAppleSystemLibraryDirectory();
707 __tzZoneInfo
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@\\etc\\zoneinfo"), winDir
);
709 if (!__tzDir
&& __tzZoneInfo
) {
710 int length
= CFStringGetLength(__tzZoneInfo
) + sizeof("\\zone.tab") + 1;
711 __tzDir
= malloc(length
); // If we don't use ascii, we'll need to malloc more space
712 if (!__tzDir
|| !CFStringGetCString(__tzZoneInfo
, __tzDir
, length
, kCFStringEncodingASCII
)) {
715 strcat(__tzDir
, "\\zone.tab");
718 __CFSpinUnlock(&__CFTZDirLock
);
722 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
723 static CFTimeZoneRef
__CFTimeZoneCreateSystem(void) {
724 CFTimeZoneRef result
= NULL
;
726 #if DEPLOYMENT_TARGET_WINDOWS_SYNC
727 CFStringRef name
= NULL
;
728 TIME_ZONE_INFORMATION tzi
= { 0 };
729 DWORD rval
= GetTimeZoneInformation(&tzi
);
730 if (rval
!= TIME_ZONE_ID_INVALID
) {
731 LPWSTR standardName
= (LPWSTR
)&tzi
.StandardName
;
732 CFStringRef cfStandardName
= CFStringCreateWithBytes(kCFAllocatorSystemDefault
, (UInt8
*)standardName
, wcslen(standardName
)*sizeof(WCHAR
), kCFStringEncodingUTF16LE
, false);
733 if (cfStandardName
) {
734 CFDictionaryRef winToOlson
= CFTimeZoneCopyWinToOlsonDictionary();
736 name
= CFDictionaryGetValue(winToOlson
, cfStandardName
);
737 if (name
) CFRetain(name
);
738 CFRelease(winToOlson
);
740 CFRelease(cfStandardName
);
743 CFLog(kCFLogLevelError
, CFSTR("Couldn't get time zone information error %d"), GetLastError());
749 char linkbuf
[CFMaxPathSize
];
751 tzenv
= __CFgetenv("TZFILE");
753 CFStringRef name
= CFStringCreateWithBytes(kCFAllocatorSystemDefault
, (uint8_t *)tzenv
, strlen(tzenv
), kCFStringEncodingUTF8
, false);
754 result
= CFTimeZoneCreateWithName(kCFAllocatorSystemDefault
, name
, false);
756 if (result
) return result
;
758 tzenv
= __CFgetenv("TZ");
760 CFStringRef name
= CFStringCreateWithBytes(kCFAllocatorSystemDefault
, (uint8_t *)tzenv
, strlen(tzenv
), kCFStringEncodingUTF8
, false);
761 result
= CFTimeZoneCreateWithName(kCFAllocatorSystemDefault
, name
, true);
763 if (result
) return result
;
765 ret
= readlink(TZZONELINK
, linkbuf
, sizeof(linkbuf
));
769 if (strncmp(linkbuf
, TZZONEINFO
, sizeof(TZZONEINFO
) - 1) == 0) {
770 name
= CFStringCreateWithBytes(kCFAllocatorSystemDefault
, (uint8_t *)linkbuf
+ sizeof(TZZONEINFO
) - 1, strlen(linkbuf
) - sizeof(TZZONEINFO
) + 1, kCFStringEncodingUTF8
, false);
772 name
= CFStringCreateWithBytes(kCFAllocatorSystemDefault
, (uint8_t *)linkbuf
, strlen(linkbuf
), kCFStringEncodingUTF8
, false);
776 result
= CFTimeZoneCreateWithName(kCFAllocatorSystemDefault
, name
, false);
778 if (result
) return result
;
780 return CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorSystemDefault
, 0.0);
782 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
783 static CFTimeZoneRef
__CFTimeZoneCreateSystem(void) {
784 CFTimeZoneRef result
= NULL
;
785 /* The GetTimeZoneInformation function retrieves the current
786 * time-zone parameters for Win32
787 * (Aleksey Dukhnyakov)
790 TIME_ZONE_INFORMATION tz
;
792 dw_result
=GetTimeZoneInformation(&tz
);
794 if ( dw_result
== TIME_ZONE_ID_STANDARD
||
795 dw_result
== TIME_ZONE_ID_DAYLIGHT
) {
796 CFStringRef name
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (const UniChar
*)tz
.StandardName
, wcslen(tz
.StandardName
));
797 data
= CFDataCreate(kCFAllocatorSystemDefault
, (UInt8
*)&tz
, sizeof(tz
));
798 result
= CFTimeZoneCreate(kCFAllocatorSystemDefault
, name
, data
);
801 if (result
) return result
;
803 return CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorSystemDefault
, 0.0);
806 #error Unknown or unspecified DEPLOYMENT_TARGET
809 CFTimeZoneRef
CFTimeZoneCopySystem(void) {
811 __CFTimeZoneLockGlobal();
812 if (NULL
== __CFTimeZoneSystem
) {
813 __CFTimeZoneUnlockGlobal();
814 tz
= __CFTimeZoneCreateSystem();
815 __CFTimeZoneLockGlobal();
816 if (NULL
== __CFTimeZoneSystem
) {
817 __CFTimeZoneSystem
= tz
;
819 if (tz
) CFRelease(tz
);
822 tz
= __CFTimeZoneSystem
? (CFTimeZoneRef
)CFRetain(__CFTimeZoneSystem
) : NULL
;
823 __CFTimeZoneUnlockGlobal();
827 static CFIndex __noteCount
= 0;
829 void CFTimeZoneResetSystem(void) {
830 __CFTimeZoneLockGlobal();
831 if (__CFTimeZoneDefault
== __CFTimeZoneSystem
) {
832 if (__CFTimeZoneDefault
) CFRelease(__CFTimeZoneDefault
);
833 __CFTimeZoneDefault
= NULL
;
835 CFTimeZoneRef tz
= __CFTimeZoneSystem
;
836 __CFTimeZoneSystem
= NULL
;
837 __CFTimeZoneUnlockGlobal();
838 if (tz
) CFRelease(tz
);
841 CFIndex
_CFTimeZoneGetNoteCount(void) {
845 CFTimeZoneRef
CFTimeZoneCopyDefault(void) {
847 __CFTimeZoneLockGlobal();
848 if (NULL
== __CFTimeZoneDefault
) {
849 __CFTimeZoneUnlockGlobal();
850 tz
= CFTimeZoneCopySystem();
851 __CFTimeZoneLockGlobal();
852 if (NULL
== __CFTimeZoneDefault
) {
853 __CFTimeZoneDefault
= tz
;
855 if (tz
) CFRelease(tz
);
858 tz
= __CFTimeZoneDefault
? (CFTimeZoneRef
)CFRetain(__CFTimeZoneDefault
) : NULL
;
859 __CFTimeZoneUnlockGlobal();
863 void CFTimeZoneSetDefault(CFTimeZoneRef tz
) {
864 if (tz
) __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
865 __CFTimeZoneLockGlobal();
866 if (tz
!= __CFTimeZoneDefault
) {
867 if (tz
) CFRetain(tz
);
868 if (__CFTimeZoneDefault
) CFRelease(__CFTimeZoneDefault
);
869 __CFTimeZoneDefault
= tz
;
871 __CFTimeZoneUnlockGlobal();
874 static CFDictionaryRef
__CFTimeZoneCopyCompatibilityDictionary(void);
876 CFArrayRef
CFTimeZoneCopyKnownNames(void) {
878 __CFTimeZoneLockGlobal();
879 if (NULL
== __CFKnownTimeZoneList
) {
880 CFMutableArrayRef list
;
881 /* TimeZone information locate in the registry for Win32
882 * (Aleksey Dukhnyakov)
884 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
885 list
= __CFCopyRecursiveDirectoryList();
886 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
887 list
= __CFCopyWindowsTimeZoneList();
889 #error Unknown or unspecified DEPLOYMENT_TARGET
891 // Remove undesirable ancient cruft
892 CFDictionaryRef dict
= __CFTimeZoneCopyCompatibilityDictionary();
894 for (idx
= CFArrayGetCount(list
); idx
--; ) {
895 CFStringRef item
= (CFStringRef
)CFArrayGetValueAtIndex(list
, idx
);
896 if (CFDictionaryContainsKey(dict
, item
)) {
897 CFArrayRemoveValueAtIndex(list
, idx
);
900 __CFKnownTimeZoneList
= CFArrayCreateCopy(kCFAllocatorSystemDefault
, list
);
903 tzs
= __CFKnownTimeZoneList
? (CFArrayRef
)CFRetain(__CFKnownTimeZoneList
) : NULL
;
904 __CFTimeZoneUnlockGlobal();
908 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
909 /* The criteria here are sort of: coverage for the U.S. and Europe,
910 * large cities, abbreviation uniqueness, and perhaps a few others.
911 * But do not make the list too large with obscure information.
913 static const char *__CFTimeZoneAbbreviationDefaults
=
914 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
915 " <!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">"
916 " <plist version=\"1.0\">"
918 " <key>ADT</key> <string>America/Halifax</string>"
919 " <key>AKDT</key> <string>America/Juneau</string>"
920 " <key>AKST</key> <string>America/Juneau</string>"
921 " <key>ART</key> <string>America/Argentina/Buenos_Aires</string>"
922 " <key>AST</key> <string>America/Halifax</string>"
923 " <key>BDT</key> <string>Asia/Dhaka</string>"
924 " <key>BRST</key> <string>America/Sao_Paulo</string>"
925 " <key>BRT</key> <string>America/Sao_Paulo</string>"
926 " <key>BST</key> <string>Europe/London</string>"
927 " <key>CAT</key> <string>Africa/Harare</string>"
928 " <key>CDT</key> <string>America/Chicago</string>"
929 " <key>CEST</key> <string>Europe/Paris</string>"
930 " <key>CET</key> <string>Europe/Paris</string>"
931 " <key>CLST</key> <string>America/Santiago</string>"
932 " <key>CLT</key> <string>America/Santiago</string>"
933 " <key>COT</key> <string>America/Bogota</string>"
934 " <key>CST</key> <string>America/Chicago</string>"
935 " <key>EAT</key> <string>Africa/Addis_Ababa</string>"
936 " <key>EDT</key> <string>America/New_York</string>"
937 " <key>EEST</key> <string>Europe/Istanbul</string>"
938 " <key>EET</key> <string>Europe/Istanbul</string>"
939 " <key>EST</key> <string>America/New_York</string>"
940 " <key>GMT</key> <string>GMT</string>"
941 " <key>GST</key> <string>Asia/Dubai</string>"
942 " <key>HKT</key> <string>Asia/Hong_Kong</string>"
943 " <key>HST</key> <string>Pacific/Honolulu</string>"
944 " <key>ICT</key> <string>Asia/Bangkok</string>"
945 " <key>IRST</key> <string>Asia/Tehran</string>"
946 " <key>IST</key> <string>Asia/Calcutta</string>"
947 " <key>JST</key> <string>Asia/Tokyo</string>"
948 " <key>KST</key> <string>Asia/Seoul</string>"
949 " <key>MDT</key> <string>America/Denver</string>"
950 " <key>MSD</key> <string>Europe/Moscow</string>"
951 " <key>MSK</key> <string>Europe/Moscow</string>"
952 " <key>MST</key> <string>America/Denver</string>"
953 " <key>NZDT</key> <string>Pacific/Auckland</string>"
954 " <key>NZST</key> <string>Pacific/Auckland</string>"
955 " <key>PDT</key> <string>America/Los_Angeles</string>"
956 " <key>PET</key> <string>America/Lima</string>"
957 " <key>PHT</key> <string>Asia/Manila</string>"
958 " <key>PKT</key> <string>Asia/Karachi</string>"
959 " <key>PST</key> <string>America/Los_Angeles</string>"
960 " <key>SGT</key> <string>Asia/Singapore</string>"
961 " <key>UTC</key> <string>UTC</string>"
962 " <key>WAT</key> <string>Africa/Lagos</string>"
963 " <key>WEST</key> <string>Europe/Lisbon</string>"
964 " <key>WET</key> <string>Europe/Lisbon</string>"
965 " <key>WIT</key> <string>Asia/Jakarta</string>"
968 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
969 static const char *__CFTimeZoneAbbreviationDefaults
=
970 /* Mappings to time zones in Windows Registry are best-guess */
971 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
972 " <!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">"
973 " <plist version=\"1.0\">"
975 " <key>ADT</key> <string>Atlantic Standard Time</string>"
976 " <key>AKDT</key> <string>Alaskan Standard Time</string>"
977 " <key>AKST</key> <string>Alaskan Standard Time</string>"
978 " <key>ART</key> <string>SA Eastern Standard Time</string>"
979 " <key>AST</key> <string>Atlantic Standard Time</string>"
980 " <key>BDT</key> <string>Central Asia Standard Time</string>"
981 " <key>BRST</key> <string>SA Eastern Standard Time</string>"
982 " <key>BRT</key> <string>SA Eastern Standard Time</string>"
983 " <key>BST</key> <string>GMT Standard Time</string>"
984 " <key>CAT</key> <string>South Africa Standard Time</string>"
985 " <key>CDT</key> <string>Central Standard Time</string>"
986 " <key>CEST</key> <string>Central Europe Standard Time</string>"
987 " <key>CET</key> <string>Central Europe Standard Time</string>"
988 " <key>CLST</key> <string>SA Western Standard Time</string>"
989 " <key>CLT</key> <string>SA Western Standard Time</string>"
990 " <key>COT</key> <string>Central Standard Time</string>"
991 " <key>CST</key> <string>Central Standard Time</string>"
992 " <key>EAT</key> <string>E. Africa Standard Time</string>"
993 " <key>EDT</key> <string>Eastern Standard Time</string>"
994 " <key>EEST</key> <string>E. Europe Standard Time</string>"
995 " <key>EET</key> <string>E. Europe Standard Time</string>"
996 " <key>EST</key> <string>Eastern Standard Time</string>"
997 " <key>GMT</key> <string>Greenwich Standard Time</string>"
998 " <key>GST</key> <string>Arabian Standard Time</string>"
999 " <key>HKT</key> <string>China Standard Time</string>"
1000 " <key>HST</key> <string>Hawaiian Standard Time</string>"
1001 " <key>ICT</key> <string>SE Asia Standard Time</string>"
1002 " <key>IRST</key> <string>Iran Standard Time</string>"
1003 " <key>IST</key> <string>India Standard Time</string>"
1004 " <key>JST</key> <string>Tokyo Standard Time</string>"
1005 " <key>KST</key> <string>Korea Standard Time</string>"
1006 " <key>MDT</key> <string>Mountain Standard Time</string>"
1007 " <key>MSD</key> <string>E. Europe Standard Time</string>"
1008 " <key>MSK</key> <string>E. Europe Standard Time</string>"
1009 " <key>MST</key> <string>Mountain Standard Time</string>"
1010 " <key>NZDT</key> <string>New Zealand Standard Time</string>"
1011 " <key>NZST</key> <string>New Zealand Standard Time</string>"
1012 " <key>PDT</key> <string>Pacific Standard Time</string>"
1013 " <key>PET</key> <string>SA Pacific Standard Time</string>"
1014 " <key>PHT</key> <string>Taipei Standard Time</string>"
1015 " <key>PKT</key> <string>West Asia Standard Time</string>"
1016 " <key>PST</key> <string>Pacific Standard Time</string>"
1017 " <key>SGT</key> <string>Singapore Standard Time</string>"
1018 " <key>UTC</key> <string>Greenwich Standard Time</string>"
1019 " <key>WAT</key> <string>W. Central Africa Standard Time</string>"
1020 " <key>WEST</key> <string>W. Europe Standard Time</string>"
1021 " <key>WET</key> <string>W. Europe Standard Time</string>"
1022 " <key>WIT</key> <string>SE Asia Standard Time</string>"
1026 #error Unknown or unspecified DEPLOYMENT_TARGET
1029 CFDictionaryRef
CFTimeZoneCopyAbbreviationDictionary(void) {
1030 CFDictionaryRef dict
;
1031 __CFTimeZoneLockAbbreviations();
1032 if (NULL
== __CFTimeZoneAbbreviationDict
) {
1033 CFDataRef data
= CFDataCreate(kCFAllocatorSystemDefault
, (uint8_t *)__CFTimeZoneAbbreviationDefaults
, strlen(__CFTimeZoneAbbreviationDefaults
));
1034 __CFTimeZoneAbbreviationDict
= (CFDictionaryRef
)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault
, data
, kCFPropertyListImmutable
, NULL
);
1037 if (NULL
== __CFTimeZoneAbbreviationDict
) {
1038 __CFTimeZoneAbbreviationDict
= CFDictionaryCreate(kCFAllocatorSystemDefault
, NULL
, NULL
, 0, NULL
, NULL
);
1040 dict
= __CFTimeZoneAbbreviationDict
? (CFDictionaryRef
)CFRetain(__CFTimeZoneAbbreviationDict
) : NULL
;
1041 __CFTimeZoneUnlockAbbreviations();
1045 void CFTimeZoneSetAbbreviationDictionary(CFDictionaryRef dict
) {
1046 __CFGenericValidateType(dict
, CFDictionaryGetTypeID());
1047 __CFTimeZoneLockGlobal();
1048 if (dict
!= __CFTimeZoneAbbreviationDict
) {
1049 if (dict
) CFRetain(dict
);
1050 if (__CFTimeZoneAbbreviationDict
) {
1051 for (id key
in (id
)__CFTimeZoneAbbreviationDict
) {
1052 CFDictionaryRemoveValue(__CFTimeZoneCache
, (CFStringRef
)key
);
1054 CFRelease(__CFTimeZoneAbbreviationDict
);
1056 __CFTimeZoneAbbreviationDict
= dict
;
1058 __CFTimeZoneUnlockGlobal();
1061 CFTimeZoneRef
CFTimeZoneCreate(CFAllocatorRef allocator
, CFStringRef name
, CFDataRef data
) {
1062 // assert: (NULL != name && NULL != data);
1063 CFTimeZoneRef memory
;
1065 CFTZPeriod
*tzp
= NULL
;
1066 CFIndex idx
, cnt
= 0;
1068 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
1069 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
1070 __CFGenericValidateType(name
, CFStringGetTypeID());
1071 __CFGenericValidateType(data
, CFDataGetTypeID());
1072 __CFTimeZoneLockGlobal();
1073 if (NULL
!= __CFTimeZoneCache
&& CFDictionaryGetValueIfPresent(__CFTimeZoneCache
, name
, (const void **)&memory
)) {
1074 __CFTimeZoneUnlockGlobal();
1075 return (CFTimeZoneRef
)CFRetain(memory
);
1077 if (!__CFParseTimeZoneData(allocator
, data
, &tzp
, &cnt
)) {
1078 __CFTimeZoneUnlockGlobal();
1081 size
= sizeof(struct __CFTimeZone
) - sizeof(CFRuntimeBase
);
1082 memory
= (CFTimeZoneRef
)_CFRuntimeCreateInstance(allocator
, CFTimeZoneGetTypeID(), size
, NULL
);
1083 if (NULL
== memory
) {
1084 __CFTimeZoneUnlockGlobal();
1085 for (idx
= 0; idx
< cnt
; idx
++) {
1086 if (NULL
!= tzp
[idx
].abbrev
) CFRelease(tzp
[idx
].abbrev
);
1088 if (NULL
!= tzp
) CFAllocatorDeallocate(allocator
, tzp
);
1091 ((struct __CFTimeZone
*)memory
)->_name
= (CFStringRef
)CFStringCreateCopy(allocator
, name
);
1092 ((struct __CFTimeZone
*)memory
)->_data
= CFDataCreateCopy(allocator
, data
);
1093 ((struct __CFTimeZone
*)memory
)->_periods
= tzp
;
1094 ((struct __CFTimeZone
*)memory
)->_periodCnt
= cnt
;
1095 if (NULL
== __CFTimeZoneCache
) {
1096 __CFTimeZoneCache
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
1098 CFDictionaryAddValue(__CFTimeZoneCache
, ((struct __CFTimeZone
*)memory
)->_name
, memory
);
1099 __CFTimeZoneUnlockGlobal();
1103 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
1104 static CFTimeZoneRef
__CFTimeZoneCreateFixed(CFAllocatorRef allocator
, int32_t seconds
, CFStringRef name
, int isDST
) {
1105 CFTimeZoneRef result
;
1107 int32_t nameLen
= CFStringGetLength(name
);
1108 unsigned char dataBytes
[52 + nameLen
+ 1];
1109 memset(dataBytes
, 0, sizeof(dataBytes
));
1111 // Put in correct magic bytes for timezone structures
1117 __CFEntzcode(1, dataBytes
+ 20);
1118 __CFEntzcode(1, dataBytes
+ 24);
1119 __CFEntzcode(1, dataBytes
+ 36);
1120 __CFEntzcode(nameLen
+ 1, dataBytes
+ 40);
1121 __CFEntzcode(seconds
, dataBytes
+ 44);
1122 dataBytes
[48] = isDST
? 1 : 0;
1123 CFStringGetCString(name
, (char *)dataBytes
+ 50, nameLen
+ 1, kCFStringEncodingASCII
);
1124 data
= CFDataCreate(allocator
, dataBytes
, 52 + nameLen
+ 1);
1125 result
= CFTimeZoneCreate(allocator
, name
, data
);
1129 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
1130 static CFTimeZoneRef
__CFTimeZoneCreateFixed(CFAllocatorRef allocator
, int32_t seconds
, CFStringRef name
, int isDST
) {
1131 /* CFTimeZoneRef->_data will contain TIME_ZONE_INFORMATION structure
1132 * to find current timezone
1133 * (Aleksey Dukhnyakov)
1135 CFTimeZoneRef result
;
1136 TIME_ZONE_INFORMATION tzi
;
1138 CFIndex length
= CFStringGetLength(name
);
1140 memset(&tzi
,0,sizeof(tzi
));
1141 tzi
.Bias
=(long)(-seconds
/60);
1142 CFStringGetCharacters(name
, CFRangeMake(0, length
< 31 ? length
: 31 ), (UniChar
*)tzi
.StandardName
);
1143 data
= CFDataCreate(allocator
,(UInt8
*)&tzi
, sizeof(tzi
));
1144 result
= CFTimeZoneCreate(allocator
, name
, data
);
1149 #error Unknown or unspecified DEPLOYMENT_TARGET
1152 // rounds offset to nearest minute
1153 CFTimeZoneRef
CFTimeZoneCreateWithTimeIntervalFromGMT(CFAllocatorRef allocator
, CFTimeInterval ti
) {
1154 CFTimeZoneRef result
;
1156 int32_t seconds
, minute
, hour
;
1157 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
1158 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
1159 if (ti
< -18.0 * 3600 || 18.0 * 3600 < ti
) return NULL
;
1160 ti
= (ti
< 0.0) ? ceil((ti
/ 60.0) - 0.5) * 60.0 : floor((ti
/ 60.0) + 0.5) * 60.0;
1161 seconds
= (int32_t)ti
;
1162 hour
= (ti
< 0) ? (-seconds
/ 3600) : (seconds
/ 3600);
1163 seconds
-= ((ti
< 0) ? -hour
: hour
) * 3600;
1164 minute
= (ti
< 0) ? (-seconds
/ 60) : (seconds
/ 60);
1165 if (fabs(ti
) < 1.0) {
1166 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
1167 name
= (CFStringRef
)CFRetain(CFSTR("GMT"));
1168 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
1169 name
= (CFStringRef
)CFRetain(CFSTR("Greenwich Standard Time"));
1171 #error Unknown or unspecified DEPLOYMENT_TARGET
1174 name
= CFStringCreateWithFormat(allocator
, NULL
, CFSTR("GMT%c%02d%02d"), (ti
< 0.0 ? '-' : '+'), hour
, minute
);
1176 result
= __CFTimeZoneCreateFixed(allocator
, (int32_t)ti
, name
, 0);
1181 CFTimeZoneRef
CFTimeZoneCreateWithName(CFAllocatorRef allocator
, CFStringRef name
, Boolean tryAbbrev
) {
1182 CFTimeZoneRef result
= NULL
;
1183 CFStringRef tzName
= NULL
;
1184 CFDataRef data
= NULL
;
1186 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
1187 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
1188 __CFGenericValidateType(name
, CFStringGetTypeID());
1189 if (CFEqual(CFSTR(""), name
)) {
1190 // empty string is not a time zone name, just abort now,
1191 // following stuff will fail anyway
1194 __CFTimeZoneLockGlobal();
1195 if (NULL
!= __CFTimeZoneCache
&& CFDictionaryGetValueIfPresent(__CFTimeZoneCache
, name
, (const void **)&result
)) {
1196 __CFTimeZoneUnlockGlobal();
1197 return (CFTimeZoneRef
)CFRetain(result
);
1199 __CFTimeZoneUnlockGlobal();
1200 CFIndex len
= CFStringGetLength(name
);
1201 if (6 == len
|| 8 == len
) {
1203 CFStringGetCharacters(name
, CFRangeMake(0, len
), buffer
);
1204 if ('G' == buffer
[0] && 'M' == buffer
[1] && 'T' == buffer
[2] && ('+' == buffer
[3] || '-' == buffer
[3])) {
1205 if (('0' <= buffer
[4] && buffer
[4] <= '9') && ('0' <= buffer
[5] && buffer
[5] <= '9')) {
1206 int32_t hours
= (buffer
[4] - '0') * 10 + (buffer
[5] - '0');
1207 if (-14 <= hours
&& hours
<= 14) {
1208 CFTimeInterval ti
= hours
* 3600.0;
1210 return CFTimeZoneCreateWithTimeIntervalFromGMT(allocator
, ('-' == buffer
[3] ? -1.0 : 1.0) * ti
);
1212 if (('0' <= buffer
[6] && buffer
[6] <= '9') && ('0' <= buffer
[7] && buffer
[7] <= '9')) {
1213 int32_t minutes
= (buffer
[6] - '0') * 10 + (buffer
[7] - '0');
1214 if ((-14 == hours
&& 0 == minutes
) || (14 == hours
&& 0 == minutes
) || (0 <= minutes
&& minutes
<= 59)) {
1215 ti
= ti
+ minutes
* 60.0;
1216 return CFTimeZoneCreateWithTimeIntervalFromGMT(allocator
, ('-' == buffer
[3] ? -1.0 : 1.0) * ti
);
1224 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
1225 CFURLRef baseURL
, tempURL
;
1229 #if DEPLOYMENT_TARGET_WINDOWS_SYNC
1230 if (!__tzZoneInfo
) __InitTZStrings();
1231 if (!__tzZoneInfo
) return NULL
;
1232 baseURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, __tzZoneInfo
, kCFURLWindowsPathStyle
, true);
1234 baseURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, CFSTR(TZZONEINFO
), kCFURLPOSIXPathStyle
, true);
1237 CFDictionaryRef abbrevs
= CFTimeZoneCopyAbbreviationDictionary();
1238 tzName
= CFDictionaryGetValue(abbrevs
, name
);
1239 if (NULL
!= tzName
) {
1240 tempURL
= CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault
, baseURL
, tzName
, false);
1241 if (NULL
!= tempURL
) {
1242 if (_CFReadBytesFromFile(kCFAllocatorSystemDefault
, tempURL
, &bytes
, &length
, 0)) {
1243 data
= CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault
, bytes
, length
, kCFAllocatorSystemDefault
);
1251 CFDictionaryRef dict
= __CFTimeZoneCopyCompatibilityDictionary();
1252 CFStringRef mapping
= CFDictionaryGetValue(dict
, name
);
1255 #if DEPLOYMENT_TARGET_WINDOWS_SYNC
1256 } else if (CFStringHasPrefix(name
, __tzZoneInfo
)) {
1257 CFMutableStringRef unprefixed
= CFStringCreateMutableCopy(kCFAllocatorSystemDefault
, CFStringGetLength(name
), name
);
1258 CFStringDelete(unprefixed
, CFRangeMake(0, CFStringGetLength(__tzZoneInfo
)));
1260 } else if (CFStringHasPrefix(name
, CFSTR(TZZONEINFO
))) {
1261 CFMutableStringRef unprefixed
= CFStringCreateMutableCopy(kCFAllocatorSystemDefault
, CFStringGetLength(name
), name
);
1262 CFStringDelete(unprefixed
, CFRangeMake(0, sizeof(TZZONEINFO
)));
1264 mapping
= CFDictionaryGetValue(dict
, unprefixed
);
1268 CFRelease(unprefixed
);
1271 if (CFEqual(CFSTR(""), name
)) {
1277 tempURL
= CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault
, baseURL
, tzName
, false);
1278 if (NULL
!= tempURL
) {
1279 if (_CFReadBytesFromFile(kCFAllocatorSystemDefault
, tempURL
, &bytes
, &length
, 0)) {
1280 data
= CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault
, bytes
, length
, kCFAllocatorSystemDefault
);
1287 result
= CFTimeZoneCreate(allocator
, tzName
, data
);
1288 if (name
!= tzName
) {
1289 CFStringRef nameCopy
= (CFStringRef
)CFStringCreateCopy(allocator
, name
);
1290 __CFTimeZoneLockGlobal();
1291 CFDictionaryAddValue(__CFTimeZoneCache
, nameCopy
, result
);
1292 __CFTimeZoneUnlockGlobal();
1293 CFRelease(nameCopy
);
1299 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
1300 /* Reading GMT offset and daylight flag from the registry
1302 * (Aleksey Dukhnyakov)
1305 CFStringRef safeName
= name
;
1310 SYSTEMTIME StandardDate
;
1311 SYSTEMTIME DaylightDate
;
1313 TIME_ZONE_INFORMATION tzi_system
;
1316 DWORD dwType
, dwSize
=sizeof(tzi
),
1317 dwSize_name1
=sizeof(tzi_system
.StandardName
),
1318 dwSize_name2
=sizeof(tzi_system
.DaylightName
);
1321 CFDictionaryRef abbrevs
= CFTimeZoneCopyAbbreviationDictionary();
1322 tzName
= (CFStringRef
)CFDictionaryGetValue(abbrevs
, name
);
1323 if (NULL
== tzName
) {
1331 /* Open regestry and move down to the TimeZone information
1333 if (RegOpenKey(HKEY_LOCAL_MACHINE
,_T(TZZONEINFO
),&hkResult
) !=
1337 /* Move down to specific TimeZone name
1339 #if defined(UNICODE)
1340 UniChar
*uniTimeZone
= (UniChar
*)CFStringGetCharactersPtr(name
);
1341 if (uniTimeZone
== NULL
) {
1342 // We need to extract the bytes out of the CFStringRef and create our own
1343 // UNICODE string to pass to the Win32 API - RegOpenKey.
1344 UInt8 uniBuff
[MAX_PATH
+2]; // adding +2 to handle Unicode-null termination /0/0.
1345 CFIndex usedBuff
= 0;
1346 CFIndex numChars
= CFStringGetBytes(name
, CFRangeMake(0, CFStringGetLength(name
)), kCFStringEncodingUnicode
, 0, FALSE
, uniBuff
, MAX_PATH
, &usedBuff
);
1347 if (numChars
== 0) {
1350 // NULL-terminate the newly created Unicode string.
1351 uniBuff
[usedBuff
] = '\0';
1352 uniBuff
[usedBuff
+1] = '\0';
1355 if (RegOpenKey(hkResult
, (LPCWSTR
)uniBuff
,&hkResult
) != ERROR_SUCCESS
) {
1359 if (RegOpenKey(hkResult
, (LPCWSTR
)uniTimeZone
,&hkResult
) != ERROR_SUCCESS
) {
1364 if (RegOpenKey(hkResult
,CFStringGetCStringPtr(name
, CFStringGetSystemEncoding()),&hkResult
) != ERROR_SUCCESS
) {
1369 /* TimeZone information(offsets, daylight flag, ...) assign to tzi structure
1371 if ( RegQueryValueEx(hkResult
,_T("TZI"),NULL
,&dwType
,(LPBYTE
)&tzi
,&dwSize
) != ERROR_SUCCESS
&&
1372 RegQueryValueEx(hkResult
,_T("Std"),NULL
,&dwType
,(LPBYTE
)&tzi_system
.StandardName
,&dwSize_name1
) != ERROR_SUCCESS
&&
1373 RegQueryValueEx(hkResult
,_T("Dlt"),NULL
,&dwType
,(LPBYTE
)&tzi_system
.DaylightName
,&dwSize_name2
) != ERROR_SUCCESS
)
1378 tzi_system
.Bias
=tzi
.Bias
;
1379 tzi_system
.StandardBias
=tzi
.StandardBias
;
1380 tzi_system
.DaylightBias
=tzi
.DaylightBias
;
1381 tzi_system
.StandardDate
=tzi
.StandardDate
;
1382 tzi_system
.DaylightDate
=tzi
.DaylightDate
;
1384 /* CFTimeZoneRef->_data will contain TIME_ZONE_INFORMATION structure
1385 * to find current timezone
1386 * (Aleksey Dukhnyakov)
1388 data
= CFDataCreate(allocator
,(UInt8
*)&tzi_system
, sizeof(tzi_system
));
1390 RegCloseKey(hkResult
);
1391 result
= CFTimeZoneCreate(allocator
, name
, data
);
1394 result
->_periods
->abbrev
= (CFStringRef
)CFStringCreateCopy(allocator
,safeName
);
1403 #error Unknown or unspecified DEPLOYMENT_TARGET
1406 CFStringRef
CFTimeZoneGetName(CFTimeZoneRef tz
) {
1407 CF_OBJC_FUNCDISPATCH0(CFTimeZoneGetTypeID(), CFStringRef
, tz
, "name");
1408 __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
1412 CFDataRef
CFTimeZoneGetData(CFTimeZoneRef tz
) {
1413 CF_OBJC_FUNCDISPATCH0(CFTimeZoneGetTypeID(), CFDataRef
, tz
, "data");
1414 __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
1418 /* This function converts CFAbsoluteTime to (Win32) SYSTEMTIME
1419 * (Aleksey Dukhnyakov)
1421 #if DEPLOYMENT_TARGET_WINDOWS
1422 BOOL
__CFTimeZoneGetWin32SystemTime(SYSTEMTIME
* sys_time
, CFAbsoluteTime time
)
1425 FILETIME
* ftime
=(FILETIME
*)&l
;
1427 /* seconds between 1601 and 1970 : 11644473600,
1428 * seconds between 1970 and 2001 : 978307200,
1429 * FILETIME - number of 100-nanosecond intervals since January 1, 1601
1431 l
=(LONGLONG
)(time
+11644473600LL+978307200)*10000000;
1432 if (FileTimeToSystemTime(ftime
,sys_time
))
1437 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
1439 #error Unknown or unspecified DEPLOYMENT_TARGET
1442 CFTimeInterval
CFTimeZoneGetSecondsFromGMT(CFTimeZoneRef tz
, CFAbsoluteTime at
) {
1443 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
1445 CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), CFTimeInterval
, tz
, "_secondsFromGMTForAbsoluteTime:", at
);
1446 __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
1447 idx
= __CFBSearchTZPeriods(tz
, at
);
1448 return __CFTZPeriodGMTOffset(&(tz
->_periods
[idx
]));
1449 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
1450 /* To calculate seconds from GMT, calculate current timezone time and
1451 * subtract GMT timnezone time
1452 * (Aleksey Dukhnyakov)
1454 TIME_ZONE_INFORMATION tzi
;
1455 FILETIME ftime1
,ftime2
;
1456 SYSTEMTIME stime0
,stime1
,stime2
;
1457 LONGLONG
* l1
= (LONGLONG
*)&ftime1
;
1458 LONGLONG
* l2
= (LONGLONG
*)&ftime2
;
1459 CFRange range
={0,sizeof(TIME_ZONE_INFORMATION
)};
1462 CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), CFTimeInterval
, tz
, "_secondsFromGMTForAbsoluteTime:", at
);
1464 CFDataGetBytes(tz
->_data
,range
,(UInt8
*)&tzi
);
1466 if (!__CFTimeZoneGetWin32SystemTime(&stime0
,at
) ||
1467 !SystemTimeToTzSpecificLocalTime(&tzi
,&stime0
,&stime1
) ||
1468 !SystemTimeToFileTime(&stime1
,&ftime1
) )
1470 CFAssert(0, __kCFLogAssertion
, "Win32 system time/timezone failed !\n");
1474 tzi
.DaylightDate
.wMonth
=0;
1475 tzi
.StandardDate
.wMonth
=0;
1480 if ( !SystemTimeToTzSpecificLocalTime(&tzi
,&stime0
,&stime2
) ||
1481 !SystemTimeToFileTime(&stime2
,&ftime2
))
1483 CFAssert(0, __kCFLogAssertion
, "Win32 system time/timezone failed !\n");
1486 result
=(double)((*l1
-*l2
)/10000000);
1489 #error Unknown or unspecified DEPLOYMENT_TARGET
1493 #if DEPLOYMENT_TARGET_WINDOWS_SAFARI
1495 * Get abbreviation for name for WIN32 platform
1496 * (Aleksey Dukhnyakov)
1504 static void _CFFindKeyForValue(const void *key
, const void *value
, void *context
) {
1505 if ( ((_CFAbbrFind
*)context
)->tzAbbr
!= NULL
) {
1506 if ( ((_CFAbbrFind
*)context
)->tzName
== (CFStringRef
) value
) {
1507 ((_CFAbbrFind
*)context
)->tzAbbr
= (CFStringRef
)key
;
1512 CFIndex
__CFTimeZoneInitAbbrev(CFTimeZoneRef tz
) {
1514 if ( tz
->_periods
->abbrev
== NULL
) {
1515 _CFAbbrFind abbr
= { NULL
, NULL
};
1516 CFDictionaryRef abbrevs
= CFTimeZoneCopyAbbreviationDictionary();
1518 CFDictionaryApplyFunction(abbrevs
, _CFFindKeyForValue
, &abbr
);
1520 if ( abbr
.tzAbbr
!= NULL
)
1521 tz
->_periods
->abbrev
= (CFStringRef
)CFStringCreateCopy(kCFAllocatorSystemDefault
, abbr
.tzAbbr
);
1523 tz
->_periods
->abbrev
= (CFStringRef
)CFStringCreateCopy(kCFAllocatorSystemDefault
, tz
->_name
);
1524 /* We should return name of TimeZone if couldn't find abbrevation.
1527 * (Aleksey Dukhnyakov)
1529 CFRelease( abbrevs
);
1534 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
1536 #error Unknown or unspecified DEPLOYMENT_TARGET
1539 CFStringRef
CFTimeZoneCopyAbbreviation(CFTimeZoneRef tz
, CFAbsoluteTime at
) {
1542 CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), CFStringRef
, tz
, "_abbreviationForAbsoluteTime:", at
);
1543 __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
1544 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
1545 idx
= __CFBSearchTZPeriods(tz
, at
);
1546 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
1548 * Initialize abbreviation for this TimeZone
1549 * (Aleksey Dukhnyakov)
1551 idx
= __CFTimeZoneInitAbbrev(tz
);
1553 #error Unknown or unspecified DEPLOYMENT_TARGET
1555 result
= __CFTZPeriodAbbreviation(&(tz
->_periods
[idx
]));
1556 return result
? (CFStringRef
)CFRetain(result
) : NULL
;
1559 Boolean
CFTimeZoneIsDaylightSavingTime(CFTimeZoneRef tz
, CFAbsoluteTime at
) {
1560 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
1562 CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), Boolean
, tz
, "_isDaylightSavingTimeForAbsoluteTime:", at
);
1563 __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
1564 idx
= __CFBSearchTZPeriods(tz
, at
);
1565 return __CFTZPeriodIsDST(&(tz
->_periods
[idx
]));
1566 #elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
1567 /* Compare current timezone time and current timezone time without
1568 * transition to day light saving time
1569 * (Aleskey Dukhnyakov)
1571 TIME_ZONE_INFORMATION tzi
;
1572 SYSTEMTIME stime0
,stime1
,stime2
;
1573 CFRange range
={0,sizeof(TIME_ZONE_INFORMATION
)};
1575 CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), Boolean
, tz
, "_isDaylightSavingTimeForAbsoluteTime:", at
);
1577 CFDataGetBytes(tz
->_data
,range
,(UInt8
*)&tzi
);
1579 if ( !__CFTimeZoneGetWin32SystemTime(&stime0
,at
) ||
1580 !SystemTimeToTzSpecificLocalTime(&tzi
,&stime0
,&stime1
)) {
1581 CFAssert(0, __kCFLogAssertion
, "Win32 system time/timezone failed !\n");
1585 tzi
.DaylightDate
.wMonth
=0;
1586 tzi
.StandardDate
.wMonth
=0;
1588 if ( !SystemTimeToTzSpecificLocalTime(&tzi
,&stime0
,&stime2
)) {
1589 CFAssert(0, __kCFLogAssertion
, "Win32 system time/timezone failed !\n");
1593 if ( !memcmp(&stime1
,&stime2
,sizeof(stime1
)) )
1598 #error Unknown or unspecified DEPLOYMENT_TARGET
1602 CFTimeInterval
CFTimeZoneGetDaylightSavingTimeOffset(CFTimeZoneRef tz
, CFAbsoluteTime at
) {
1603 CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), CFTimeInterval
, tz
, "_daylightSavingTimeOffsetForAbsoluteTime:", at
);
1604 __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
1605 CFIndex idx
= __CFBSearchTZPeriods(tz
, at
);
1606 if (__CFTZPeriodIsDST(&(tz
->_periods
[idx
]))) {
1607 CFTimeInterval offset
= __CFTZPeriodGMTOffset(&(tz
->_periods
[idx
]));
1608 if (idx
+ 1 < tz
->_periodCnt
) {
1609 return offset
- __CFTZPeriodGMTOffset(&(tz
->_periods
[idx
+ 1]));
1610 } else if (0 < idx
) {
1611 return offset
- __CFTZPeriodGMTOffset(&(tz
->_periods
[idx
- 1]));
1617 CFAbsoluteTime
CFTimeZoneGetNextDaylightSavingTimeTransition(CFTimeZoneRef tz
, CFAbsoluteTime at
) {
1618 CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), CFTimeInterval
, tz
, "_nextDaylightSavingTimeTransitionAfterAbsoluteTime:", at
);
1619 __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
1620 CFIndex idx
= __CFBSearchTZPeriods(tz
, at
);
1621 if (tz
->_periodCnt
<= idx
+ 1) {
1624 return (CFAbsoluteTime
)__CFTZPeriodStartSeconds(&(tz
->_periods
[idx
+ 1]));
1627 extern UCalendar
*__CFCalendarCreateUCalendar(CFStringRef calendarID
, CFStringRef localeID
, CFTimeZoneRef tz
);
1629 #define BUFFER_SIZE 768
1631 CFStringRef
CFTimeZoneCopyLocalizedName(CFTimeZoneRef tz
, CFTimeZoneNameStyle style
, CFLocaleRef locale
) {
1632 CF_OBJC_FUNCDISPATCH2(CFTimeZoneGetTypeID(), CFStringRef
, tz
, "localizedName:locale:", style
, locale
);
1633 __CFGenericValidateType(tz
, CFTimeZoneGetTypeID());
1634 __CFGenericValidateType(locale
, CFLocaleGetTypeID());
1636 if (style
== kCFTimeZoneNameStyleGeneric
|| style
== kCFTimeZoneNameStyleShortGeneric
) {
1637 CFDateFormatterRef df
= CFDateFormatterCreate(kCFAllocatorSystemDefault
, locale
, kCFDateFormatterNoStyle
, kCFDateFormatterNoStyle
);
1638 CFDateFormatterSetProperty(df
, kCFDateFormatterTimeZone
, tz
);
1639 CFDateFormatterSetFormat(df
, (style
== kCFTimeZoneNameStyleGeneric
) ? CFSTR("vvvv") : CFSTR("v"));
1640 CFStringRef str
= CFDateFormatterCreateStringWithAbsoluteTime(CFGetAllocator(tz
), df
, 0.0);
1645 CFStringRef localeID
= CFLocaleGetIdentifier(locale
);
1646 UCalendar
*cal
= __CFCalendarCreateUCalendar(NULL
, localeID
, tz
);
1651 char buffer
[BUFFER_SIZE
];
1652 const char *cstr
= CFStringGetCStringPtr(localeID
, kCFStringEncodingASCII
);
1654 if (CFStringGetCString(localeID
, buffer
, BUFFER_SIZE
, kCFStringEncodingASCII
)) cstr
= buffer
;
1661 UChar ubuffer
[BUFFER_SIZE
];
1662 UErrorCode status
= U_ZERO_ERROR
;
1663 int32_t cnt
= ucal_getTimeZoneDisplayName(cal
, (UCalendarDisplayNameType
)style
, cstr
, ubuffer
, BUFFER_SIZE
, &status
);
1665 if (U_SUCCESS(status
) && cnt
<= BUFFER_SIZE
) {
1666 return CFStringCreateWithCharacters(CFGetAllocator(tz
), (const UniChar
*)ubuffer
, cnt
);
1671 static CFDictionaryRef
__CFTimeZoneCopyCompatibilityDictionary(void) {
1672 CFDictionaryRef dict
;
1673 __CFTimeZoneLockCompatibilityMapping();
1674 if (NULL
== __CFTimeZoneCompatibilityMappingDict
) {
1675 __CFTimeZoneCompatibilityMappingDict
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 112, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
1677 // Empty string means delete/ignore these
1679 dict
= __CFTimeZoneCompatibilityMappingDict
? (CFDictionaryRef
)CFRetain(__CFTimeZoneCompatibilityMappingDict
) : NULL
;
1680 __CFTimeZoneUnlockCompatibilityMapping();