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