Skip to content

Commit 19af385

Browse files
committed
TimeZone: delegate to ICU on Windows
Unfortunately, Windows does not have full time zone information available. For many cases we can make do with the system information, augmented with alternate names (the Olson-to-Windows conversion database). This papers over the inability to deserialize the full information in the registry by falling back to ICU to get the information for the DST time conversion.
1 parent f80087a commit 19af385

File tree

1 file changed

+35
-2
lines changed

1 file changed

+35
-2
lines changed

CoreFoundation/NumberDate.subproj/CFTimeZone.c

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1648,13 +1648,32 @@ CFTimeInterval CFTimeZoneGetSecondsFromGMT(CFTimeZoneRef tz, CFAbsoluteTime at)
16481648
return __CFTZPeriodGMTOffset(&(tz->_periods[idx]));
16491649
}
16501650

1651+
extern UCalendar *__CFCalendarCreateUCalendar(CFStringRef calendarID, CFStringRef localeID, CFTimeZoneRef tz);
1652+
16511653
CFStringRef CFTimeZoneCopyAbbreviation(CFTimeZoneRef tz, CFAbsoluteTime at) {
16521654
CFStringRef result;
16531655
CFIndex idx;
16541656
__CFGenericValidateType(tz, CFTimeZoneGetTypeID());
1657+
#if TARGET_OS_WIN32
1658+
UErrorCode status = U_ZERO_ERROR;
1659+
UCalendar *ucal = __CFCalendarCreateUCalendar(NULL, CFSTR("C"), tz);
1660+
if (ucal == NULL) {
1661+
return NULL;
1662+
}
1663+
ucal_setMillis(ucal, (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0, &status);
1664+
1665+
UChar buffer[64];
1666+
int32_t length;
1667+
length = ucal_getTimeZoneDisplayName(ucal, UCAL_SHORT_STANDARD, "C", buffer, sizeof(buffer), &status);
1668+
1669+
ucal_close(ucal);
1670+
1671+
return length <= sizeof(buffer) ? CFStringCreateWithCharacters(kCFAllocatorSystemDefault, buffer, length) : NULL;
1672+
#else
16551673
idx = __CFBSearchTZPeriods(tz, at);
16561674
result = __CFTZPeriodAbbreviation(&(tz->_periods[idx]));
16571675
return result ? (CFStringRef)CFRetain(result) : NULL;
1676+
#endif
16581677
}
16591678

16601679
Boolean CFTimeZoneIsDaylightSavingTime(CFTimeZoneRef tz, CFAbsoluteTime at) {
@@ -1682,15 +1701,29 @@ CFTimeInterval CFTimeZoneGetDaylightSavingTimeOffset(CFTimeZoneRef tz, CFAbsolut
16821701
CFAbsoluteTime CFTimeZoneGetNextDaylightSavingTimeTransition(CFTimeZoneRef tz, CFAbsoluteTime at) {
16831702
CF_OBJC_FUNCDISPATCHV(CFTimeZoneGetTypeID(), CFTimeInterval, (NSTimeZone *)tz, _nextDaylightSavingTimeTransitionAfterAbsoluteTime:at);
16841703
__CFGenericValidateType(tz, CFTimeZoneGetTypeID());
1704+
#if TARGET_OS_WIN32
1705+
UErrorCode status = U_ZERO_ERROR;
1706+
UCalendar *ucal = __CFCalendarCreateUCalendar(NULL, CFSTR("C"), tz);
1707+
if (ucal == NULL) {
1708+
return 0.0;
1709+
}
1710+
ucal_setMillis(ucal, (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0, &status);
1711+
1712+
UDate date;
1713+
ucal_getTimeZoneTransitionDate(ucal, UCAL_TZ_TRANSITION_NEXT, &date, &status);
1714+
1715+
ucal_close(ucal);
1716+
1717+
return (date / 1000.0) - kCFAbsoluteTimeIntervalSince1970;
1718+
#else
16851719
CFIndex idx = __CFBSearchTZPeriods(tz, at);
16861720
if (tz->_periodCnt <= idx + 1) {
16871721
return 0.0;
16881722
}
16891723
return (CFAbsoluteTime)__CFTZPeriodStartSeconds(&(tz->_periods[idx + 1]));
1724+
#endif
16901725
}
16911726

1692-
extern UCalendar *__CFCalendarCreateUCalendar(CFStringRef calendarID, CFStringRef localeID, CFTimeZoneRef tz);
1693-
16941727
#define BUFFER_SIZE 768
16951728

16961729
CFStringRef CFTimeZoneCopyLocalizedName(CFTimeZoneRef tz, CFTimeZoneNameStyle style, CFLocaleRef locale) {

0 commit comments

Comments
 (0)