]> git.saurik.com Git - apple/cf.git/blob - NumberDate.subproj/CFTimeZone.c
14af1dca770dd2ec49256ac5887cf01a2dcfd991
[apple/cf.git] / NumberDate.subproj / CFTimeZone.c
1 /*
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /* CFTimeZone.c
26 Copyright 1998-2002, Apple, Inc. All rights reserved.
27 Responsibility: Christopher Kane
28 */
29
30 #include <CoreFoundation/CFTimeZone.h>
31 #include <CoreFoundation/CFPropertyList.h>
32 #include "CFUtilities.h"
33 #include "CFInternal.h"
34 #include <math.h>
35 #include <limits.h>
36 #include <sys/stat.h>
37 #if !defined(__WIN32__)
38 #include <dirent.h>
39 #else
40 #include <windows.h>
41 #include <winreg.h>
42 #include <tchar.h>
43 #include <time.h>
44 #endif
45 #include <fcntl.h>
46 #include <stdlib.h>
47 #include <string.h>
48
49 #if defined(__WIN32__)
50 #include <io.h>
51 #endif
52
53 // For Windows(TM) time zone information, see registry key:
54 // HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Time Zones
55
56 #if defined(__WIN32__)
57 #define TZZONEINFO "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones"
58 #else
59 #define TZZONELINK "/etc/localtime"
60 #define TZZONEINFO "/usr/share/zoneinfo/"
61 #endif
62
63 static CFTimeZoneRef __CFTimeZoneSystem = NULL;
64 static CFTimeZoneRef __CFTimeZoneDefault = NULL;
65 static CFDictionaryRef __CFTimeZoneAbbreviationDict = NULL;
66 static CFSpinLock_t __CFTimeZoneAbbreviationLock = 0;
67 static CFDictionaryRef __CFTimeZoneCompatibilityMappingDict = NULL;
68 static CFDictionaryRef __CFTimeZoneCompatibilityMappingDict2 = NULL;
69 static CFSpinLock_t __CFTimeZoneCompatibilityMappingLock = 0;
70 static CFArrayRef __CFKnownTimeZoneList = NULL;
71 static CFMutableDictionaryRef __CFTimeZoneCache = NULL;
72 static CFSpinLock_t __CFTimeZoneGlobalLock = 0;
73
74 CF_INLINE void __CFTimeZoneLockGlobal(void) {
75 __CFSpinLock(&__CFTimeZoneGlobalLock);
76 }
77
78 CF_INLINE void __CFTimeZoneUnlockGlobal(void) {
79 __CFSpinUnlock(&__CFTimeZoneGlobalLock);
80 }
81
82 CF_INLINE void __CFTimeZoneLockAbbreviations(void) {
83 __CFSpinLock(&__CFTimeZoneAbbreviationLock);
84 }
85
86 CF_INLINE void __CFTimeZoneUnlockAbbreviations(void) {
87 __CFSpinUnlock(&__CFTimeZoneAbbreviationLock);
88 }
89
90 CF_INLINE void __CFTimeZoneLockCompatibilityMapping(void) {
91 __CFSpinLock(&__CFTimeZoneCompatibilityMappingLock);
92 }
93
94 CF_INLINE void __CFTimeZoneUnlockCompatibilityMapping(void) {
95 __CFSpinUnlock(&__CFTimeZoneCompatibilityMappingLock);
96 }
97
98 /* This function should be used for WIN32 instead of
99 * __CFCopyRecursiveDirectoryList function.
100 * It takes TimeZone names from the registry
101 * (Aleksey Dukhnyakov)
102 */
103 #if defined(__WIN32__)
104 static CFMutableArrayRef __CFCopyWindowsTimeZoneList() {
105 CFMutableArrayRef result = NULL;
106 HKEY hkResult;
107 TCHAR lpName[MAX_PATH+1];
108 DWORD dwIndex, retCode;
109
110 if (RegOpenKey(HKEY_LOCAL_MACHINE,_T(TZZONEINFO),&hkResult) !=
111 ERROR_SUCCESS )
112 return NULL;
113
114 result = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
115
116 for (dwIndex=0; (retCode = RegEnumKey(hkResult,dwIndex,lpName,MAX_PATH)) != ERROR_NO_MORE_ITEMS ; dwIndex++) {
117
118 if (retCode != ERROR_SUCCESS) {
119 RegCloseKey(hkResult);
120 CFRelease(result);
121 return NULL;
122 }
123 else {
124 #if defined(UNICODE)
125 CFStringRef string = CFStringCreateWithBytes(kCFAllocatorDefault, lpName, _tcslen(lpName), kCFStringEncodingUnicode, false);
126 #else
127 CFStringRef string = CFStringCreateWithBytes(kCFAllocatorDefault, lpName, _tcslen(lpName), CFStringGetSystemEncoding(), false);
128 #endif
129 CFArrayAppendValue(result, string);
130 CFRelease(string);
131 }
132 }
133
134 RegCloseKey(hkResult);
135 return result;
136 }
137 #endif
138
139 static CFMutableArrayRef __CFCopyRecursiveDirectoryList(const char *topDir) {
140 CFMutableArrayRef result = NULL, temp;
141 long fd, numread, plen, basep = 0;
142 CFIndex idx, cnt, usedLen;
143 char *dirge, path[CFMaxPathSize];
144
145 #if !defined(__WIN32__)
146 // No d_namlen in dirent struct on Linux
147 #if defined(__LINUX__)
148 #define dentDNameLen strlen(dent->d_name)
149 #else
150 #define dentDNameLen dent->d_namlen
151 #endif
152 fd = open(topDir, O_RDONLY, 0);
153 if (fd < 0) {
154 return NULL;
155 }
156 dirge = malloc(8192);
157 result = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
158 numread = getdirentries(fd, dirge, 8192, &basep);
159 while (0 < numread) {
160 struct dirent *dent = (struct dirent *)dirge;
161 for (; dent < (struct dirent *)(dirge + numread); dent = (struct dirent *)((char *)dent + dent->d_reclen)) {
162 if (0 == dent->d_fileno) continue;
163 if (1 == dentDNameLen && '.' == dent->d_name[0]) continue;
164 if (2 == dentDNameLen && '.' == dent->d_name[0] && '.' == dent->d_name[1]) continue;
165 if (dent->d_type == DT_UNKNOWN) {
166 struct stat statbuf;
167 strcpy(path, topDir);
168 strcat(path, "/");
169 plen = strlen(path);
170 memmove(path + plen, dent->d_name, dentDNameLen);
171 path[plen + dentDNameLen] = '\0';
172 if (0 <= stat(path, &statbuf) && (statbuf.st_mode & S_IFMT) == S_IFDIR) {
173 dent->d_type = DT_DIR;
174 }
175 }
176 if (DT_DIR == dent->d_type) {
177 strcpy(path, topDir);
178 strcat(path, "/");
179 plen = strlen(path);
180 memmove(path + plen, dent->d_name, dentDNameLen);
181 path[plen + dentDNameLen] = '\0';
182 temp = __CFCopyRecursiveDirectoryList(path);
183 for (idx = 0, cnt = CFArrayGetCount(temp); idx < cnt; idx++) {
184 CFStringRef string, item = CFArrayGetValueAtIndex(temp, idx);
185 memmove(path, dent->d_name, dentDNameLen);
186 path[dentDNameLen] = '/';
187 CFStringGetBytes(item, CFRangeMake(0, CFStringGetLength(item)), kCFStringEncodingUTF8, 0, false, path + dentDNameLen + 1, CFMaxPathLength - dentDNameLen - 2, &usedLen);
188 string = CFStringCreateWithBytes(kCFAllocatorDefault, path, dentDNameLen + 1 + usedLen, kCFStringEncodingUTF8, false);
189 CFArrayAppendValue(result, string);
190 CFRelease(string);
191 }
192 CFRelease(temp);
193 } else {
194 CFStringRef string = CFStringCreateWithBytes(kCFAllocatorDefault, dent->d_name, dentDNameLen, kCFStringEncodingUTF8, false);
195 CFArrayAppendValue(result, string);
196 CFRelease(string);
197 }
198 }
199 numread = getdirentries(fd, dirge, 8192, &basep);
200 }
201 close(fd);
202 free(dirge);
203 if (-1 == numread) {
204 CFRelease(result);
205 return NULL;
206 }
207 #endif
208 return result;
209 }
210
211 typedef struct _CFTZPeriod {
212 int32_t startSec;
213 CFStringRef abbrev;
214 uint32_t info;
215 } CFTZPeriod;
216
217 struct __CFTimeZone {
218 CFRuntimeBase _base;
219 CFStringRef _name; /* immutable */
220 CFDataRef _data; /* immutable */
221 CFTZPeriod *_periods; /* immutable */
222 int32_t _periodCnt; /* immutable */
223 };
224
225 /* startSec is the whole integer seconds from a CFAbsoluteTime, giving dates
226 * between 1933 and 2069; info outside these years is discarded on read-in */
227 /* Bits 31-18 of the info are unused */
228 /* Bit 17 of the info is used for the is-DST state */
229 /* Bit 16 of the info is used for the sign of the offset (1 == negative) */
230 /* Bits 15-0 of the info are used for abs(offset) in seconds from GMT */
231
232 CF_INLINE void __CFTZPeriodInit(CFTZPeriod *period, int32_t startTime, CFStringRef abbrev, int32_t offset, Boolean isDST) {
233 period->startSec = startTime;
234 period->abbrev = abbrev ? CFRetain(abbrev) : NULL;
235 __CFBitfieldSetValue(period->info, 15, 0, abs(offset));
236 __CFBitfieldSetValue(period->info, 16, 16, (offset < 0 ? 1 : 0));
237 __CFBitfieldSetValue(period->info, 17, 17, (isDST ? 1 : 0));
238 }
239
240 CF_INLINE int32_t __CFTZPeriodStartSeconds(const CFTZPeriod *period) {
241 return period->startSec;
242 }
243
244 CF_INLINE CFStringRef __CFTZPeriodAbbreviation(const CFTZPeriod *period) {
245 return period->abbrev;
246 }
247
248 CF_INLINE int32_t __CFTZPeriodGMTOffset(const CFTZPeriod *period) {
249 int32_t v = __CFBitfieldGetValue(period->info, 15, 0);
250 if (__CFBitfieldGetValue(period->info, 16, 16)) v = -v;
251 return v;
252 }
253
254 CF_INLINE Boolean __CFTZPeriodIsDST(const CFTZPeriod *period) {
255 return (Boolean)__CFBitfieldGetValue(period->info, 17, 17);
256 }
257
258 static CFComparisonResult __CFCompareTZPeriods(const void *val1, const void *val2, void *context) {
259 CFTZPeriod *tzp1 = (CFTZPeriod *)val1;
260 CFTZPeriod *tzp2 = (CFTZPeriod *)val2;
261 // we treat equal as less than, as the code which uses the
262 // result of the bsearch doesn't expect exact matches
263 // (they're pretty rare, so no point in over-coding for them)
264 if (__CFTZPeriodStartSeconds(tzp1) <= __CFTZPeriodStartSeconds(tzp2)) return kCFCompareLessThan;
265 return kCFCompareGreaterThan;
266 }
267
268 CF_INLINE CFIndex __CFBSearchTZPeriods(CFTimeZoneRef tz, CFAbsoluteTime at) {
269 CFTZPeriod elem;
270 CFIndex idx;
271 __CFTZPeriodInit(&elem, (int32_t)(float)floor(at), NULL, 0, false);
272 idx = CFBSearch(&elem, sizeof(CFTZPeriod), tz->_periods, tz->_periodCnt, __CFCompareTZPeriods, NULL);
273 if (tz->_periodCnt <= idx) {
274 idx = tz->_periodCnt;
275 } else if (0 == idx) {
276 // We want anything before the time zone records start to be not in DST;
277 // we assume that if period[0] is DST, then period[1] is not; could do a search instead.
278 idx = __CFTZPeriodIsDST(&(tz->_periods[0])) ? 2 : 1;
279 }
280 return idx - 1;
281 }
282
283 /*
284 ** Each time zone data file begins with. . .
285 */
286
287 struct tzhead {
288 char tzh_reserved[20]; /* reserved for future use */
289 char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
290 char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
291 char tzh_leapcnt[4]; /* coded number of leap seconds */
292 char tzh_timecnt[4]; /* coded number of transition times */
293 char tzh_typecnt[4]; /* coded number of local time types */
294 char tzh_charcnt[4]; /* coded number of abbr. chars */
295 };
296
297 /*
298 ** . . .followed by. . .
299 **
300 ** tzh_timecnt (char [4])s coded transition times a la time(2)
301 ** tzh_timecnt (UInt8)s types of local time starting at above
302 ** tzh_typecnt repetitions of
303 ** one (char [4]) coded GMT offset in seconds
304 ** one (UInt8) used to set tm_isdst
305 ** one (UInt8) that's an abbreviation list index
306 ** tzh_charcnt (char)s '\0'-terminated zone abbreviations
307 ** tzh_leapcnt repetitions of
308 ** one (char [4]) coded leap second transition times
309 ** one (char [4]) total correction after above
310 ** tzh_ttisstdcnt (char)s indexed by type; if 1, transition
311 ** time is standard time, if 0,
312 ** transition time is wall clock time
313 ** if absent, transition times are
314 ** assumed to be wall clock time
315 ** tzh_ttisgmtcnt (char)s indexed by type; if 1, transition
316 ** time is GMT, if 0,
317 ** transition time is local time
318 ** if absent, transition times are
319 ** assumed to be local time
320 */
321
322 CF_INLINE int32_t __CFDetzcode(const unsigned char *bufp) {
323 int32_t result = (bufp[0] & 0x80) ? ~0L : 0L;
324 result = (result << 8) | (bufp[0] & 0xff);
325 result = (result << 8) | (bufp[1] & 0xff);
326 result = (result << 8) | (bufp[2] & 0xff);
327 result = (result << 8) | (bufp[3] & 0xff);
328 return result;
329 }
330
331 CF_INLINE void __CFEntzcode(int32_t value, unsigned char *bufp) {
332 bufp[0] = (value >> 24) & 0xff;
333 bufp[1] = (value >> 16) & 0xff;
334 bufp[2] = (value >> 8) & 0xff;
335 bufp[3] = (value >> 0) & 0xff;
336 }
337
338 static Boolean __CFParseTimeZoneData(CFAllocatorRef allocator, CFDataRef data, CFTZPeriod **tzpp, CFIndex *cntp) {
339 #if !defined(__WIN32__)
340 int32_t len, timecnt, typecnt, charcnt, idx, cnt;
341 const char *p, *timep, *typep, *ttisp, *charp;
342 CFStringRef *abbrs;
343 Boolean result = true;
344
345 p = CFDataGetBytePtr(data);
346 len = CFDataGetLength(data);
347 if (len < (int32_t)sizeof(struct tzhead)) {
348 return false;
349 }
350 p += 20 + 4 + 4 + 4; /* skip reserved, ttisgmtcnt, ttisstdcnt, leapcnt */
351 timecnt = __CFDetzcode(p);
352 p += 4;
353 typecnt = __CFDetzcode(p);
354 p += 4;
355 charcnt = __CFDetzcode(p);
356 p += 4;
357 if (typecnt <= 0 || timecnt < 0 || charcnt < 0) {
358 return false;
359 }
360 if (len - (int32_t)sizeof(struct tzhead) < (4 + 1) * timecnt + (4 + 1 + 1) * typecnt + charcnt) {
361 return false;
362 }
363 timep = p;
364 typep = timep + 4 * timecnt;
365 ttisp = typep + timecnt;
366 charp = ttisp + (4 + 1 + 1) * typecnt;
367 cnt = (0 < timecnt) ? timecnt : 1;
368 *tzpp = CFAllocatorAllocate(allocator, cnt * sizeof(CFTZPeriod), 0);
369 if (__CFOASafe) __CFSetLastAllocationEventName(*tzpp, "CFTimeZone (store)");
370 memset(*tzpp, 0, cnt * sizeof(CFTZPeriod));
371 abbrs = CFAllocatorAllocate(allocator, (charcnt + 1) * sizeof(CFStringRef), 0);
372 if (__CFOASafe) __CFSetLastAllocationEventName(*tzpp, "CFTimeZone (temp)");
373 for (idx = 0; idx < charcnt + 1; idx++) {
374 abbrs[idx] = NULL;
375 }
376 for (idx = 0; idx < cnt; idx++) {
377 CFAbsoluteTime at;
378 int32_t itime, offset;
379 uint8_t type, dst, abbridx;
380
381 at = (CFAbsoluteTime)(__CFDetzcode(timep) + 0.0) - kCFAbsoluteTimeIntervalSince1970;
382 if (0 == timecnt) itime = INT_MIN;
383 else if (at < (CFAbsoluteTime)INT_MIN) itime = INT_MIN;
384 else if ((CFAbsoluteTime)INT_MAX < at) itime = INT_MAX;
385 else itime = (int32_t)at;
386 timep += 4; /* harmless if 0 == timecnt */
387 type = (0 < timecnt) ? (uint8_t)*typep++ : 0;
388 if (typecnt <= type) {
389 result = false;
390 break;
391 }
392 offset = __CFDetzcode(ttisp + 6 * type);
393 dst = (uint8_t)*(ttisp + 6 * type + 4);
394 if (0 != dst && 1 != dst) {
395 result = false;
396 break;
397 }
398 abbridx = (uint8_t)*(ttisp + 6 * type + 5);
399 if (charcnt < abbridx) {
400 result = false;
401 break;
402 }
403 if (NULL == abbrs[abbridx]) {
404 abbrs[abbridx] = CFStringCreateWithCString(allocator, &charp[abbridx], kCFStringEncodingASCII);
405 }
406 __CFTZPeriodInit(*tzpp + idx, itime, abbrs[abbridx], offset, (dst ? true : false));
407 }
408 for (idx = 0; idx < charcnt + 1; idx++) {
409 if (NULL != abbrs[idx]) {
410 CFRelease(abbrs[idx]);
411 }
412 }
413 CFAllocatorDeallocate(allocator, abbrs);
414 if (result) {
415 // dump all but the last INT_MIN and the first INT_MAX
416 for (idx = 0; idx < cnt; idx++) {
417 if (((*tzpp + idx)->startSec == INT_MIN) && (idx + 1 < cnt) && (((*tzpp + idx + 1)->startSec == INT_MIN))) {
418 cnt--;
419 memmove((*tzpp + idx), (*tzpp + idx + 1), sizeof(CFTZPeriod) * (cnt - idx));
420 idx--;
421 }
422 }
423 // Don't combine these loops! Watch the idx decrementing...
424 for (idx = 0; idx < cnt; idx++) {
425 if (((*tzpp + idx)->startSec == INT_MAX) && (0 < idx) && (((*tzpp + idx - 1)->startSec == INT_MAX))) {
426 cnt--;
427 memmove((*tzpp + idx), (*tzpp + idx + 1), sizeof(CFTZPeriod) * (cnt - idx));
428 idx--;
429 }
430 }
431 CFQSortArray(*tzpp, cnt, sizeof(CFTZPeriod), __CFCompareTZPeriods, NULL);
432 *cntp = cnt;
433 } else {
434 CFAllocatorDeallocate(allocator, *tzpp);
435 *tzpp = NULL;
436 }
437 return result;
438 #else
439 /* We use Win32 function to find TimeZone
440 * (Aleksey Dukhnyakov)
441 */
442 *tzpp = CFAllocatorAllocate(allocator, sizeof(CFTZPeriod), 0);
443 __CFTZPeriodInit(*tzpp, 0, NULL, 0, false);
444 *cntp = 1;
445 return TRUE;
446 #endif
447 }
448
449 static Boolean __CFTimeZoneEqual(CFTypeRef cf1, CFTypeRef cf2) {
450 CFTimeZoneRef tz1 = (CFTimeZoneRef)cf1;
451 CFTimeZoneRef tz2 = (CFTimeZoneRef)cf2;
452 if (!CFEqual(CFTimeZoneGetName(tz1), CFTimeZoneGetName(tz2))) return false;
453 if (!CFEqual(CFTimeZoneGetData(tz1), CFTimeZoneGetData(tz2))) return false;
454 return true;
455 }
456
457 static CFHashCode __CFTimeZoneHash(CFTypeRef cf) {
458 CFTimeZoneRef tz = (CFTimeZoneRef)cf;
459 return CFHash(CFTimeZoneGetName(tz));
460 }
461
462 static CFStringRef __CFTimeZoneCopyDescription(CFTypeRef cf) {
463 CFTimeZoneRef tz = (CFTimeZoneRef)cf;
464 CFStringRef result, abbrev;
465 CFAbsoluteTime at;
466 at = CFAbsoluteTimeGetCurrent();
467 abbrev = CFTimeZoneCopyAbbreviation(tz, at);
468 result = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("<CFTimeZone %p [%p]>{name = %@; abbreviation = %@; GMT offset = %g; is DST = %s}"), cf, CFGetAllocator(tz), tz->_name, abbrev, CFTimeZoneGetSecondsFromGMT(tz, at), CFTimeZoneIsDaylightSavingTime(tz, at) ? "true" : "false");
469 CFRelease(abbrev);
470 return result;
471 }
472
473 static void __CFTimeZoneDeallocate(CFTypeRef cf) {
474 CFTimeZoneRef tz = (CFTimeZoneRef)cf;
475 CFAllocatorRef allocator = CFGetAllocator(tz);
476 CFIndex idx;
477 if (tz->_name) CFRelease(tz->_name);
478 if (tz->_data) CFRelease(tz->_data);
479 for (idx = 0; idx < tz->_periodCnt; idx++) {
480 if (NULL != tz->_periods[idx].abbrev) CFRelease(tz->_periods[idx].abbrev);
481 }
482 if (NULL != tz->_periods) CFAllocatorDeallocate(allocator, tz->_periods);
483 }
484
485 static CFTypeID __kCFTimeZoneTypeID = _kCFRuntimeNotATypeID;
486
487 static const CFRuntimeClass __CFTimeZoneClass = {
488 0,
489 "CFTimeZone",
490 NULL, // init
491 NULL, // copy
492 __CFTimeZoneDeallocate,
493 __CFTimeZoneEqual,
494 __CFTimeZoneHash,
495 NULL, //
496 __CFTimeZoneCopyDescription
497 };
498
499 __private_extern__ void __CFTimeZoneInitialize(void) {
500 __kCFTimeZoneTypeID = _CFRuntimeRegisterClass(&__CFTimeZoneClass);
501 }
502
503 CFTypeID CFTimeZoneGetTypeID(void) {
504 return __kCFTimeZoneTypeID;
505 }
506
507 static CFTimeZoneRef __CFTimeZoneCreateSystem(void) {
508 CFTimeZoneRef result = NULL;
509 #if defined(__WIN32__)
510 /* The GetTimeZoneInformation function retrieves the current
511 * time-zone parameters for Win32
512 * (Aleksey Dukhnyakov)
513 */
514 CFDataRef data;
515 TIME_ZONE_INFORMATION tz;
516 DWORD dw_result;
517 dw_result=GetTimeZoneInformation(&tz);
518
519 if ( dw_result == TIME_ZONE_ID_STANDARD ||
520 dw_result == TIME_ZONE_ID_DAYLIGHT ) {
521 CFStringRef name = CFStringCreateWithCharacters(kCFAllocatorDefault, tz.StandardName, wcslen(tz.StandardName));
522 data = CFDataCreate(kCFAllocatorDefault, (UInt8*)&tz, sizeof(tz));
523 result = CFTimeZoneCreate(kCFAllocatorSystemDefault, name, data);
524 CFRelease(name);
525 CFRelease(data);
526 if (result) return result;
527 }
528 #else
529 char *tzenv;
530 int ret;
531 char linkbuf[CFMaxPathSize];
532
533 tzenv = getenv("TZFILE");
534 if (NULL != tzenv) {
535 CFStringRef name = CFStringCreateWithBytes(kCFAllocatorDefault, tzenv, strlen(tzenv), kCFStringEncodingUTF8, false);
536 result = CFTimeZoneCreateWithName(kCFAllocatorSystemDefault, name, false);
537 CFRelease(name);
538 if (result) return result;
539 }
540 tzenv = getenv("TZ");
541 if (NULL != tzenv) {
542 CFStringRef name = CFStringCreateWithBytes(kCFAllocatorDefault, tzenv, strlen(tzenv), kCFStringEncodingUTF8, false);
543 result = CFTimeZoneCreateWithName(kCFAllocatorSystemDefault, name, true);
544 CFRelease(name);
545 if (result) return result;
546 }
547 ret = readlink(TZZONELINK, linkbuf, sizeof(linkbuf));
548 if (0 < ret) {
549 CFStringRef name;
550 linkbuf[ret] = '\0';
551 if (strncmp(linkbuf, TZZONEINFO, sizeof(TZZONEINFO) - 1) == 0) {
552 name = CFStringCreateWithBytes(kCFAllocatorDefault, linkbuf + sizeof(TZZONEINFO) - 1, strlen(linkbuf) - sizeof(TZZONEINFO) + 1, kCFStringEncodingUTF8, false);
553 } else {
554 name = CFStringCreateWithBytes(kCFAllocatorDefault, linkbuf, strlen(linkbuf), kCFStringEncodingUTF8, false);
555 }
556 result = CFTimeZoneCreateWithName(kCFAllocatorSystemDefault, name, false);
557 CFRelease(name);
558 if (result) return result;
559 }
560 #endif
561 return CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorSystemDefault, 0.0);
562 }
563
564 CFTimeZoneRef CFTimeZoneCopySystem(void) {
565 CFTimeZoneRef tz;
566 __CFTimeZoneLockGlobal();
567 if (NULL == __CFTimeZoneSystem) {
568 __CFTimeZoneUnlockGlobal();
569 tz = __CFTimeZoneCreateSystem();
570 __CFTimeZoneLockGlobal();
571 if (NULL == __CFTimeZoneSystem) {
572 __CFTimeZoneSystem = tz;
573 } else {
574 if (tz) CFRelease(tz);
575 }
576 }
577 tz = __CFTimeZoneSystem ? CFRetain(__CFTimeZoneSystem) : NULL;
578 __CFTimeZoneUnlockGlobal();
579 return tz;
580 }
581
582 void CFTimeZoneResetSystem(void) {
583 __CFTimeZoneLockGlobal();
584 if (__CFTimeZoneDefault == __CFTimeZoneSystem) {
585 if (__CFTimeZoneDefault) CFRelease(__CFTimeZoneDefault);
586 __CFTimeZoneDefault = NULL;
587 }
588 if (__CFTimeZoneSystem) CFRelease(__CFTimeZoneSystem);
589 __CFTimeZoneSystem = NULL;
590 __CFTimeZoneUnlockGlobal();
591 }
592
593 CFTimeZoneRef CFTimeZoneCopyDefault(void) {
594 CFTimeZoneRef tz;
595 __CFTimeZoneLockGlobal();
596 if (NULL == __CFTimeZoneDefault) {
597 __CFTimeZoneUnlockGlobal();
598 tz = CFTimeZoneCopySystem();
599 __CFTimeZoneLockGlobal();
600 if (NULL == __CFTimeZoneDefault) {
601 __CFTimeZoneDefault = tz;
602 } else {
603 if (tz) CFRelease(tz);
604 }
605 }
606 tz = __CFTimeZoneDefault ? CFRetain(__CFTimeZoneDefault) : NULL;
607 __CFTimeZoneUnlockGlobal();
608 return tz;
609 }
610
611 void CFTimeZoneSetDefault(CFTimeZoneRef tz) {
612 __CFGenericValidateType(tz, __kCFTimeZoneTypeID);
613 __CFTimeZoneLockGlobal();
614 if (tz != __CFTimeZoneDefault) {
615 if (tz) CFRetain(tz);
616 if (__CFTimeZoneDefault) CFRelease(__CFTimeZoneDefault);
617 __CFTimeZoneDefault = tz;
618 }
619 __CFTimeZoneUnlockGlobal();
620 }
621
622 static CFDictionaryRef __CFTimeZoneCopyCompatibilityDictionary(void);
623
624 CFArrayRef CFTimeZoneCopyKnownNames(void) {
625 CFArrayRef tzs;
626 __CFTimeZoneLockGlobal();
627 if (NULL == __CFKnownTimeZoneList) {
628 CFMutableArrayRef list;
629 /* TimeZone information locate in the registry for Win32
630 * (Aleksey Dukhnyakov)
631 */
632 #if !defined(__WIN32__)
633 list = __CFCopyRecursiveDirectoryList(TZZONEINFO);
634 #else
635 list = __CFCopyWindowsTimeZoneList();
636 #endif
637 // Remove undesirable ancient cruft
638 CFDictionaryRef dict = __CFTimeZoneCopyCompatibilityDictionary();
639 CFIndex idx;
640 for (idx = CFArrayGetCount(list); idx--; ) {
641 CFStringRef item = CFArrayGetValueAtIndex(list, idx);
642 if (CFDictionaryContainsKey(dict, item)) {
643 CFArrayRemoveValueAtIndex(list, idx);
644 }
645 }
646 __CFKnownTimeZoneList = CFArrayCreateCopy(kCFAllocatorSystemDefault, list);
647 CFRelease(list);
648 }
649 tzs = __CFKnownTimeZoneList ? CFRetain(__CFKnownTimeZoneList) : NULL;
650 __CFTimeZoneUnlockGlobal();
651 return tzs;
652 }
653
654 static const unsigned char *__CFTimeZoneAbbreviationDefaults =
655 #if defined(__WIN32__)
656 /*
657 * TimeZone abbreviations for Win32
658 * (Andrew Dzubandovsky)
659 *
660 */
661 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
662 " <!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">"
663 " <plist version=\"1.0\">"
664 " <dict>"
665 " <key>AFG</key> <string>Afghanistan Standard Time</string>"
666 " <key>ALS</key> <string>Alaskan Standard Time</string>"
667 " <key>ARA</key> <string>Arab Standard Time</string>"
668 " <key>ARB</key> <string>Arabian Standard Time</string>"
669 " <key>ARC</key> <string>Arabic Standard Time</string>"
670 " <key>ATL</key> <string>Atlantic Standard Time</string>"
671 " <key>ASC</key> <string>AUS Central Standard Time</string>"
672 " <key>ASE</key> <string>AUS Eastern Standard Time</string>"
673 " <key>AZS</key> <string>Azores Standard Time</string>"
674 " <key>CND</key> <string>Canada Central Standard Time</string>"
675 " <key>CPV</key> <string>Cape Verde Standard Time</string>"
676 " <key>CCS</key> <string>Caucasus Standard Time</string>"
677 " <key>CNAS</key> <string>Cen. Australia Standard Time</string>"
678 " <key>CAMR</key> <string>Central America Standard Time</string>"
679 " <key>CAS</key> <string>Central Asia Standard Time</string>"
680 " <key>CER</key> <string>Central Europe Standard Time</string>"
681 " <key>CEPN</key> <string>Central European Standard Time</string>"
682 " <key>CPC</key> <string>Central Pacific Standard Time</string>"
683 " <key>CSTD</key> <string>Central Standard Time</string>"
684 " <key>CHN</key> <string>China Standard Time</string>"
685 " <key>DTLN</key> <string>Dateline Standard Time</string>"
686 " <key>EAFR</key> <string>E. Africa Standard Time</string>"
687 " <key>EAS</key> <string>E. Australia Standard Time</string>"
688 " <key>ERP</key> <string>E. Europe Standard Time</string>"
689 " <key>ESTH</key> <string>E. South America Standard Time</string>"
690 " <key>ESTM</key> <string>Eastern Standard Time</string>"
691 " <key>EGP</key> <string>Egypt Standard Time</string>"
692 " <key>EKT</key> <string>Ekaterinburg Standard Time</string>"
693 " <key>FST</key> <string>Fiji Standard Time</string>"
694 " <key>FLE</key> <string>FLE Standard Time</string>"
695 " <key>GMT</key> <string>GMT Standard Time</string>"
696 " <key>GRLD</key> <string>Greenland Standard Time</string>"
697 " <key>GRW</key> <string>Greenwich Standard Time</string>"
698 " <key>GTB</key> <string>GTB Standard Time</string>"
699 " <key>HWT</key> <string>Hawaiian Standard Time</string>"
700 " <key>INT</key> <string>India Standard Time</string>"
701 " <key>IRT</key> <string>Iran Standard Time</string>"
702 " <key>ISL</key> <string>Israel Standard Time</string>"
703 " <key>KRT</key> <string>Korea Standard Time</string>"
704 " <key>MXST</key> <string>Mexico Standard Time</string>"
705 " <key>MTL</key> <string>Mid-Atlantic Standard Time</string>"
706 " <key>MNT</key> <string>Mountain Standard Time</string>"
707 " <key>MNM</key> <string>Myanmar Standard Time</string>"
708 " <key>NCNA</key> <string>N. Central Asia Standard Time</string>"
709 " <key>MPL</key> <string>Nepal Standard Time</string>"
710 " <key>NWZ</key> <string>New Zealand Standard Time</string>"
711 " <key>NWF</key> <string>Newfoundland Standard Time</string>"
712 " <key>NTAE</key> <string>North Asia East Standard Time</string>"
713 " <key>NTAS</key> <string>North Asia Standard Time</string>"
714 " <key>HSAT</key> <string>Pacific SA Standard Time</string>"
715 " <key>PST</key> <string>Pacific Standard Time</string>"
716 " <key>RMC</key> <string>Romance Standard Time</string>"
717 " <key>MSK</key> <string>Russian Standard Time</string>"
718 " <key>SSS</key> <string>SA Eastern Standard Time</string>"
719 " <key>SPS</key> <string>SA Pacific Standard Time</string>"
720 " <key>SWS</key> <string>SA Western Standard Time</string>"
721 " <key>SMS</key> <string>Samoa Standard Time</string>"
722 " <key>SAS</key> <string>SE Asia Standard Time</string>"
723 " <key>SNG</key> <string>Singapore Standard Time</string>"
724 " <key>STAF</key> <string>South Africa Standard Time</string>"
725 " <key>SRLK</key> <string>Sri Lanka Standard Time</string>"
726 " <key>TPS</key> <string>Taipei Standard Time</string>"
727 " <key>TSM</key> <string>Tasmania Standard Time</string>"
728 " <key>JPN</key> <string>Tokyo Standard Time</string>"
729 " <key>TNG</key> <string>Tonga Standard Time</string>"
730 " <key>AEST</key> <string>US Eastern Standard Time</string>"
731 " <key>AMST</key> <string>US Mountain Standard Time</string>"
732 " <key>VLD</key> <string>Vladivostok Standard Time</string>"
733 " <key>AUSW</key> <string>W. Australia Standard Time</string>"
734 " <key>AFCW</key> <string>W. Central Africa Standard Time</string>"
735 " <key>EWS</key> <string>W. Europe Standard Time</string>"
736 " <key>ASW</key> <string>West Asia Standard Time</string>"
737 " <key>PWS</key> <string>West Pacific Standard Time</string>"
738 " <key>RKS</key> <string>Yakutsk Standard Time</string>"
739 " </dict>"
740 " </plist>";
741 #else
742 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
743 " <!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">"
744 " <plist version=\"1.0\">"
745 " <dict>"
746 " <key>ADT</key> <string>America/Halifax</string>"
747 " <key>AFT</key> <string>Asia/Kabul</string>"
748 " <key>AKDT</key> <string>America/Juneau</string>"
749 " <key>AKST</key> <string>America/Juneau</string>"
750 " <key>AST</key> <string>America/Halifax</string>"
751 " <key>CDT</key> <string>America/Chicago</string>"
752 " <key>CEST</key> <string>Europe/Rome</string>"
753 " <key>CET</key> <string>Europe/Rome</string>"
754 " <key>CST</key> <string>America/Chicago</string>"
755 " <key>EDT</key> <string>America/New_York</string>"
756 " <key>EEST</key> <string>Europe/Warsaw</string>"
757 " <key>EET</key> <string>Europe/Warsaw</string>"
758 " <key>EST</key> <string>America/New_York</string>"
759 " <key>GMT</key> <string>GMT</string>"
760 " <key>HKST</key> <string>Asia/Hong_Kong</string>"
761 " <key>HST</key> <string>Pacific/Honolulu</string>"
762 " <key>JST</key> <string>Asia/Tokyo</string>"
763 " <key>MDT</key> <string>America/Denver</string>"
764 " <key>MSD</key> <string>Europe/Moscow</string>"
765 " <key>MSK</key> <string>Europe/Moscow</string>"
766 " <key>MST</key> <string>America/Denver</string>"
767 " <key>NZDT</key> <string>Pacific/Auckland</string>"
768 " <key>NZST</key> <string>Pacific/Auckland</string>"
769 " <key>PDT</key> <string>America/Los_Angeles</string>"
770 " <key>PST</key> <string>America/Los_Angeles</string>"
771 " <key>UTC</key> <string>UTC</string>"
772 " <key>WEST</key> <string>Europe/Paris</string>"
773 " <key>WET</key> <string>Europe/Paris</string>"
774 " <key>YDT</key> <string>America/Yakutat</string>"
775 " <key>YST</key> <string>America/Yakutat</string>"
776 " </dict>"
777 " </plist>";
778 #endif
779
780 CFDictionaryRef CFTimeZoneCopyAbbreviationDictionary(void) {
781 CFDictionaryRef dict;
782 __CFTimeZoneLockAbbreviations();
783 if (NULL == __CFTimeZoneAbbreviationDict) {
784 CFDataRef data = CFDataCreate(kCFAllocatorDefault, __CFTimeZoneAbbreviationDefaults, strlen(__CFTimeZoneAbbreviationDefaults));
785 __CFTimeZoneAbbreviationDict = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, data, kCFPropertyListImmutable, NULL);
786 CFRelease(data);
787 }
788 if (NULL == __CFTimeZoneAbbreviationDict) {
789 __CFTimeZoneAbbreviationDict = CFDictionaryCreate(kCFAllocatorDefault, NULL, NULL, 0, NULL, NULL);
790 }
791 dict = __CFTimeZoneAbbreviationDict ? CFRetain(__CFTimeZoneAbbreviationDict) : NULL;
792 __CFTimeZoneUnlockAbbreviations();
793 return dict;
794 }
795
796 void CFTimeZoneSetAbbreviationDictionary(CFDictionaryRef dict) {
797 __CFGenericValidateType(dict, CFDictionaryGetTypeID());
798 __CFTimeZoneLockGlobal();
799 if (dict != __CFTimeZoneAbbreviationDict) {
800 if (dict) CFRetain(dict);
801 if (__CFTimeZoneAbbreviationDict) CFRelease(__CFTimeZoneAbbreviationDict);
802 __CFTimeZoneAbbreviationDict = dict;
803 }
804 __CFTimeZoneUnlockGlobal();
805 }
806
807 CFTimeZoneRef CFTimeZoneCreate(CFAllocatorRef allocator, CFStringRef name, CFDataRef data) {
808 // assert: (NULL != name && NULL != data);
809 CFTimeZoneRef memory;
810 uint32_t size;
811 CFTZPeriod *tzp;
812 CFIndex idx, cnt;
813
814 if (allocator == NULL) allocator = __CFGetDefaultAllocator();
815 __CFGenericValidateType(allocator, CFAllocatorGetTypeID());
816 __CFGenericValidateType(name, CFStringGetTypeID());
817 __CFGenericValidateType(data, CFDataGetTypeID());
818 __CFTimeZoneLockGlobal();
819 if (NULL != __CFTimeZoneCache && CFDictionaryGetValueIfPresent(__CFTimeZoneCache, name, (const void **)&memory)) {
820 __CFTimeZoneUnlockGlobal();
821 return (CFTimeZoneRef)CFRetain(memory);
822 }
823 if (!__CFParseTimeZoneData(allocator, data, &tzp, &cnt)) {
824 __CFTimeZoneUnlockGlobal();
825 return NULL;
826 }
827 size = sizeof(struct __CFTimeZone) - sizeof(CFRuntimeBase);
828 memory = _CFRuntimeCreateInstance(allocator, __kCFTimeZoneTypeID, size, NULL);
829 if (NULL == memory) {
830 __CFTimeZoneUnlockGlobal();
831 for (idx = 0; idx < cnt; idx++) {
832 if (NULL != tzp[idx].abbrev) CFRelease(tzp[idx].abbrev);
833 }
834 if (NULL != tzp) CFAllocatorDeallocate(allocator, tzp);
835 return NULL;
836 }
837 ((struct __CFTimeZone *)memory)->_name = CFRetain(name);
838 ((struct __CFTimeZone *)memory)->_data = CFRetain(data);
839 ((struct __CFTimeZone *)memory)->_periods = tzp;
840 ((struct __CFTimeZone *)memory)->_periodCnt = cnt;
841 if (NULL == __CFTimeZoneCache) {
842 __CFTimeZoneCache = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
843 }
844 CFDictionaryAddValue(__CFTimeZoneCache, name, memory);
845 __CFTimeZoneUnlockGlobal();
846 return memory;
847 }
848
849 static CFTimeZoneRef __CFTimeZoneCreateFixed(CFAllocatorRef allocator, int32_t seconds, CFStringRef name, int isDST) {
850 CFTimeZoneRef result;
851 CFDataRef data;
852 int32_t nameLen = CFStringGetLength(name);
853 #if defined(__WIN32__)
854 unsigned char *dataBytes = CFAllocatorAllocate(allocator, 52 + nameLen + 1, 0);
855 if (!dataBytes) return NULL;
856 if (__CFOASafe) __CFSetLastAllocationEventName(*tzpp, "CFTimeZone (temp)");
857 #else
858 unsigned char dataBytes[52 + nameLen + 1];
859 #endif
860 memset(dataBytes, 0, sizeof(dataBytes));
861 __CFEntzcode(1, dataBytes + 20);
862 __CFEntzcode(1, dataBytes + 24);
863 __CFEntzcode(1, dataBytes + 36);
864 __CFEntzcode(nameLen + 1, dataBytes + 40);
865 __CFEntzcode(seconds, dataBytes + 44);
866 dataBytes[48] = isDST ? 1 : 0;
867 CFStringGetCString(name, dataBytes + 50, nameLen + 1, kCFStringEncodingASCII);
868 data = CFDataCreate(allocator, dataBytes, 52 + nameLen + 1);
869 result = CFTimeZoneCreate(allocator, name, data);
870 CFRelease(data);
871 #if defined(__WIN32__)
872 CFAllocatorDeallocate(allocator, dataBytes);
873 #endif
874 return result;
875 }
876
877 // rounds offset to nearest minute
878 CFTimeZoneRef CFTimeZoneCreateWithTimeIntervalFromGMT(CFAllocatorRef allocator, CFTimeInterval ti) {
879 CFTimeZoneRef result;
880 CFStringRef name;
881 int32_t seconds, minute, hour;
882 if (allocator == NULL) allocator = __CFGetDefaultAllocator();
883 __CFGenericValidateType(allocator, CFAllocatorGetTypeID());
884 if (ti < -18.0 * 3600 || 18.0 * 3600 < ti) return NULL;
885 ti = (ti < 0.0) ? ceil((ti / 60.0) - 0.5) * 60.0 : floor((ti / 60.0) + 0.5) * 60.0;
886 seconds = (int32_t)ti;
887 hour = (ti < 0) ? (-seconds / 3600) : (seconds / 3600);
888 seconds -= ((ti < 0) ? -hour : hour) * 3600;
889 minute = (ti < 0) ? (-seconds / 60) : (seconds / 60);
890 if (fabs(ti) < 1.0) {
891 name = CFRetain(CFSTR("GMT"));
892 } else {
893 name = CFStringCreateWithFormat(allocator, NULL, CFSTR("GMT%c%02d%02d"), (ti < 0.0 ? '-' : '+'), hour, minute);
894 }
895 #if !defined(__WIN32__)
896 result = __CFTimeZoneCreateFixed(allocator, (int32_t)ti, name, 0);
897 #else
898 /* CFTimeZoneRef->_data will contain TIME_ZONE_INFORMATION structure
899 * to find current timezone
900 * (Aleksey Dukhnyakov)
901 */
902 {
903 TIME_ZONE_INFORMATION tzi;
904 CFDataRef data;
905 CFIndex length = CFStringGetLength(name);
906
907 memset(&tzi,0,sizeof(tzi));
908 tzi.Bias=(long)(-ti/60);
909 CFStringGetCharacters(name, CFRangeMake(0, length < 31 ? length : 31 ), tzi.StandardName);
910 data = CFDataCreate(allocator,(UInt8*)&tzi, sizeof(tzi));
911 result = CFTimeZoneCreate(allocator, name, data);
912 CFRelease(data);
913 }
914 #endif
915 CFRelease(name);
916 return result;
917 }
918
919 CFTimeZoneRef CFTimeZoneCreateWithName(CFAllocatorRef allocator, CFStringRef name, Boolean tryAbbrev) {
920 CFTimeZoneRef result = NULL;
921 CFStringRef tzName = NULL;
922 CFDataRef data = NULL;
923 CFURLRef baseURL, tempURL;
924 void *bytes;
925 CFIndex length;
926
927 if (allocator == NULL) allocator = __CFGetDefaultAllocator();
928 __CFGenericValidateType(allocator, CFAllocatorGetTypeID());
929 __CFGenericValidateType(name, CFStringGetTypeID());
930 if (CFEqual(CFSTR(""), name)) {
931 // empty string is not a time zone name, just abort now,
932 // following stuff will fail anyway
933 return NULL;
934 }
935 __CFTimeZoneLockGlobal();
936 if (NULL != __CFTimeZoneCache && CFDictionaryGetValueIfPresent(__CFTimeZoneCache, name, (const void **)&result)) {
937 __CFTimeZoneUnlockGlobal();
938 return (CFTimeZoneRef)CFRetain(result);
939 }
940 __CFTimeZoneUnlockGlobal();
941 #if !defined(__WIN32__)
942 baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR(TZZONEINFO), kCFURLPOSIXPathStyle, true);
943 if (tryAbbrev) {
944 CFDictionaryRef abbrevs = CFTimeZoneCopyAbbreviationDictionary();
945 tzName = CFDictionaryGetValue(abbrevs, name);
946 if (NULL != tzName) {
947 tempURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault, baseURL, tzName, false);
948 if (NULL != tempURL) {
949 if (_CFReadBytesFromFile(kCFAllocatorDefault, tempURL, &bytes, &length, 0)) {
950 data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, bytes, length, kCFAllocatorDefault);
951 }
952 CFRelease(tempURL);
953 }
954 }
955 CFRelease(abbrevs);
956 }
957 if (NULL == data) {
958 CFDictionaryRef dict = __CFTimeZoneCopyCompatibilityDictionary();
959 CFStringRef mapping = CFDictionaryGetValue(dict, name);
960 if (mapping) {
961 name = mapping;
962 } else if (CFStringHasPrefix(name, CFSTR(TZZONEINFO))) {
963 CFMutableStringRef unprefixed = CFStringCreateMutableCopy(kCFAllocatorDefault, CFStringGetLength(name), name);
964 CFStringDelete(unprefixed, CFRangeMake(0, sizeof(TZZONEINFO)));
965 mapping = CFDictionaryGetValue(dict, unprefixed);
966 if (mapping) {
967 name = mapping;
968 }
969 CFRelease(unprefixed);
970 }
971 CFRelease(dict);
972 if (CFEqual(CFSTR(""), name)) {
973 return NULL;
974 }
975 }
976 if (NULL == data) {
977 tzName = name;
978 tempURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault, baseURL, tzName, false);
979 if (NULL != tempURL) {
980 if (_CFReadBytesFromFile(kCFAllocatorDefault, tempURL, &bytes, &length, 0)) {
981 data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, bytes, length, kCFAllocatorDefault);
982 }
983 CFRelease(tempURL);
984 }
985 }
986 CFRelease(baseURL);
987 if (NULL == data) {
988 tzName = name;
989 tempURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, tzName, kCFURLPOSIXPathStyle, false);
990 if (NULL != tempURL) {
991 if (_CFReadBytesFromFile(kCFAllocatorDefault, tempURL, &bytes, &length, 0)) {
992 data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, bytes, length, kCFAllocatorDefault);
993 }
994 CFRelease(tempURL);
995 }
996 }
997 if (NULL != data) {
998 result = CFTimeZoneCreate(allocator, tzName, data);
999 CFRelease(data);
1000 }
1001 #else
1002 /* Reading GMT offset and daylight flag from the registry
1003 * for TimeZone name
1004 * (Aleksey Dukhnyakov)
1005 */
1006 {
1007 CFStringRef safeName = name;
1008 struct {
1009 LONG Bias;
1010 LONG StandardBias;
1011 LONG DaylightBias;
1012 SYSTEMTIME StandardDate;
1013 SYSTEMTIME DaylightDate;
1014 } tzi;
1015 TIME_ZONE_INFORMATION tzi_system;
1016
1017 HKEY hkResult;
1018 DWORD dwType, dwSize=sizeof(tzi),
1019 dwSize_name1=sizeof(tzi_system.StandardName),
1020 dwSize_name2=sizeof(tzi_system.DaylightName);
1021
1022 if (tryAbbrev) {
1023 CFDictionaryRef abbrevs = CFTimeZoneCopyAbbreviationDictionary();
1024 tzName = CFDictionaryGetValue(abbrevs, name);
1025 if (NULL == tzName) {
1026 return NULL;
1027 }
1028 name = tzName;
1029 CFRelease(abbrevs);
1030 }
1031
1032 /* Open regestry and move down to the TimeZone information
1033 */
1034 if (RegOpenKey(HKEY_LOCAL_MACHINE,_T(TZZONEINFO),&hkResult) !=
1035 ERROR_SUCCESS ) {
1036 return NULL;
1037 }
1038 /* Move down to specific TimeZone name
1039 */
1040 #if defined(UNICODE)
1041 if (RegOpenKey(hkResult,CFStringGetCharactersPtr(name) ,&hkResult) !=
1042 ERROR_SUCCESS ) {
1043 #else
1044 if (RegOpenKey(hkResult,CFStringGetCStringPtr(name, CFStringGetSystemEncoding()),&hkResult) != ERROR_SUCCESS ) {
1045 #endif
1046 return NULL;
1047 }
1048 /* TimeZone information(offsets, daylight flag, ...) assign to tzi structure
1049 */
1050 if ( RegQueryValueEx(hkResult,_T("TZI"),NULL,&dwType,(LPBYTE)&tzi,&dwSize) != ERROR_SUCCESS &&
1051 RegQueryValueEx(hkResult,_T("Std"),NULL,&dwType,(LPBYTE)&tzi_system.StandardName,&dwSize_name1) != ERROR_SUCCESS &&
1052 RegQueryValueEx(hkResult,_T("Dlt"),NULL,&dwType,(LPBYTE)&tzi_system.DaylightName,&dwSize_name2) != ERROR_SUCCESS )
1053 {
1054 return NULL;
1055 }
1056
1057 tzi_system.Bias=tzi.Bias;
1058 tzi_system.StandardBias=tzi.StandardBias;
1059 tzi_system.DaylightBias=tzi.DaylightBias;
1060 tzi_system.StandardDate=tzi.StandardDate;
1061 tzi_system.DaylightDate=tzi.DaylightDate;
1062
1063 /* CFTimeZoneRef->_data will contain TIME_ZONE_INFORMATION structure
1064 * to find current timezone
1065 * (Aleksey Dukhnyakov)
1066 */
1067 data = CFDataCreate(allocator,(UInt8*)&tzi_system, sizeof(tzi_system));
1068
1069 RegCloseKey(hkResult);
1070 result = CFTimeZoneCreate(allocator, name, data);
1071 if (result) {
1072 if (tryAbbrev)
1073 result->_periods->abbrev = CFStringCreateCopy(allocator,safeName);
1074 else {
1075 }
1076 }
1077 CFRelease(data);
1078 }
1079 #endif
1080 return result;
1081 }
1082
1083 CFStringRef CFTimeZoneGetName(CFTimeZoneRef tz) {
1084 CF_OBJC_FUNCDISPATCH0(__kCFTimeZoneTypeID, CFStringRef, tz, "name");
1085 __CFGenericValidateType(tz, __kCFTimeZoneTypeID);
1086 return tz->_name;
1087 }
1088
1089 CFDataRef CFTimeZoneGetData(CFTimeZoneRef tz) {
1090 CF_OBJC_FUNCDISPATCH0(__kCFTimeZoneTypeID, CFDataRef, tz, "data");
1091 __CFGenericValidateType(tz, __kCFTimeZoneTypeID);
1092 return tz->_data;
1093 }
1094
1095 /* This function converts CFAbsoluteTime to (Win32) SYSTEMTIME
1096 * (Aleksey Dukhnyakov)
1097 */
1098 #if defined(__WIN32__)
1099 BOOL __CFTimeZoneGetWin32SystemTime(SYSTEMTIME * sys_time, CFAbsoluteTime time)
1100 {
1101 LONGLONG l;
1102 FILETIME * ftime=(FILETIME*)&l;
1103
1104 /* seconds between 1601 and 1970 : 11644473600,
1105 * seconds between 1970 and 2001 : 978307200,
1106 * FILETIME - number of 100-nanosecond intervals since January 1, 1601
1107 */
1108 l=(time+11644473600+978307200)*10000000;
1109 if (FileTimeToSystemTime(ftime,sys_time))
1110 return TRUE;
1111 else
1112 return FALSE;
1113 }
1114 #endif
1115
1116 CFTimeInterval CFTimeZoneGetSecondsFromGMT(CFTimeZoneRef tz, CFAbsoluteTime at) {
1117 #if !defined(__WIN32__)
1118 CFIndex idx;
1119 CF_OBJC_FUNCDISPATCH1(__kCFTimeZoneTypeID, CFTimeInterval, tz, "_secondsFromGMTForAbsoluteTime:", at);
1120 __CFGenericValidateType(tz, __kCFTimeZoneTypeID);
1121 idx = __CFBSearchTZPeriods(tz, at);
1122 return __CFTZPeriodGMTOffset(&(tz->_periods[idx]));
1123 #else
1124 /* To calculate seconds from GMT, calculate current timezone time and
1125 * subtract GMT timnezone time
1126 * (Aleksey Dukhnyakov)
1127 */
1128 TIME_ZONE_INFORMATION tzi;
1129 FILETIME ftime1,ftime2;
1130 SYSTEMTIME stime0,stime1,stime2;
1131 LONGLONG * l1= (LONGLONG*)&ftime1;
1132 LONGLONG * l2= (LONGLONG*)&ftime2;
1133 CFRange range={0,sizeof(TIME_ZONE_INFORMATION)};
1134 double result;
1135
1136 CF_OBJC_FUNCDISPATCH1(__kCFTimeZoneTypeID, CFTimeInterval, tz, "_secondsFromGMTForAbsoluteTime:", at);
1137
1138 CFDataGetBytes(tz->_data,range,(UInt8*)&tzi);
1139
1140 if (!__CFTimeZoneGetWin32SystemTime(&stime0,at) ||
1141 !SystemTimeToTzSpecificLocalTime(&tzi,&stime0,&stime1) ||
1142 !SystemTimeToFileTime(&stime1,&ftime1) )
1143 {
1144 CFAssert(0, __kCFLogAssertion, "Win32 system time/timezone failed !\n");
1145 return 0;
1146 }
1147
1148 tzi.DaylightDate.wMonth=0;
1149 tzi.StandardDate.wMonth=0;
1150 tzi.StandardBias=0;
1151 tzi.DaylightBias=0;
1152 tzi.Bias=0;
1153
1154 if ( !SystemTimeToTzSpecificLocalTime(&tzi,&stime0,&stime2) ||
1155 !SystemTimeToFileTime(&stime2,&ftime2))
1156 {
1157 CFAssert(0, __kCFLogAssertion, "Win32 system time/timezone failed !\n");
1158 return 0;
1159 }
1160 result=(double)((*l1-*l2)/10000000);
1161 return result;
1162 #endif
1163 }
1164
1165 #if defined(__WIN32__)
1166 /*
1167 * Get abbreviation for name for WIN32 platform
1168 * (Aleksey Dukhnyakov)
1169 */
1170
1171 typedef struct {
1172 CFStringRef tzName;
1173 CFStringRef tzAbbr;
1174 } _CFAbbrFind;
1175
1176 static void _CFFindKeyForValue(const void *key, const void *value, void *context) {
1177 if ( ((_CFAbbrFind *)context)->tzAbbr != NULL ) {
1178 if ( ((_CFAbbrFind *)context)->tzName == (CFStringRef) value ) {
1179 ((_CFAbbrFind *)context)->tzAbbr = key ;
1180 }
1181 }
1182 }
1183
1184 CFIndex __CFTimeZoneInitAbbrev(CFTimeZoneRef tz) {
1185
1186 if ( tz->_periods->abbrev == NULL ) {
1187 _CFAbbrFind abbr = { NULL, NULL };
1188 CFDictionaryRef abbrevs = CFTimeZoneCopyAbbreviationDictionary();
1189
1190 CFDictionaryApplyFunction(abbrevs, _CFFindKeyForValue, &abbr);
1191
1192 if ( abbr.tzAbbr != NULL)
1193 tz->_periods->abbrev = CFStringCreateCopy(kCFAllocatorDefault, abbr.tzAbbr);
1194 else
1195 tz->_periods->abbrev = CFStringCreateCopy(kCFAllocatorDefault, tz->_name);
1196 /* We should return name of TimeZone if couldn't find abbrevation.
1197 * (Ala on MACOSX)
1198 *
1199 * old line : tz->_periods->abbrev =
1200 * CFStringCreateWithCString(kCFAllocatorDefault,"UNKNOWN",
1201 * CFStringGetSystemEncoding());
1202 *
1203 * (Aleksey Dukhnyakov)
1204 */
1205 CFRelease( abbrevs );
1206 }
1207
1208 return 0;
1209 }
1210 #endif
1211
1212 CFStringRef CFTimeZoneCopyAbbreviation(CFTimeZoneRef tz, CFAbsoluteTime at) {
1213 CFStringRef result;
1214 CFIndex idx;
1215 CF_OBJC_FUNCDISPATCH1(__kCFTimeZoneTypeID, CFStringRef, tz, "_abbreviationForAbsoluteTime:", at);
1216 __CFGenericValidateType(tz, __kCFTimeZoneTypeID);
1217 #if !defined(__WIN32__)
1218 idx = __CFBSearchTZPeriods(tz, at);
1219 #else
1220 /*
1221 * Initialize abbreviation for this TimeZone
1222 * (Aleksey Dukhnyakov)
1223 */
1224 idx = __CFTimeZoneInitAbbrev(tz);
1225 #endif
1226 result = __CFTZPeriodAbbreviation(&(tz->_periods[idx]));
1227 return result ? CFRetain(result) : NULL;
1228 }
1229
1230 Boolean CFTimeZoneIsDaylightSavingTime(CFTimeZoneRef tz, CFAbsoluteTime at) {
1231 #if !defined(__WIN32__)
1232 CFIndex idx;
1233 CF_OBJC_FUNCDISPATCH1(__kCFTimeZoneTypeID, Boolean, tz, "_isDaylightSavingTimeForAbsoluteTime:", at);
1234 __CFGenericValidateType(tz, __kCFTimeZoneTypeID);
1235 idx = __CFBSearchTZPeriods(tz, at);
1236 return __CFTZPeriodIsDST(&(tz->_periods[idx]));
1237 #else
1238 /* Compare current timezone time and current timezone time without
1239 * transition to day light saving time
1240 * (Aleskey Dukhnyakov)
1241 */
1242 TIME_ZONE_INFORMATION tzi;
1243 SYSTEMTIME stime0,stime1,stime2;
1244 CFRange range={0,sizeof(TIME_ZONE_INFORMATION)};
1245
1246 CF_OBJC_FUNCDISPATCH1(__kCFTimeZoneTypeID, Boolean, tz, "_isDaylightSavingTimeForAbsoluteTime:", at);
1247
1248 CFDataGetBytes(tz->_data,range,(UInt8*)&tzi);
1249
1250 if ( !__CFTimeZoneGetWin32SystemTime(&stime0,at) ||
1251 !SystemTimeToTzSpecificLocalTime(&tzi,&stime0,&stime1)) {
1252 CFAssert(0, __kCFLogAssertion, "Win32 system time/timezone failed !\n");
1253 return FALSE;
1254 }
1255
1256 tzi.DaylightDate.wMonth=0;
1257 tzi.StandardDate.wMonth=0;
1258
1259 if ( !SystemTimeToTzSpecificLocalTime(&tzi,&stime0,&stime2)) {
1260 CFAssert(0, __kCFLogAssertion, "Win32 system time/timezone failed !\n");
1261 return FALSE;
1262 }
1263
1264 if ( !memcmp(&stime1,&stime2,sizeof(stime1)) )
1265 return FALSE;
1266
1267 return TRUE;
1268 #endif
1269 }
1270
1271 CFTimeInterval _CFTimeZoneGetDSTDelta(CFTimeZoneRef tz, CFAbsoluteTime at) {
1272 CFIndex idx;
1273 __CFGenericValidateType(tz, __kCFTimeZoneTypeID);
1274 idx = __CFBSearchTZPeriods(tz, at);
1275 CFTimeInterval delta = __CFTZPeriodGMTOffset(&(tz->_periods[idx]));
1276 if (idx + 1 < tz->_periodCnt) {
1277 return fabs(delta - __CFTZPeriodGMTOffset(&(tz->_periods[idx + 1])));
1278 } else if (0 < idx) {
1279 return fabs(delta - __CFTZPeriodGMTOffset(&(tz->_periods[idx - 1])));
1280 }
1281 return 0.0;
1282 }
1283
1284 static const unsigned char *__CFTimeZoneCompatibilityMapping =
1285 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
1286 " <!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">"
1287 " <plist version=\"1.0\">"
1288 " <dict>"
1289
1290 // Empty string means delete/ignore these
1291 " <key>Factory</key> <string></string>"
1292 " <key>US/Pacific-New</key> <string></string>"
1293 " <key>Mideast/Riyadh87</key> <string></string>"
1294 " <key>Mideast/Riyadh88</key> <string></string>"
1295 " <key>Mideast/Riyadh89</key> <string></string>"
1296 " <key>SystemV/AST4</key> <string></string>"
1297 " <key>SystemV/AST4ADT</key> <string></string>"
1298 " <key>SystemV/CST6</key> <string></string>"
1299 " <key>SystemV/CST6CDT</key> <string></string>"
1300 " <key>SystemV/EST5</key> <string></string>"
1301 " <key>SystemV/EST5EDT</key> <string></string>"
1302 " <key>SystemV/HST10</key> <string></string>"
1303 " <key>SystemV/MST7</key> <string></string>"
1304 " <key>SystemV/MST7MDT</key> <string></string>"
1305 " <key>SystemV/PST8</key> <string></string>"
1306 " <key>SystemV/PST8PDT</key> <string></string>"
1307 " <key>SystemV/YST9</key> <string></string>"
1308 " <key>SystemV/YST9YDT</key> <string></string>"
1309
1310 " <key>America/Atka</key> <string>America/Adak</string>"
1311 " <key>America/Ensenada</key> <string>America/Tijuana</string>"
1312 " <key>America/Fort_Wayne</key> <string>America/Indianapolis</string>"
1313 " <key>America/Indiana/Indianapolis</key> <string>America/Indianapolis</string>"
1314 " <key>America/Kentucky/Louisville</key> <string>America/Louisville</string>"
1315 " <key>America/Knox_IN</key> <string>America/Indiana/Knox</string>"
1316 " <key>America/Porto_Acre</key> <string>America/Rio_Branco</string>"
1317 " <key>America/Rosario</key> <string>America/Cordoba</string>"
1318 " <key>America/Shiprock</key> <string>America/Denver</string>"
1319 " <key>America/Virgin</key> <string>America/St_Thomas</string>"
1320 " <key>Antarctica/South_Pole</key> <string>Antarctica/McMurdo</string>"
1321 " <key>Asia/Ashkhabad</key> <string>Asia/Ashgabat</string>"
1322 " <key>Asia/Chungking</key> <string>Asia/Chongqing</string>"
1323 //" <key>Asia/Dacca</key> <string>Asia/Dhaka</string>"
1324 //" <key>Asia/Istanbul</key> <string>Europe/Istanbul</string>"
1325 " <key>Asia/Macao</key> <string>Asia/Macau</string>"
1326 " <key>Asia/Tel_Aviv</key> <string>Asia/Jerusalem</string>"
1327 " <key>Asia/Thimbu</key> <string>Asia/Thimphu</string>"
1328 " <key>Asia/Ujung_Pandang</key> <string>Asia/Makassar</string>"
1329 " <key>Asia/Ulan_Bator</key> <string>Asia/Ulaanbaatar</string>"
1330 " <key>Australia/ACT</key> <string>Australia/Sydney</string>"
1331 //" <key>Australia/Canberra</key> <string>Australia/Sydney</string>"
1332 " <key>Australia/LHI</key> <string>Australia/Lord_Howe</string>"
1333 " <key>Australia/NSW</key> <string>Australia/Sydney</string>"
1334 " <key>Australia/North</key> <string>Australia/Darwin</string>"
1335 " <key>Australia/Queensland</key> <string>Australia/Brisbane</string>"
1336 " <key>Australia/South</key> <string>Australia/Adelaide</string>"
1337 " <key>Australia/Tasmania</key> <string>Australia/Hobart</string>"
1338 " <key>Australia/Victoria</key> <string>Australia/Melbourne</string>"
1339 " <key>Australia/West</key> <string>Australia/Perth</string>"
1340 " <key>Australia/Yancowinna</key> <string>Australia/Broken_Hill</string>"
1341 " <key>Brazil/Acre</key> <string>America/Porto_Acre</string>"
1342 " <key>Brazil/DeNoronha</key> <string>America/Noronha</string>"
1343 //" <key>Brazil/East</key> <string>America/Sao_Paulo</string>"
1344 " <key>Brazil/West</key> <string>America/Manaus</string>"
1345 " <key>CST6CDT</key> <string>America/Chicago</string>"
1346 //" <key>Canada/Atlantic</key> <string>America/Halifax</string>"
1347 " <key>Canada/Central</key> <string>America/Winnipeg</string>"
1348 " <key>Canada/East-Saskatchewan</key> <string>America/Regina</string>"
1349 //" <key>Canada/Eastern</key> <string>America/Montreal</string>"
1350 //" <key>Canada/Mountain</key> <string>America/Edmonton</string>"
1351 //" <key>Canada/Newfoundland</key> <string>America/St_Johns</string>"
1352 " <key>Canada/Pacific</key> <string>America/Vancouver</string>"
1353 //" <key>Canada/Saskatchewan</key> <string>America/Regina</string>"
1354 " <key>Canada/Yukon</key> <string>America/Whitehorse</string>"
1355 " <key>Chile/Continental</key> <string>America/Santiago</string>"
1356 " <key>Chile/EasterIsland</key> <string>Pacific/Easter</string>"
1357 " <key>Cuba</key> <string>America/Havana</string>"
1358 " <key>EST5EDT</key> <string>America/New_York</string>"
1359 " <key>Egypt</key> <string>Africa/Cairo</string>"
1360 " <key>Eire</key> <string>Europe/Dublin</string>"
1361 " <key>Etc/GMT+0</key> <string>GMT</string>"
1362 " <key>Etc/GMT-0</key> <string>GMT</string>"
1363 " <key>Etc/GMT0</key> <string>GMT</string>"
1364 " <key>Etc/Greenwich</key> <string>GMT</string>"
1365 " <key>Etc/Universal</key> <string>UTC</string>"
1366 " <key>Etc/Zulu</key> <string>UTC</string>"
1367 " <key>Europe/Nicosia</key> <string>Asia/Nicosia</string>"
1368 " <key>Europe/Tiraspol</key> <string>Europe/Chisinau</string>"
1369 " <key>GB-Eire</key> <string>Europe/London</string>"
1370 " <key>GB</key> <string>Europe/London</string>"
1371 " <key>GMT+0</key> <string>GMT</string>"
1372 " <key>GMT-0</key> <string>GMT</string>"
1373 " <key>GMT0</key> <string>GMT</string>"
1374 " <key>Greenwich</key> <string>GMT</string>"
1375 " <key>Hongkong</key> <string>Asia/Hong_Kong</string>"
1376 " <key>Iceland</key> <string>Atlantic/Reykjavik</string>"
1377 " <key>Iran</key> <string>Asia/Tehran</string>"
1378 " <key>Israel</key> <string>Asia/Jerusalem</string>"
1379 " <key>Jamaica</key> <string>America/Jamaica</string>"
1380 //" <key>Japan</key> <string>Asia/Tokyo</string>"
1381 " <key>Kwajalein</key> <string>Pacific/Kwajalein</string>"
1382 " <key>Libya</key> <string>Africa/Tripoli</string>"
1383 " <key>MST7MDT</key> <string>America/Denver</string>"
1384 " <key>Mexico/BajaNorte</key> <string>America/Tijuana</string>"
1385 " <key>Mexico/BajaSur</key> <string>America/Mazatlan</string>"
1386 " <key>Mexico/General</key> <string>America/Mexico_City</string>"
1387 " <key>NZ-CHAT</key> <string>Pacific/Chatham</string>"
1388 " <key>NZ</key> <string>Pacific/Auckland</string>"
1389 " <key>Navajo</key> <string>America/Denver</string>"
1390 " <key>PRC</key> <string>Asia/Shanghai</string>"
1391 " <key>PST8PDT</key> <string>America/Los_Angeles</string>"
1392 " <key>Pacific/Samoa</key> <string>Pacific/Pago_Pago</string>"
1393 " <key>Poland</key> <string>Europe/Warsaw</string>"
1394 " <key>Portugal</key> <string>Europe/Lisbon</string>"
1395 " <key>ROC</key> <string>Asia/Taipei</string>"
1396 " <key>ROK</key> <string>Asia/Seoul</string>"
1397 " <key>Singapore</key> <string>Asia/Singapore</string>"
1398 " <key>Turkey</key> <string>Europe/Istanbul</string>"
1399 " <key>UCT</key> <string>UTC</string>"
1400 " <key>US/Alaska</key> <string>America/Anchorage</string>"
1401 " <key>US/Aleutian</key> <string>America/Adak</string>"
1402 " <key>US/Arizona</key> <string>America/Phoenix</string>"
1403 //" <key>US/Central</key> <string>America/Chicago</string>"
1404 " <key>US/East-Indiana</key> <string>America/Indianapolis</string>"
1405 //" <key>US/Eastern</key> <string>America/New_York</string>"
1406 " <key>US/Hawaii</key> <string>Pacific/Honolulu</string>"
1407 " <key>US/Indiana-Starke</key> <string>America/Indiana/Knox</string>"
1408 " <key>US/Michigan</key> <string>America/Detroit</string>"
1409 //" <key>US/Mountain</key> <string>America/Denver</string>"
1410 //" <key>US/Pacific</key> <string>America/Los_Angeles</string>"
1411 " <key>US/Samoa</key> <string>Pacific/Pago_Pago</string>"
1412 " <key>Universal</key> <string>UTC</string>"
1413 " <key>W-SU</key> <string>Europe/Moscow</string>"
1414 " <key>Zulu</key> <string>UTC</string>"
1415 " </dict>"
1416 " </plist>";
1417
1418 static CFDictionaryRef __CFTimeZoneCopyCompatibilityDictionary(void) {
1419 CFDictionaryRef dict;
1420 __CFTimeZoneLockCompatibilityMapping();
1421 if (NULL == __CFTimeZoneCompatibilityMappingDict) {
1422 CFDataRef data = CFDataCreate(kCFAllocatorDefault, __CFTimeZoneCompatibilityMapping, strlen(__CFTimeZoneCompatibilityMapping));
1423 __CFTimeZoneCompatibilityMappingDict = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, data, kCFPropertyListImmutable, NULL);
1424 CFRelease(data);
1425 }
1426 if (NULL == __CFTimeZoneCompatibilityMappingDict) {
1427 __CFTimeZoneCompatibilityMappingDict = CFDictionaryCreate(kCFAllocatorDefault, NULL, NULL, 0, NULL, NULL);
1428 }
1429 dict = __CFTimeZoneCompatibilityMappingDict ? CFRetain(__CFTimeZoneCompatibilityMappingDict) : NULL;
1430 __CFTimeZoneUnlockCompatibilityMapping();
1431 return dict;
1432 }
1433
1434 static const unsigned char *__CFTimeZoneCompatibilityMapping2 =
1435 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
1436 " <!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">"
1437 " <plist version=\"1.0\">"
1438 " <dict>"
1439 " <key>Asia/Dacca</key> <string>Asia/Dhaka</string>"
1440 " <key>Asia/Istanbul</key> <string>Europe/Istanbul</string>"
1441 " <key>Australia/Canberra</key> <string>Australia/Sydney</string>"
1442 " <key>Brazil/East</key> <string>America/Sao_Paulo</string>"
1443 " <key>Canada/Atlantic</key> <string>America/Halifax</string>"
1444 " <key>Canada/Eastern</key> <string>America/Montreal</string>"
1445 " <key>Canada/Mountain</key> <string>America/Edmonton</string>"
1446 " <key>Canada/Newfoundland</key> <string>America/St_Johns</string>"
1447 " <key>Canada/Saskatchewan</key> <string>America/Regina</string>"
1448 " <key>Japan</key> <string>Asia/Tokyo</string>"
1449 " <key>US/Central</key> <string>America/Chicago</string>"
1450 " <key>US/Eastern</key> <string>America/New_York</string>"
1451 " <key>US/Mountain</key> <string>America/Denver</string>"
1452 " <key>US/Pacific</key> <string>America/Los_Angeles</string>"
1453 " </dict>"
1454 " </plist>";
1455
1456 __private_extern__ CFDictionaryRef __CFTimeZoneCopyCompatibilityDictionary2(void) {
1457 CFDictionaryRef dict;
1458 __CFTimeZoneLockCompatibilityMapping();
1459 if (NULL == __CFTimeZoneCompatibilityMappingDict2) {
1460 CFDataRef data = CFDataCreate(kCFAllocatorDefault, __CFTimeZoneCompatibilityMapping2, strlen(__CFTimeZoneCompatibilityMapping2));
1461 __CFTimeZoneCompatibilityMappingDict2 = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, data, kCFPropertyListImmutable, NULL);
1462 CFRelease(data);
1463 }
1464 if (NULL == __CFTimeZoneCompatibilityMappingDict2) {
1465 __CFTimeZoneCompatibilityMappingDict2 = CFDictionaryCreate(kCFAllocatorDefault, NULL, NULL, 0, NULL, NULL);
1466 }
1467 dict = __CFTimeZoneCompatibilityMappingDict2 ? CFRetain(__CFTimeZoneCompatibilityMappingDict2) : NULL;
1468 __CFTimeZoneUnlockCompatibilityMapping();
1469 return dict;
1470 }
1471
1472