2 * Copyright (c) 2009 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 Copyright (c) 2002-2009, Apple Inc. All rights reserved.
26 Responsibility: Christopher Kane
29 #include <CoreFoundation/CFDateFormatter.h>
30 #include <CoreFoundation/CFDate.h>
31 #include <CoreFoundation/CFTimeZone.h>
32 #include <CoreFoundation/CFCalendar.h>
33 #include <CoreFoundation/CFNumber.h>
34 #include "CFInternal.h"
35 #include "CFLocaleInternal.h"
36 #include <unicode/udat.h>
37 #include <unicode/udatpg.h>
41 extern UCalendar
*__CFCalendarCreateUCalendar(CFStringRef calendarID
, CFStringRef localeID
, CFTimeZoneRef tz
);
42 static void __CFDateFormatterCustomize(CFDateFormatterRef formatter
);
44 CF_EXPORT
const CFStringRef kCFDateFormatterCalendarIdentifierKey
;
46 #undef CFReleaseIfNotNull
47 #define CFReleaseIfNotNull(X) if (X) CFRelease(X)
49 #define BUFFER_SIZE 768
51 CFStringRef
CFDateFormatterCreateDateFormatFromTemplate(CFAllocatorRef allocator
, CFStringRef tmplate
, CFOptionFlags options
, CFLocaleRef locale
) {
52 if (allocator
) __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
53 if (locale
) __CFGenericValidateType(locale
, CFLocaleGetTypeID());
54 __CFGenericValidateType(tmplate
, CFStringGetTypeID());
56 CFStringRef localeName
= locale
? CFLocaleGetIdentifier(locale
) : CFSTR("");
57 char buffer
[BUFFER_SIZE
];
58 const char *cstr
= CFStringGetCStringPtr(localeName
, kCFStringEncodingASCII
);
60 if (CFStringGetCString(localeName
, buffer
, BUFFER_SIZE
, kCFStringEncodingASCII
)) cstr
= buffer
;
66 UErrorCode status
= U_ZERO_ERROR
;
67 UDateTimePatternGenerator
*ptg
= udatpg_open(cstr
, &status
);
68 if (NULL
== ptg
|| U_FAILURE(status
)) {
72 CFIndex jCount
= 0; // the only interesting cases are 0, 1, and 2 (adjacent)
73 CFRange r
= CFStringFind(tmplate
, CFSTR("j"), 0);
74 if (kCFNotFound
!= r
.location
) {
76 if ((r
.location
+ 1 < CFStringGetLength(tmplate
)) && ('j' == CFStringGetCharacterAtIndex(tmplate
, r
.location
+ 1))) {
81 UChar pattern
[BUFFER_SIZE
], skel
[BUFFER_SIZE
], bpat
[BUFFER_SIZE
];
82 CFIndex cnt
= CFStringGetLength(tmplate
);
83 if (BUFFER_SIZE
< cnt
) cnt
= BUFFER_SIZE
;
84 CFStringGetCharacters(tmplate
, CFRangeMake(0, cnt
), (UniChar
*)pattern
);
87 status
= U_ZERO_ERROR
;
88 int32_t skellen
= udatpg_getSkeleton(ptg
, pattern
, patlen
, skel
, sizeof(skel
) / sizeof(skel
[0]), &status
);
89 if (U_FAILURE(status
)) {
93 if ((0 < jCount
) && (skellen
+ jCount
< (sizeof(skel
) / sizeof(skel
[0])))) {
94 skel
[skellen
++] = 'j';
95 if (1 < jCount
) skel
[skellen
++] = 'j';
98 status
= U_ZERO_ERROR
;
99 int32_t bpatlen
= udatpg_getBestPattern(ptg
, skel
, skellen
, bpat
, sizeof(bpat
) / sizeof(bpat
[0]), &status
);
100 if (U_FAILURE(status
)) {
105 return CFStringCreateWithCharacters(allocator
, (const UniChar
*)bpat
, bpatlen
);
108 struct __CFDateFormatter
{
112 CFDateFormatterStyle _timeStyle
;
113 CFDateFormatterStyle _dateStyle
;
115 CFStringRef _defformat
;
117 CFBooleanRef _IsLenient
;
118 CFBooleanRef _DoesRelativeDateFormatting
;
119 CFBooleanRef _HasCustomFormat
;
120 CFTimeZoneRef _TimeZone
;
121 CFCalendarRef _Calendar
;
122 CFStringRef _CalendarName
;
123 CFDateRef _TwoDigitStartDate
;
124 CFDateRef _DefaultDate
;
125 CFDateRef _GregorianStartDate
;
126 CFArrayRef _EraSymbols
;
127 CFArrayRef _LongEraSymbols
;
128 CFArrayRef _MonthSymbols
;
129 CFArrayRef _ShortMonthSymbols
;
130 CFArrayRef _VeryShortMonthSymbols
;
131 CFArrayRef _StandaloneMonthSymbols
;
132 CFArrayRef _ShortStandaloneMonthSymbols
;
133 CFArrayRef _VeryShortStandaloneMonthSymbols
;
134 CFArrayRef _WeekdaySymbols
;
135 CFArrayRef _ShortWeekdaySymbols
;
136 CFArrayRef _VeryShortWeekdaySymbols
;
137 CFArrayRef _StandaloneWeekdaySymbols
;
138 CFArrayRef _ShortStandaloneWeekdaySymbols
;
139 CFArrayRef _VeryShortStandaloneWeekdaySymbols
;
140 CFArrayRef _QuarterSymbols
;
141 CFArrayRef _ShortQuarterSymbols
;
142 CFArrayRef _StandaloneQuarterSymbols
;
143 CFArrayRef _ShortStandaloneQuarterSymbols
;
144 CFStringRef _AMSymbol
;
145 CFStringRef _PMSymbol
;
149 static CFStringRef
__CFDateFormatterCopyDescription(CFTypeRef cf
) {
150 CFDateFormatterRef formatter
= (CFDateFormatterRef
)cf
;
151 return CFStringCreateWithFormat(CFGetAllocator(formatter
), NULL
, CFSTR("<CFDateFormatter %p [%p]>"), cf
, CFGetAllocator(formatter
));
154 static void __CFDateFormatterDeallocate(CFTypeRef cf
) {
155 CFDateFormatterRef formatter
= (CFDateFormatterRef
)cf
;
156 if (formatter
->_df
) udat_close(formatter
->_df
);
157 if (formatter
->_locale
) CFRelease(formatter
->_locale
);
158 if (formatter
->_format
) CFRelease(formatter
->_format
);
159 if (formatter
->_defformat
) CFRelease(formatter
->_defformat
);
160 CFReleaseIfNotNull(formatter
->_property
._IsLenient
);
161 CFReleaseIfNotNull(formatter
->_property
._DoesRelativeDateFormatting
);
162 CFReleaseIfNotNull(formatter
->_property
._TimeZone
);
163 CFReleaseIfNotNull(formatter
->_property
._Calendar
);
164 CFReleaseIfNotNull(formatter
->_property
._CalendarName
);
165 CFReleaseIfNotNull(formatter
->_property
._TwoDigitStartDate
);
166 CFReleaseIfNotNull(formatter
->_property
._DefaultDate
);
167 CFReleaseIfNotNull(formatter
->_property
._GregorianStartDate
);
168 CFReleaseIfNotNull(formatter
->_property
._EraSymbols
);
169 CFReleaseIfNotNull(formatter
->_property
._LongEraSymbols
);
170 CFReleaseIfNotNull(formatter
->_property
._MonthSymbols
);
171 CFReleaseIfNotNull(formatter
->_property
._ShortMonthSymbols
);
172 CFReleaseIfNotNull(formatter
->_property
._VeryShortMonthSymbols
);
173 CFReleaseIfNotNull(formatter
->_property
._StandaloneMonthSymbols
);
174 CFReleaseIfNotNull(formatter
->_property
._ShortStandaloneMonthSymbols
);
175 CFReleaseIfNotNull(formatter
->_property
._VeryShortStandaloneMonthSymbols
);
176 CFReleaseIfNotNull(formatter
->_property
._WeekdaySymbols
);
177 CFReleaseIfNotNull(formatter
->_property
._ShortWeekdaySymbols
);
178 CFReleaseIfNotNull(formatter
->_property
._VeryShortWeekdaySymbols
);
179 CFReleaseIfNotNull(formatter
->_property
._StandaloneWeekdaySymbols
);
180 CFReleaseIfNotNull(formatter
->_property
._ShortStandaloneWeekdaySymbols
);
181 CFReleaseIfNotNull(formatter
->_property
._VeryShortStandaloneWeekdaySymbols
);
182 CFReleaseIfNotNull(formatter
->_property
._QuarterSymbols
);
183 CFReleaseIfNotNull(formatter
->_property
._ShortQuarterSymbols
);
184 CFReleaseIfNotNull(formatter
->_property
._StandaloneQuarterSymbols
);
185 CFReleaseIfNotNull(formatter
->_property
._ShortStandaloneQuarterSymbols
);
186 CFReleaseIfNotNull(formatter
->_property
._AMSymbol
);
187 CFReleaseIfNotNull(formatter
->_property
._PMSymbol
);
190 static CFStringRef
__CFDateFormatterCreateForcedString(CFDateFormatterRef formatter
, CFStringRef inString
);
192 static void __CFDateFormatterSetProperty(CFDateFormatterRef formatter
, CFStringRef key
, CFTypeRef value
, Boolean directToICU
);
194 #define RESET_PROPERTY(C, K) \
195 if (df->_property. C) __CFDateFormatterSetProperty(df, K, df->_property. C, true);
197 static void __ResetUDateFormat(CFDateFormatterRef df
, Boolean goingToHaveCustomFormat
) {
198 if (df
->_df
) udat_close(df
->_df
);
201 // uses _timeStyle, _dateStyle, _locale, _property._TimeZone; sets _df, _format, _defformat
202 char loc_buffer
[BUFFER_SIZE
];
204 CFStringRef tmpLocName
= df
->_locale
? CFLocaleGetIdentifier(df
->_locale
) : CFSTR("");
205 CFStringGetCString(tmpLocName
, loc_buffer
, BUFFER_SIZE
, kCFStringEncodingASCII
);
207 UChar tz_buffer
[BUFFER_SIZE
];
209 CFStringRef tmpTZName
= df
->_property
._TimeZone
? CFTimeZoneGetName(df
->_property
._TimeZone
) : CFSTR("GMT");
210 CFStringGetCharacters(tmpTZName
, CFRangeMake(0, CFStringGetLength(tmpTZName
)), (UniChar
*)tz_buffer
);
212 df
->_property
._HasCustomFormat
= kCFBooleanFalse
;
214 int32_t udstyle
= 0, utstyle
= 0;
215 switch (df
->_dateStyle
) {
216 case kCFDateFormatterNoStyle
: udstyle
= UDAT_NONE
; break;
217 case kCFDateFormatterShortStyle
: udstyle
= UDAT_SHORT
; break;
218 case kCFDateFormatterMediumStyle
: udstyle
= UDAT_MEDIUM
; break;
219 case kCFDateFormatterLongStyle
: udstyle
= UDAT_LONG
; break;
220 case kCFDateFormatterFullStyle
: udstyle
= UDAT_FULL
; break;
222 switch (df
->_timeStyle
) {
223 case kCFDateFormatterNoStyle
: utstyle
= UDAT_NONE
; break;
224 case kCFDateFormatterShortStyle
: utstyle
= UDAT_SHORT
; break;
225 case kCFDateFormatterMediumStyle
: utstyle
= UDAT_MEDIUM
; break;
226 case kCFDateFormatterLongStyle
: utstyle
= UDAT_LONG
; break;
227 case kCFDateFormatterFullStyle
: utstyle
= UDAT_FULL
; break;
229 Boolean wantRelative
= (NULL
!= df
->_property
._DoesRelativeDateFormatting
&& df
->_property
._DoesRelativeDateFormatting
== kCFBooleanTrue
);
230 Boolean hasFormat
= (NULL
!= df
->_property
._HasCustomFormat
&& df
->_property
._HasCustomFormat
== kCFBooleanTrue
) || goingToHaveCustomFormat
;
231 if (wantRelative
&& !hasFormat
) {
232 udstyle
|= UDAT_RELATIVE
;
235 UErrorCode status
= U_ZERO_ERROR
;
236 UDateFormat
*icudf
= udat_open((UDateFormatStyle
)utstyle
, (UDateFormatStyle
)udstyle
, loc_buffer
, tz_buffer
, CFStringGetLength(tmpTZName
), NULL
, 0, &status
);
237 if (NULL
== icudf
|| U_FAILURE(status
)) {
240 udat_setLenient(icudf
, 0);
241 if (kCFDateFormatterNoStyle
== df
->_dateStyle
&& kCFDateFormatterNoStyle
== df
->_timeStyle
) {
242 udat_applyPattern(icudf
, false, NULL
, 0);
244 CFStringRef calident
= (CFStringRef
)CFLocaleGetValue(df
->_locale
, kCFLocaleCalendarIdentifierKey
);
245 if (calident
&& CFEqual(calident
, kCFCalendarIdentifierGregorian
)) {
246 status
= U_ZERO_ERROR
;
247 udat_set2DigitYearStart(icudf
, -631152000000.0, &status
); // 1950-01-01 00:00:00 GMT
251 __CFDateFormatterCustomize(df
);
253 UChar ubuffer
[BUFFER_SIZE
];
254 status
= U_ZERO_ERROR
;
255 int32_t ret
= udat_toPattern(icudf
, false, ubuffer
, BUFFER_SIZE
, &status
);
256 if (U_SUCCESS(status
) && ret
<= BUFFER_SIZE
) {
257 CFStringRef newFormat
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (const UniChar
*)ubuffer
, ret
);
258 CFStringRef formatString
= __CFDateFormatterCreateForcedString(df
, newFormat
);
259 CFIndex cnt
= CFStringGetLength(formatString
);
260 CFAssert1(cnt
<= 1024, __kCFLogAssertion
, "%s(): format string too long", __PRETTY_FUNCTION__
);
261 if (df
->_format
!= formatString
&& cnt
<= 1024) {
262 STACK_BUFFER_DECL(UChar
, ubuffer
, cnt
);
263 const UChar
*ustr
= (UChar
*)CFStringGetCharactersPtr((CFStringRef
)formatString
);
265 CFStringGetCharacters(formatString
, CFRangeMake(0, cnt
), (UniChar
*)ubuffer
);
268 UErrorCode status
= U_ZERO_ERROR
;
269 // udat_applyPattern(df->_df, false, ustr, cnt, &status);
270 udat_applyPattern(df
->_df
, false, ustr
, cnt
);
271 if (U_SUCCESS(status
)) {
272 if (df
->_format
) CFRelease(df
->_format
);
273 df
->_format
= (CFStringRef
)CFStringCreateCopy(CFGetAllocator(df
), formatString
);
276 CFRelease(formatString
);
277 CFRelease(newFormat
);
279 if (df
->_defformat
) CFRelease(df
->_defformat
);
280 df
->_defformat
= df
->_format
? (CFStringRef
)CFRetain(df
->_format
) : NULL
;
282 RESET_PROPERTY(_IsLenient
, kCFDateFormatterIsLenientKey
);
283 RESET_PROPERTY(_DoesRelativeDateFormatting
, kCFDateFormatterDoesRelativeDateFormattingKey
);
284 RESET_PROPERTY(_Calendar
, kCFDateFormatterCalendarKey
);
285 RESET_PROPERTY(_CalendarName
, kCFDateFormatterCalendarIdentifierKey
);
286 RESET_PROPERTY(_TimeZone
, kCFDateFormatterTimeZoneKey
);
287 RESET_PROPERTY(_TwoDigitStartDate
, kCFDateFormatterTwoDigitStartDateKey
);
288 RESET_PROPERTY(_DefaultDate
, kCFDateFormatterDefaultDateKey
);
289 RESET_PROPERTY(_GregorianStartDate
, kCFDateFormatterGregorianStartDateKey
);
290 RESET_PROPERTY(_EraSymbols
, kCFDateFormatterEraSymbolsKey
);
291 RESET_PROPERTY(_LongEraSymbols
, kCFDateFormatterLongEraSymbolsKey
);
292 RESET_PROPERTY(_MonthSymbols
, kCFDateFormatterMonthSymbolsKey
);
293 RESET_PROPERTY(_ShortMonthSymbols
, kCFDateFormatterShortMonthSymbolsKey
);
294 RESET_PROPERTY(_VeryShortMonthSymbols
, kCFDateFormatterVeryShortMonthSymbolsKey
);
295 RESET_PROPERTY(_StandaloneMonthSymbols
, kCFDateFormatterStandaloneMonthSymbolsKey
);
296 RESET_PROPERTY(_ShortStandaloneMonthSymbols
, kCFDateFormatterShortStandaloneMonthSymbolsKey
);
297 RESET_PROPERTY(_VeryShortStandaloneMonthSymbols
, kCFDateFormatterVeryShortStandaloneMonthSymbolsKey
);
298 RESET_PROPERTY(_WeekdaySymbols
, kCFDateFormatterWeekdaySymbolsKey
);
299 RESET_PROPERTY(_ShortWeekdaySymbols
, kCFDateFormatterShortWeekdaySymbolsKey
);
300 RESET_PROPERTY(_VeryShortWeekdaySymbols
, kCFDateFormatterVeryShortWeekdaySymbolsKey
);
301 RESET_PROPERTY(_StandaloneWeekdaySymbols
, kCFDateFormatterStandaloneWeekdaySymbolsKey
);
302 RESET_PROPERTY(_ShortStandaloneWeekdaySymbols
, kCFDateFormatterShortStandaloneWeekdaySymbolsKey
);
303 RESET_PROPERTY(_VeryShortStandaloneWeekdaySymbols
, kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey
);
304 RESET_PROPERTY(_QuarterSymbols
, kCFDateFormatterQuarterSymbolsKey
);
305 RESET_PROPERTY(_ShortQuarterSymbols
, kCFDateFormatterShortQuarterSymbolsKey
);
306 RESET_PROPERTY(_StandaloneQuarterSymbols
, kCFDateFormatterStandaloneQuarterSymbolsKey
);
307 RESET_PROPERTY(_ShortStandaloneQuarterSymbols
, kCFDateFormatterShortStandaloneQuarterSymbolsKey
);
308 RESET_PROPERTY(_AMSymbol
, kCFDateFormatterAMSymbolKey
);
309 RESET_PROPERTY(_PMSymbol
, kCFDateFormatterPMSymbolKey
);
312 static CFTypeID __kCFDateFormatterTypeID
= _kCFRuntimeNotATypeID
;
314 static const CFRuntimeClass __CFDateFormatterClass
= {
319 __CFDateFormatterDeallocate
,
323 __CFDateFormatterCopyDescription
326 static void __CFDateFormatterInitialize(void) {
327 __kCFDateFormatterTypeID
= _CFRuntimeRegisterClass(&__CFDateFormatterClass
);
330 CFTypeID
CFDateFormatterGetTypeID(void) {
331 if (_kCFRuntimeNotATypeID
== __kCFDateFormatterTypeID
) __CFDateFormatterInitialize();
332 return __kCFDateFormatterTypeID
;
335 CFDateFormatterRef
CFDateFormatterCreate(CFAllocatorRef allocator
, CFLocaleRef locale
, CFDateFormatterStyle dateStyle
, CFDateFormatterStyle timeStyle
) {
336 struct __CFDateFormatter
*memory
;
337 uint32_t size
= sizeof(struct __CFDateFormatter
) - sizeof(CFRuntimeBase
);
338 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
339 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
340 if (locale
) __CFGenericValidateType(locale
, CFLocaleGetTypeID());
341 memory
= (struct __CFDateFormatter
*)_CFRuntimeCreateInstance(allocator
, CFDateFormatterGetTypeID(), size
, NULL
);
342 if (NULL
== memory
) {
346 memory
->_locale
= NULL
;
347 memory
->_format
= NULL
;
348 memory
->_defformat
= NULL
;
349 memory
->_dateStyle
= dateStyle
;
350 memory
->_timeStyle
= timeStyle
;
351 memory
->_property
._IsLenient
= NULL
;
352 memory
->_property
._DoesRelativeDateFormatting
= NULL
;
353 memory
->_property
._HasCustomFormat
= NULL
;
354 memory
->_property
._TimeZone
= NULL
;
355 memory
->_property
._Calendar
= NULL
;
356 memory
->_property
._CalendarName
= NULL
;
357 memory
->_property
._TwoDigitStartDate
= NULL
;
358 memory
->_property
._DefaultDate
= NULL
;
359 memory
->_property
._GregorianStartDate
= NULL
;
360 memory
->_property
._EraSymbols
= NULL
;
361 memory
->_property
._LongEraSymbols
= NULL
;
362 memory
->_property
._MonthSymbols
= NULL
;
363 memory
->_property
._ShortMonthSymbols
= NULL
;
364 memory
->_property
._VeryShortMonthSymbols
= NULL
;
365 memory
->_property
._StandaloneMonthSymbols
= NULL
;
366 memory
->_property
._ShortStandaloneMonthSymbols
= NULL
;
367 memory
->_property
._VeryShortStandaloneMonthSymbols
= NULL
;
368 memory
->_property
._WeekdaySymbols
= NULL
;
369 memory
->_property
._ShortWeekdaySymbols
= NULL
;
370 memory
->_property
._VeryShortWeekdaySymbols
= NULL
;
371 memory
->_property
._StandaloneWeekdaySymbols
= NULL
;
372 memory
->_property
._ShortStandaloneWeekdaySymbols
= NULL
;
373 memory
->_property
._VeryShortStandaloneWeekdaySymbols
= NULL
;
374 memory
->_property
._QuarterSymbols
= NULL
;
375 memory
->_property
._ShortQuarterSymbols
= NULL
;
376 memory
->_property
._StandaloneQuarterSymbols
= NULL
;
377 memory
->_property
._ShortStandaloneQuarterSymbols
= NULL
;
378 memory
->_property
._AMSymbol
= NULL
;
379 memory
->_property
._PMSymbol
= NULL
;
382 case kCFDateFormatterNoStyle
:
383 case kCFDateFormatterShortStyle
:
384 case kCFDateFormatterMediumStyle
:
385 case kCFDateFormatterLongStyle
:
386 case kCFDateFormatterFullStyle
: break;
388 CFAssert2(0, __kCFLogAssertion
, "%s(): unknown date style %d", __PRETTY_FUNCTION__
, dateStyle
);
389 memory
->_dateStyle
= kCFDateFormatterMediumStyle
;
393 case kCFDateFormatterNoStyle
:
394 case kCFDateFormatterShortStyle
:
395 case kCFDateFormatterMediumStyle
:
396 case kCFDateFormatterLongStyle
:
397 case kCFDateFormatterFullStyle
: break;
399 CFAssert2(0, __kCFLogAssertion
, "%s(): unknown time style %d", __PRETTY_FUNCTION__
, timeStyle
);
400 memory
->_timeStyle
= kCFDateFormatterMediumStyle
;
404 memory
->_locale
= locale
? CFLocaleCreateCopy(allocator
, locale
) : (CFLocaleRef
)CFRetain(CFLocaleGetSystem());
405 memory
->_property
._TimeZone
= CFTimeZoneCopyDefault();
406 __ResetUDateFormat(memory
, false);
411 return (CFDateFormatterRef
)memory
;
414 extern CFDictionaryRef
__CFLocaleGetPrefs(CFLocaleRef locale
);
416 static void __substituteFormatStringFromPrefsDFRelative(CFDateFormatterRef formatter
) {
417 CFDictionaryRef prefs
= __CFLocaleGetPrefs(formatter
->_locale
);
419 CFIndex dateLen
= -1;
420 UChar dateBuffer
[BUFFER_SIZE
];
421 if (kCFDateFormatterNoStyle
!= formatter
->_dateStyle
) {
422 CFPropertyListRef metapref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleICUDateFormatStrings")) : NULL
;
423 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFDictionaryGetTypeID()) {
425 switch (formatter
->_dateStyle
) {
426 case kCFDateFormatterShortStyle
: key
= CFSTR("1"); break;
427 case kCFDateFormatterMediumStyle
: key
= CFSTR("2"); break;
428 case kCFDateFormatterLongStyle
: key
= CFSTR("3"); break;
429 case kCFDateFormatterFullStyle
: key
= CFSTR("4"); break;
430 default: key
= CFSTR("0"); break;
432 CFStringRef pref
= (CFStringRef
)CFDictionaryGetValue((CFDictionaryRef
)metapref
, key
);
433 if (NULL
!= pref
&& CFGetTypeID(pref
) == CFStringGetTypeID()) {
434 dateLen
= __CFMin(CFStringGetLength(pref
), BUFFER_SIZE
);
435 CFStringGetCharacters(pref
, CFRangeMake(0, dateLen
), (UniChar
*)dateBuffer
);
440 UErrorCode status
= U_ZERO_ERROR
;
441 int32_t ret
= udat_toPatternRelativeDate(formatter
->_df
, dateBuffer
, BUFFER_SIZE
, &status
);
442 if (!U_FAILURE(status
)) {
447 CFIndex timeLen
= -1;
448 UChar timeBuffer
[BUFFER_SIZE
];
449 if (kCFDateFormatterNoStyle
!= formatter
->_timeStyle
) {
450 CFPropertyListRef metapref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleICUTimeFormatStrings")) : NULL
;
451 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFDictionaryGetTypeID()) {
453 switch (formatter
->_timeStyle
) {
454 case kCFDateFormatterShortStyle
: key
= CFSTR("1"); break;
455 case kCFDateFormatterMediumStyle
: key
= CFSTR("2"); break;
456 case kCFDateFormatterLongStyle
: key
= CFSTR("3"); break;
457 case kCFDateFormatterFullStyle
: key
= CFSTR("4"); break;
458 default: key
= CFSTR("0"); break;
460 CFStringRef pref
= (CFStringRef
)CFDictionaryGetValue((CFDictionaryRef
)metapref
, key
);
461 if (NULL
!= pref
&& CFGetTypeID(pref
) == CFStringGetTypeID()) {
462 timeLen
= __CFMin(CFStringGetLength(pref
), BUFFER_SIZE
);
463 CFStringGetCharacters(pref
, CFRangeMake(0, timeLen
), (UniChar
*)timeBuffer
);
468 UErrorCode status
= U_ZERO_ERROR
;
469 int32_t ret
= udat_toPatternRelativeTime(formatter
->_df
, timeBuffer
, BUFFER_SIZE
, &status
);
470 if (!U_FAILURE(status
)) {
475 UErrorCode status
= U_ZERO_ERROR
;
476 udat_applyPatternRelative(formatter
->_df
, (0 <= dateLen
) ? dateBuffer
: NULL
, (0 <= dateLen
) ? dateLen
: 0, (0 <= timeLen
) ? timeBuffer
: NULL
, (0 <= timeLen
) ? timeLen
: 0, &status
);
479 static void __substituteFormatStringFromPrefsDF(CFDateFormatterRef formatter
, bool doTime
) {
480 CFIndex formatStyle
= doTime
? formatter
->_timeStyle
: formatter
->_dateStyle
;
481 CFStringRef prefName
= doTime
? CFSTR("AppleICUTimeFormatStrings") : CFSTR("AppleICUDateFormatStrings");
482 if (kCFDateFormatterNoStyle
!= formatStyle
) {
483 CFStringRef pref
= NULL
;
484 CFDictionaryRef prefs
= __CFLocaleGetPrefs(formatter
->_locale
);
485 CFPropertyListRef metapref
= prefs
? CFDictionaryGetValue(prefs
, prefName
) : NULL
;
486 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFDictionaryGetTypeID()) {
488 switch (formatStyle
) {
489 case kCFDateFormatterShortStyle
: key
= CFSTR("1"); break;
490 case kCFDateFormatterMediumStyle
: key
= CFSTR("2"); break;
491 case kCFDateFormatterLongStyle
: key
= CFSTR("3"); break;
492 case kCFDateFormatterFullStyle
: key
= CFSTR("4"); break;
493 default: key
= CFSTR("0"); break;
495 pref
= (CFStringRef
)CFDictionaryGetValue((CFDictionaryRef
)metapref
, key
);
497 if (NULL
!= pref
&& CFGetTypeID(pref
) == CFStringGetTypeID()) {
498 int32_t icustyle
= UDAT_NONE
;
499 switch (formatStyle
) {
500 case kCFDateFormatterShortStyle
: icustyle
= UDAT_SHORT
; break;
501 case kCFDateFormatterMediumStyle
: icustyle
= UDAT_MEDIUM
; break;
502 case kCFDateFormatterLongStyle
: icustyle
= UDAT_LONG
; break;
503 case kCFDateFormatterFullStyle
: icustyle
= UDAT_FULL
; break;
505 CFStringRef localeName
= CFLocaleGetIdentifier(formatter
->_locale
);
506 char buffer
[BUFFER_SIZE
];
507 const char *cstr
= CFStringGetCStringPtr(localeName
, kCFStringEncodingASCII
);
509 if (CFStringGetCString(localeName
, buffer
, BUFFER_SIZE
, kCFStringEncodingASCII
)) cstr
= buffer
;
511 UErrorCode status
= U_ZERO_ERROR
;
512 UDateFormat
*df
= udat_open((UDateFormatStyle
)(doTime
? icustyle
: UDAT_NONE
), (UDateFormatStyle
)(doTime
? UDAT_NONE
: icustyle
), cstr
, NULL
, 0, NULL
, 0, &status
);
514 UChar ubuffer
[BUFFER_SIZE
];
515 status
= U_ZERO_ERROR
;
516 int32_t date_len
= udat_toPattern(df
, false, ubuffer
, BUFFER_SIZE
, &status
);
517 if (U_SUCCESS(status
) && date_len
<= BUFFER_SIZE
) {
518 CFStringRef dateString
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (UniChar
*)ubuffer
, date_len
);
519 status
= U_ZERO_ERROR
;
520 int32_t formatter_len
= udat_toPattern(formatter
->_df
, false, ubuffer
, BUFFER_SIZE
, &status
);
521 if (U_SUCCESS(status
) && formatter_len
<= BUFFER_SIZE
) {
522 CFMutableStringRef formatString
= CFStringCreateMutable(kCFAllocatorSystemDefault
, 0);
523 CFStringAppendCharacters(formatString
, (UniChar
*)ubuffer
, formatter_len
);
524 // find dateString inside formatString, substitute the pref in that range
526 if (CFStringFindWithOptions(formatString
, dateString
, CFRangeMake(0, formatter_len
), 0, &result
)) {
527 CFStringReplace(formatString
, result
, pref
);
528 int32_t new_len
= CFStringGetLength(formatString
);
529 STACK_BUFFER_DECL(UChar
, new_buffer
, new_len
);
530 const UChar
*new_ustr
= (UChar
*)CFStringGetCharactersPtr(formatString
);
531 if (NULL
== new_ustr
) {
532 CFStringGetCharacters(formatString
, CFRangeMake(0, new_len
), (UniChar
*)new_buffer
);
533 new_ustr
= new_buffer
;
535 status
= U_ZERO_ERROR
;
536 // udat_applyPattern(formatter->_df, false, new_ustr, new_len, &status);
537 udat_applyPattern(formatter
->_df
, false, new_ustr
, new_len
);
539 CFRelease(formatString
);
541 CFRelease(dateString
);
549 static void __CFDateFormatterApplySymbolPrefs(const void *key
, const void *value
, void *context
) {
550 if (CFGetTypeID(key
) == CFStringGetTypeID() && CFGetTypeID(value
) == CFArrayGetTypeID()) {
551 CFDateFormatterRef formatter
= (CFDateFormatterRef
)context
;
552 UDateFormatSymbolType sym
= (UDateFormatSymbolType
)CFStringGetIntValue((CFStringRef
)key
);
553 CFArrayRef array
= (CFArrayRef
)value
;
554 CFIndex idx
, cnt
= CFArrayGetCount(array
);
555 for (idx
= 0; idx
< cnt
; idx
++) {
556 CFStringRef item
= (CFStringRef
)CFArrayGetValueAtIndex(array
, idx
);
557 if (CFGetTypeID(item
) != CFStringGetTypeID()) continue;
558 CFIndex item_cnt
= CFStringGetLength(item
);
559 STACK_BUFFER_DECL(UChar
, item_buffer
, __CFMin(BUFFER_SIZE
, item_cnt
));
560 UChar
*item_ustr
= (UChar
*)CFStringGetCharactersPtr(item
);
561 if (NULL
== item_ustr
) {
562 item_cnt
= __CFMin(BUFFER_SIZE
, item_cnt
);
563 CFStringGetCharacters(item
, CFRangeMake(0, item_cnt
), (UniChar
*)item_buffer
);
564 item_ustr
= item_buffer
;
566 UErrorCode status
= U_ZERO_ERROR
;
567 udat_setSymbols(formatter
->_df
, sym
, idx
, item_ustr
, item_cnt
, &status
);
572 static CFStringRef
__CFDateFormatterCreateForcedString(CFDateFormatterRef formatter
, CFStringRef inString
) {
573 if (!inString
) return NULL
;
574 Boolean doForce24
= false, doForce12
= false;
575 CFDictionaryRef prefs
= __CFLocaleGetPrefs(formatter
->_locale
);
576 CFPropertyListRef pref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleICUForce24HourTime")) : NULL
;
577 if (NULL
!= pref
&& CFGetTypeID(pref
) == CFBooleanGetTypeID()) {
578 doForce24
= CFBooleanGetValue((CFBooleanRef
)pref
);
580 pref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleICUForce12HourTime")) : NULL
;
581 if (NULL
!= pref
&& CFGetTypeID(pref
) == CFBooleanGetTypeID()) {
582 doForce12
= CFBooleanGetValue((CFBooleanRef
)pref
);
584 if (!doForce24
&& !doForce12
) return (CFStringRef
)CFRetain(inString
);
585 if (doForce24
) doForce12
= false; // if both are set, Force24 wins, period
586 CFMutableStringRef outString
= CFStringCreateMutable(kCFAllocatorSystemDefault
, 0);
587 CFIndex cnt
= CFStringGetLength(inString
);
588 CFIndex lastSecond
= -1, lastMinute
= -1, firstHour
= -1;
589 Boolean isInQuote
= false, hasA
= false, had12Hour
= false, had24Hour
= false;
590 for (CFIndex idx
= 0; idx
< cnt
; idx
++) {
592 UniChar ch
= CFStringGetCharacterAtIndex(inString
, idx
);
594 case '\'': isInQuote
= !isInQuote
; break;
595 case 'h': if (!isInQuote
) {if (-1 == firstHour
) firstHour
= CFStringGetLength(outString
); had12Hour
= true; if (doForce24
) ch
= 'H';} break; // switch 12-hour to 24-hour
596 case 'K': if (!isInQuote
) {if (-1 == firstHour
) firstHour
= CFStringGetLength(outString
); had12Hour
= true; if (doForce24
) ch
= 'k';} break; // switch 12-hour to 24-hour
597 case 'H': if (!isInQuote
) {if (-1 == firstHour
) firstHour
= CFStringGetLength(outString
); had24Hour
= true; if (doForce12
) ch
= 'h';} break; // switch 24-hour to 12-hour
598 case 'k': if (!isInQuote
) {if (-1 == firstHour
) firstHour
= CFStringGetLength(outString
); had24Hour
= true; if (doForce12
) ch
= 'K';} break; // switch 24-hour to 12-hour
599 case 'm': if (!isInQuote
) lastMinute
= CFStringGetLength(outString
); break;
600 case 's': if (!isInQuote
) lastSecond
= CFStringGetLength(outString
); break;
601 case 'a': if (!isInQuote
) hasA
= true;
602 if (!isInQuote
&& doForce24
) {
603 // skip 'a' and one optional trailing space
605 if (idx
+ 1 < cnt
&& ' ' == CFStringGetCharacterAtIndex(inString
, idx
+ 1)) idx
++;
609 if (!isInQuote
&& doForce24
) {
610 // if next character is 'a' AND we have seen the hour designator, skip space and 'a'
611 if (idx
+ 1 < cnt
&& 'a' == CFStringGetCharacterAtIndex(inString
, idx
+ 1) && -1 != firstHour
) {
618 if (emit
) CFStringAppendCharacters(outString
, &ch
, 1);
620 if (doForce12
&& !hasA
&& had24Hour
) {
621 CFStringRef locName
= CFLocaleGetIdentifier(formatter
->_locale
);
622 if (-1 != firstHour
&& (CFStringHasPrefix(locName
, CFSTR("ko")) || CFEqual(locName
, CFSTR("zh_SG")))) {
623 CFStringInsert(outString
, firstHour
, CFSTR("a "));
624 } else if (-1 != firstHour
&& (CFStringHasPrefix(locName
, CFSTR("zh")) || CFStringHasPrefix(locName
, CFSTR("ja")))) {
625 CFStringInsert(outString
, firstHour
, CFSTR("a"));
627 CFIndex lastPos
= (-1 != lastSecond
) ? lastSecond
: ((-1 != lastMinute
) ? lastMinute
: -1);
629 cnt
= CFStringGetLength(outString
);
631 UniChar ch
= (lastPos
< cnt
) ? CFStringGetCharacterAtIndex(outString
, lastPos
) : 0;
633 case '\"': lastPos
++; break;
638 ch
= (lastPos
< cnt
) ? CFStringGetCharacterAtIndex(outString
, lastPos
) : 0;
639 } while ('\'' != ch
&& '\0' != ch
);
640 if ('\'' == ch
) lastPos
++;
641 ch
= (lastPos
< cnt
) ? CFStringGetCharacterAtIndex(outString
, lastPos
) : 0;
642 if ('\'' == ch
) goto again
;
645 CFStringInsert(outString
, lastPos
, CFSTR(" a"));
652 static void __CFDateFormatterCustomize(CFDateFormatterRef formatter
) {
653 Boolean wantRelative
= (NULL
!= formatter
->_property
._DoesRelativeDateFormatting
&& formatter
->_property
._DoesRelativeDateFormatting
== kCFBooleanTrue
);
654 Boolean hasFormat
= (NULL
!= formatter
->_property
._HasCustomFormat
&& formatter
->_property
._HasCustomFormat
== kCFBooleanTrue
);
655 if (wantRelative
&& !hasFormat
) {
656 __substituteFormatStringFromPrefsDFRelative(formatter
);
658 __substituteFormatStringFromPrefsDF(formatter
, false);
659 __substituteFormatStringFromPrefsDF(formatter
, true);
661 CFDictionaryRef prefs
= __CFLocaleGetPrefs(formatter
->_locale
);
662 CFPropertyListRef metapref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleICUDateTimeSymbols")) : NULL
;
663 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFDictionaryGetTypeID()) {
664 CFDictionaryApplyFunction((CFDictionaryRef
)metapref
, __CFDateFormatterApplySymbolPrefs
, formatter
);
666 metapref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleFirstWeekday")) : NULL
;
667 CFStringRef calID
= (CFStringRef
)CFLocaleGetValue(formatter
->_locale
, kCFLocaleCalendarIdentifierKey
);
668 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFDictionaryGetTypeID()) {
669 metapref
= (CFNumberRef
)CFDictionaryGetValue((CFDictionaryRef
)metapref
, calID
);
671 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFNumberGetTypeID()) {
673 if (CFNumberGetValue((CFNumberRef
)metapref
, kCFNumberCFIndexType
, &wkdy
)) {
674 UCalendar
*cal
= (UCalendar
*)udat_getCalendar(formatter
->_df
);
675 if (cal
) ucal_setAttribute(cal
, UCAL_FIRST_DAY_OF_WEEK
, wkdy
);
678 metapref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleMinDaysInFirstWeek")) : NULL
;
679 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFDictionaryGetTypeID()) {
680 metapref
= (CFNumberRef
)CFDictionaryGetValue((CFDictionaryRef
)metapref
, calID
);
682 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFNumberGetTypeID()) {
684 if (CFNumberGetValue((CFNumberRef
)metapref
, kCFNumberCFIndexType
, &mwd
)) {
685 UCalendar
*cal
= (UCalendar
*)udat_getCalendar(formatter
->_df
);
686 if (cal
) ucal_setAttribute(cal
, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK
, mwd
);
691 CFLocaleRef
CFDateFormatterGetLocale(CFDateFormatterRef formatter
) {
692 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
693 return formatter
->_locale
;
696 CFDateFormatterStyle
CFDateFormatterGetDateStyle(CFDateFormatterRef formatter
) {
697 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
698 return formatter
->_dateStyle
;
701 CFDateFormatterStyle
CFDateFormatterGetTimeStyle(CFDateFormatterRef formatter
) {
702 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
703 return formatter
->_timeStyle
;
706 CFStringRef
CFDateFormatterGetFormat(CFDateFormatterRef formatter
) {
707 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
708 return formatter
->_format
;
711 void CFDateFormatterSetFormat(CFDateFormatterRef formatter
, CFStringRef formatString
) {
712 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
713 __CFGenericValidateType(formatString
, CFStringGetTypeID());
714 formatString
= __CFDateFormatterCreateForcedString(formatter
, formatString
);
715 CFIndex cnt
= CFStringGetLength(formatString
);
716 CFAssert1(cnt
<= 1024, __kCFLogAssertion
, "%s(): format string too long", __PRETTY_FUNCTION__
);
717 if (formatter
->_format
!= formatString
&& cnt
<= 1024) {
718 __ResetUDateFormat(formatter
, true);
719 STACK_BUFFER_DECL(UChar
, ubuffer
, cnt
);
720 const UChar
*ustr
= (UChar
*)CFStringGetCharactersPtr((CFStringRef
)formatString
);
722 CFStringGetCharacters(formatString
, CFRangeMake(0, cnt
), (UniChar
*)ubuffer
);
725 UErrorCode status
= U_ZERO_ERROR
;
726 // udat_applyPattern(formatter->_df, false, ustr, cnt, &status);
727 udat_applyPattern(formatter
->_df
, false, ustr
, cnt
);
728 if (U_SUCCESS(status
)) {
729 if (formatter
->_format
) CFRelease(formatter
->_format
);
730 formatter
->_format
= (CFStringRef
)CFStringCreateCopy(CFGetAllocator(formatter
), formatString
);
733 if (formatString
) CFRelease(formatString
);
736 CFStringRef
CFDateFormatterCreateStringWithDate(CFAllocatorRef allocator
, CFDateFormatterRef formatter
, CFDateRef date
) {
737 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
738 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
739 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
740 __CFGenericValidateType(date
, CFDateGetTypeID());
741 return CFDateFormatterCreateStringWithAbsoluteTime(allocator
, formatter
, CFDateGetAbsoluteTime(date
));
744 CFStringRef
CFDateFormatterCreateStringWithAbsoluteTime(CFAllocatorRef allocator
, CFDateFormatterRef formatter
, CFAbsoluteTime at
) {
745 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
746 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
747 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
748 UChar
*ustr
= NULL
, ubuffer
[BUFFER_SIZE
];
749 UErrorCode status
= U_ZERO_ERROR
;
750 CFIndex used
, cnt
= BUFFER_SIZE
;
751 UDate ud
= (at
+ kCFAbsoluteTimeIntervalSince1970
) * 1000.0 + 0.5;
752 used
= udat_format(formatter
->_df
, ud
, ubuffer
, cnt
, NULL
, &status
);
753 if (status
== U_BUFFER_OVERFLOW_ERROR
|| cnt
< used
) {
755 ustr
= (UChar
*)CFAllocatorAllocate(kCFAllocatorSystemDefault
, sizeof(UChar
) * cnt
, 0);
756 status
= U_ZERO_ERROR
;
757 used
= udat_format(formatter
->_df
, ud
, ustr
, cnt
, NULL
, &status
);
759 CFStringRef string
= NULL
;
760 if (U_SUCCESS(status
)) {
761 string
= CFStringCreateWithCharacters(allocator
, (const UniChar
*)(ustr
? ustr
: ubuffer
), used
);
763 if (ustr
) CFAllocatorDeallocate(kCFAllocatorSystemDefault
, ustr
);
767 CFDateRef
CFDateFormatterCreateDateFromString(CFAllocatorRef allocator
, CFDateFormatterRef formatter
, CFStringRef string
, CFRange
*rangep
) {
768 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
769 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
770 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
771 __CFGenericValidateType(string
, CFStringGetTypeID());
773 if (CFDateFormatterGetAbsoluteTimeFromString(formatter
, string
, rangep
, &at
)) {
774 return CFDateCreate(allocator
, at
);
779 Boolean
CFDateFormatterGetAbsoluteTimeFromString(CFDateFormatterRef formatter
, CFStringRef string
, CFRange
*rangep
, CFAbsoluteTime
*atp
) {
780 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
781 __CFGenericValidateType(string
, CFStringGetTypeID());
782 CFRange range
= {0, 0};
786 range
.length
= CFStringGetLength(string
);
788 if (1024 < range
.length
) range
.length
= 1024;
789 const UChar
*ustr
= (UChar
*)CFStringGetCharactersPtr(string
);
790 STACK_BUFFER_DECL(UChar
, ubuffer
, (NULL
== ustr
) ? range
.length
: 1);
792 CFStringGetCharacters(string
, range
, (UniChar
*)ubuffer
);
795 ustr
+= range
.location
;
799 UErrorCode status
= U_ZERO_ERROR
;
800 if (formatter
->_property
._DefaultDate
) {
801 CFAbsoluteTime at
= CFDateGetAbsoluteTime(formatter
->_property
._DefaultDate
);
802 udate
= (at
+ kCFAbsoluteTimeIntervalSince1970
) * 1000.0;
803 UDateFormat
*df2
= udat_clone(formatter
->_df
, &status
);
804 UCalendar
*cal2
= (UCalendar
*)udat_getCalendar(df2
);
805 ucal_setMillis(cal2
, udate
, &status
);
806 udat_parseCalendar(formatter
->_df
, cal2
, ustr
, range
.length
, &dpos
, &status
);
807 udate
= ucal_getMillis(cal2
, &status
);
810 udate
= udat_parse(formatter
->_df
, ustr
, range
.length
, &dpos
, &status
);
812 if (rangep
) rangep
->length
= dpos
;
813 if (U_FAILURE(status
)) {
817 *atp
= (double)udate
/ 1000.0 - kCFAbsoluteTimeIntervalSince1970
;
822 static void __CFDateFormatterSetSymbolsArray(UDateFormat
*icudf
, int32_t icucode
, int index_base
, CFTypeRef value
) {
823 UErrorCode status
= U_ZERO_ERROR
;
824 __CFGenericValidateType(value
, CFArrayGetTypeID());
825 CFArrayRef array
= (CFArrayRef
)value
;
826 CFIndex idx
, cnt
= CFArrayGetCount(array
);
827 for (idx
= 0; idx
< cnt
; idx
++) {
828 CFStringRef item
= (CFStringRef
)CFArrayGetValueAtIndex(array
, idx
);
829 __CFGenericValidateType(item
, CFStringGetTypeID());
830 CFIndex item_cnt
= CFStringGetLength(item
);
831 STACK_BUFFER_DECL(UChar
, item_buffer
, __CFMin(BUFFER_SIZE
, item_cnt
));
832 UChar
*item_ustr
= (UChar
*)CFStringGetCharactersPtr(item
);
833 if (NULL
== item_ustr
) {
834 item_cnt
= __CFMin(BUFFER_SIZE
, item_cnt
);
835 CFStringGetCharacters(item
, CFRangeMake(0, item_cnt
), (UniChar
*)item_buffer
);
836 item_ustr
= item_buffer
;
838 status
= U_ZERO_ERROR
;
839 udat_setSymbols(icudf
, (UDateFormatSymbolType
)icucode
, idx
+ index_base
, item_ustr
, item_cnt
, &status
);
843 static CFArrayRef
__CFDateFormatterGetSymbolsArray(UDateFormat
*icudf
, int32_t icucode
, int index_base
) {
844 UErrorCode status
= U_ZERO_ERROR
;
845 CFIndex idx
, cnt
= udat_countSymbols(icudf
, (UDateFormatSymbolType
)icucode
) - index_base
;
846 STACK_BUFFER_DECL(CFStringRef
, strings
, cnt
);
847 for (idx
= 0; idx
< cnt
; idx
++) {
848 UChar ubuffer
[BUFFER_SIZE
];
849 CFStringRef str
= NULL
;
850 status
= U_ZERO_ERROR
;
851 CFIndex ucnt
= udat_getSymbols(icudf
, (UDateFormatSymbolType
)icucode
, idx
+ index_base
, ubuffer
, BUFFER_SIZE
, &status
);
852 if (U_SUCCESS(status
) && cnt
<= BUFFER_SIZE
) {
853 str
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (const UniChar
*)ubuffer
, ucnt
);
855 strings
[idx
] = !str
? (CFStringRef
)CFRetain(CFSTR("<error>")) : str
;
857 CFArrayRef array
= CFArrayCreate(kCFAllocatorSystemDefault
, (const void **)strings
, cnt
, &kCFTypeArrayCallBacks
);
859 CFRelease(strings
[cnt
]);
864 #define SET_SYMBOLS_ARRAY(A, B, C) \
865 if (!directToICU) { \
866 oldProperty = formatter->_property. C; \
867 formatter->_property. C = NULL; \
869 __CFDateFormatterSetSymbolsArray(formatter->_df, A, B, value); \
870 if (!directToICU) { \
871 formatter->_property. C = __CFDateFormatterGetSymbolsArray(formatter->_df, A, B); \
874 static void __CFDateFormatterSetProperty(CFDateFormatterRef formatter
, CFStringRef key
, CFTypeRef value
, Boolean directToICU
) {
875 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
876 __CFGenericValidateType(key
, CFStringGetTypeID());
877 CFTypeRef oldProperty
= NULL
;
878 UErrorCode status
= U_ZERO_ERROR
;
879 UChar ubuffer
[BUFFER_SIZE
];
881 if (kCFDateFormatterIsLenientKey
== key
) {
883 oldProperty
= formatter
->_property
. _IsLenient
;
884 formatter
->_property
. _IsLenient
= NULL
;
886 __CFGenericValidateType(value
, CFBooleanGetTypeID());
887 udat_setLenient(formatter
->_df
, (kCFBooleanTrue
== value
));
888 UCalendar
*cal
= (UCalendar
*)udat_getCalendar(formatter
->_df
);
889 if (cal
) ucal_setAttribute(cal
, UCAL_LENIENT
, (kCFBooleanTrue
== value
));
891 formatter
->_property
. _IsLenient
= (CFBooleanRef
)CFDateFormatterCopyProperty(formatter
, kCFDateFormatterIsLenientKey
);
893 } else if (kCFDateFormatterDoesRelativeDateFormattingKey
== key
) {
895 oldProperty
= formatter
->_property
. _DoesRelativeDateFormatting
;
896 formatter
->_property
. _DoesRelativeDateFormatting
= NULL
;
898 __CFGenericValidateType(value
, CFBooleanGetTypeID());
900 if (kCFBooleanTrue
!= value
) value
= kCFBooleanFalse
;
901 formatter
->_property
. _DoesRelativeDateFormatting
= value
? (CFBooleanRef
)CFRetain(value
) : NULL
;
902 __ResetUDateFormat(formatter
, false);
904 } else if (kCFDateFormatterCalendarKey
== key
) {
906 oldProperty
= formatter
->_property
. _Calendar
;
907 formatter
->_property
. _Calendar
= NULL
;
909 __CFGenericValidateType(value
, CFCalendarGetTypeID());
910 CFStringRef localeName
= CFLocaleGetIdentifier(formatter
->_locale
);
911 CFDictionaryRef components
= CFLocaleCreateComponentsFromLocaleIdentifier(kCFAllocatorSystemDefault
, localeName
);
912 CFMutableDictionaryRef mcomponents
= CFDictionaryCreateMutableCopy(kCFAllocatorSystemDefault
, 0, components
);
913 CFDictionarySetValue(mcomponents
, kCFLocaleCalendarIdentifierKey
, CFCalendarGetIdentifier((CFCalendarRef
)value
));
914 localeName
= CFLocaleCreateLocaleIdentifierFromComponents(kCFAllocatorSystemDefault
, mcomponents
);
915 CFRelease(mcomponents
);
916 CFRelease(components
);
917 CFLocaleRef newLocale
= CFLocaleCreate(CFGetAllocator(formatter
->_locale
), localeName
);
918 CFRelease(localeName
);
919 CFRelease(formatter
->_locale
);
920 formatter
->_locale
= newLocale
;
921 UCalendar
*cal
= __CFCalendarCreateUCalendar(NULL
, CFLocaleGetIdentifier(formatter
->_locale
), formatter
->_property
._TimeZone
);
922 if (cal
) ucal_setAttribute(cal
, UCAL_FIRST_DAY_OF_WEEK
, CFCalendarGetFirstWeekday((CFCalendarRef
)value
));
923 if (cal
) ucal_setAttribute(cal
, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK
, CFCalendarGetMinimumDaysInFirstWeek((CFCalendarRef
)value
));
924 if (cal
) udat_setCalendar(formatter
->_df
, cal
);
925 if (cal
) ucal_close(cal
);
927 formatter
->_property
. _Calendar
= (CFCalendarRef
)CFDateFormatterCopyProperty(formatter
, kCFDateFormatterCalendarKey
);
929 } else if (kCFDateFormatterCalendarIdentifierKey
== key
) {
931 oldProperty
= formatter
->_property
. _CalendarName
;
932 formatter
->_property
. _CalendarName
= NULL
;
934 __CFGenericValidateType(value
, CFStringGetTypeID());
935 CFStringRef localeName
= CFLocaleGetIdentifier(formatter
->_locale
);
936 CFDictionaryRef components
= CFLocaleCreateComponentsFromLocaleIdentifier(kCFAllocatorSystemDefault
, localeName
);
937 CFMutableDictionaryRef mcomponents
= CFDictionaryCreateMutableCopy(kCFAllocatorSystemDefault
, 0, components
);
938 CFDictionarySetValue(mcomponents
, kCFLocaleCalendarIdentifierKey
, value
);
939 localeName
= CFLocaleCreateLocaleIdentifierFromComponents(kCFAllocatorSystemDefault
, mcomponents
);
940 CFRelease(mcomponents
);
941 CFRelease(components
);
942 CFLocaleRef newLocale
= CFLocaleCreate(CFGetAllocator(formatter
->_locale
), localeName
);
943 CFRelease(localeName
);
944 CFRelease(formatter
->_locale
);
945 formatter
->_locale
= newLocale
;
946 UCalendar
*cal
= __CFCalendarCreateUCalendar(NULL
, CFLocaleGetIdentifier(formatter
->_locale
), formatter
->_property
._TimeZone
);
947 if (cal
) udat_setCalendar(formatter
->_df
, cal
);
948 if (cal
) ucal_close(cal
);
950 formatter
->_property
. _CalendarName
= (CFStringRef
)CFDateFormatterCopyProperty(formatter
, kCFDateFormatterCalendarIdentifierKey
);
952 } else if (kCFDateFormatterTimeZoneKey
== key
) {
953 if (formatter
->_property
. _TimeZone
!= value
) {
955 oldProperty
= formatter
->_property
. _TimeZone
;
956 formatter
->_property
. _TimeZone
= NULL
;
958 __CFGenericValidateType(value
, CFTimeZoneGetTypeID());
959 CFTimeZoneRef old
= formatter
->_property
._TimeZone
;
960 formatter
->_property
._TimeZone
= value
? (CFTimeZoneRef
)CFRetain(value
) : CFTimeZoneCopyDefault();
961 if (old
) CFRelease(old
);
962 CFStringRef tznam
= CFTimeZoneGetName(formatter
->_property
._TimeZone
);
963 UCalendar
*cal
= (UCalendar
*)udat_getCalendar(formatter
->_df
);
964 CFIndex ucnt
= CFStringGetLength(tznam
);
965 if (BUFFER_SIZE
< ucnt
) ucnt
= BUFFER_SIZE
;
966 CFStringGetCharacters(tznam
, CFRangeMake(0, ucnt
), (UniChar
*)ubuffer
);
967 ucal_setTimeZone(cal
, ubuffer
, ucnt
, &status
);
969 old
= formatter
->_property
._TimeZone
;
970 formatter
->_property
. _TimeZone
= (CFTimeZoneRef
)CFDateFormatterCopyProperty(formatter
, kCFDateFormatterTimeZoneKey
);
971 if (old
) CFRelease(old
);
974 } else if (kCFDateFormatterDefaultFormatKey
== key
) {
975 // read-only attribute
976 } else if (kCFDateFormatterTwoDigitStartDateKey
== key
) {
978 oldProperty
= formatter
->_property
. _TwoDigitStartDate
;
979 formatter
->_property
. _TwoDigitStartDate
= NULL
;
981 __CFGenericValidateType(value
, CFDateGetTypeID());
982 CFAbsoluteTime at
= CFDateGetAbsoluteTime((CFDateRef
)value
);
983 UDate udate
= (at
+ kCFAbsoluteTimeIntervalSince1970
) * 1000.0;
984 udat_set2DigitYearStart(formatter
->_df
, udate
, &status
);
986 formatter
->_property
. _TwoDigitStartDate
= (CFDateRef
)CFDateFormatterCopyProperty(formatter
, kCFDateFormatterTwoDigitStartDateKey
);
988 } else if (kCFDateFormatterDefaultDateKey
== key
) {
990 oldProperty
= formatter
->_property
. _DefaultDate
;
991 formatter
->_property
. _DefaultDate
= NULL
;
993 __CFGenericValidateType(value
, CFDateGetTypeID());
995 formatter
->_property
._DefaultDate
= value
? (CFDateRef
)CFRetain(value
) : NULL
;
997 } else if (kCFDateFormatterGregorianStartDateKey
== key
) {
999 oldProperty
= formatter
->_property
. _GregorianStartDate
;
1000 formatter
->_property
. _GregorianStartDate
= NULL
;
1002 __CFGenericValidateType(value
, CFDateGetTypeID());
1003 CFAbsoluteTime at
= CFDateGetAbsoluteTime((CFDateRef
)value
);
1004 UDate udate
= (at
+ kCFAbsoluteTimeIntervalSince1970
) * 1000.0;
1005 UCalendar
*cal
= (UCalendar
*)udat_getCalendar(formatter
->_df
);
1006 ucal_setGregorianChange(cal
, udate
, &status
);
1008 formatter
->_property
. _GregorianStartDate
= (CFDateRef
)CFDateFormatterCopyProperty(formatter
, kCFDateFormatterGregorianStartDateKey
);
1010 } else if (kCFDateFormatterEraSymbolsKey
== key
) {
1011 SET_SYMBOLS_ARRAY(UDAT_ERAS
, 0, _EraSymbols
)
1012 } else if (kCFDateFormatterLongEraSymbolsKey
== key
) {
1013 SET_SYMBOLS_ARRAY(UDAT_ERA_NAMES
, 0, _LongEraSymbols
)
1014 } else if (kCFDateFormatterMonthSymbolsKey
== key
) {
1015 SET_SYMBOLS_ARRAY(UDAT_MONTHS
, 0, _MonthSymbols
)
1016 } else if (kCFDateFormatterShortMonthSymbolsKey
== key
) {
1017 SET_SYMBOLS_ARRAY(UDAT_SHORT_MONTHS
, 0, _ShortMonthSymbols
)
1018 } else if (kCFDateFormatterVeryShortMonthSymbolsKey
== key
) {
1019 SET_SYMBOLS_ARRAY(UDAT_NARROW_MONTHS
, 0, _VeryShortMonthSymbols
)
1020 } else if (kCFDateFormatterStandaloneMonthSymbolsKey
== key
) {
1021 SET_SYMBOLS_ARRAY(UDAT_STANDALONE_MONTHS
, 0, _StandaloneMonthSymbols
)
1022 } else if (kCFDateFormatterShortStandaloneMonthSymbolsKey
== key
) {
1023 SET_SYMBOLS_ARRAY(UDAT_STANDALONE_SHORT_MONTHS
, 0, _ShortStandaloneMonthSymbols
)
1024 } else if (kCFDateFormatterVeryShortStandaloneMonthSymbolsKey
== key
) {
1025 SET_SYMBOLS_ARRAY(UDAT_STANDALONE_NARROW_MONTHS
, 0, _VeryShortStandaloneMonthSymbols
)
1026 } else if (kCFDateFormatterWeekdaySymbolsKey
== key
) {
1027 SET_SYMBOLS_ARRAY(UDAT_WEEKDAYS
, 1, _WeekdaySymbols
)
1028 } else if (kCFDateFormatterShortWeekdaySymbolsKey
== key
) {
1029 SET_SYMBOLS_ARRAY(UDAT_SHORT_WEEKDAYS
, 1, _ShortWeekdaySymbols
)
1030 } else if (kCFDateFormatterVeryShortWeekdaySymbolsKey
== key
) {
1031 SET_SYMBOLS_ARRAY(UDAT_NARROW_WEEKDAYS
, 1, _VeryShortWeekdaySymbols
)
1032 } else if (kCFDateFormatterStandaloneWeekdaySymbolsKey
== key
) {
1033 SET_SYMBOLS_ARRAY(UDAT_STANDALONE_WEEKDAYS
, 1, _StandaloneWeekdaySymbols
)
1034 } else if (kCFDateFormatterShortStandaloneWeekdaySymbolsKey
== key
) {
1035 SET_SYMBOLS_ARRAY(UDAT_STANDALONE_SHORT_WEEKDAYS
, 1, _ShortStandaloneWeekdaySymbols
)
1036 } else if (kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey
== key
) {
1037 SET_SYMBOLS_ARRAY(UDAT_STANDALONE_NARROW_WEEKDAYS
, 1, _VeryShortStandaloneWeekdaySymbols
)
1038 } else if (kCFDateFormatterQuarterSymbolsKey
== key
) {
1039 SET_SYMBOLS_ARRAY(UDAT_QUARTERS
, 0, _QuarterSymbols
)
1040 } else if (kCFDateFormatterShortQuarterSymbolsKey
== key
) {
1041 SET_SYMBOLS_ARRAY(UDAT_SHORT_QUARTERS
, 0, _ShortQuarterSymbols
)
1042 } else if (kCFDateFormatterStandaloneQuarterSymbolsKey
== key
) {
1043 SET_SYMBOLS_ARRAY(UDAT_STANDALONE_QUARTERS
, 0, _StandaloneQuarterSymbols
)
1044 } else if (kCFDateFormatterShortStandaloneQuarterSymbolsKey
== key
) {
1045 SET_SYMBOLS_ARRAY(UDAT_STANDALONE_SHORT_QUARTERS
, 0, _ShortStandaloneQuarterSymbols
)
1046 } else if (kCFDateFormatterAMSymbolKey
== key
) {
1048 oldProperty
= formatter
->_property
. _AMSymbol
;
1049 formatter
->_property
. _AMSymbol
= NULL
;
1051 __CFGenericValidateType(value
, CFStringGetTypeID());
1052 CFIndex item_cnt
= CFStringGetLength((CFStringRef
)value
);
1053 STACK_BUFFER_DECL(UChar
, item_buffer
, __CFMin(BUFFER_SIZE
, item_cnt
));
1054 UChar
*item_ustr
= (UChar
*)CFStringGetCharactersPtr((CFStringRef
)value
);
1055 if (NULL
== item_ustr
) {
1056 item_cnt
= __CFMin(BUFFER_SIZE
, item_cnt
);
1057 CFStringGetCharacters((CFStringRef
)value
, CFRangeMake(0, item_cnt
), (UniChar
*)item_buffer
);
1058 item_ustr
= item_buffer
;
1060 udat_setSymbols(formatter
->_df
, UDAT_AM_PMS
, 0, item_ustr
, item_cnt
, &status
);
1062 formatter
->_property
. _AMSymbol
= (CFStringRef
)CFDateFormatterCopyProperty(formatter
, kCFDateFormatterAMSymbolKey
);
1064 } else if (kCFDateFormatterPMSymbolKey
== key
) {
1066 oldProperty
= formatter
->_property
. _PMSymbol
;
1067 formatter
->_property
. _PMSymbol
= NULL
;
1069 __CFGenericValidateType(value
, CFStringGetTypeID());
1070 CFIndex item_cnt
= CFStringGetLength((CFStringRef
)value
);
1071 STACK_BUFFER_DECL(UChar
, item_buffer
, __CFMin(BUFFER_SIZE
, item_cnt
));
1072 UChar
*item_ustr
= (UChar
*)CFStringGetCharactersPtr((CFStringRef
)value
);
1073 if (NULL
== item_ustr
) {
1074 item_cnt
= __CFMin(BUFFER_SIZE
, item_cnt
);
1075 CFStringGetCharacters((CFStringRef
)value
, CFRangeMake(0, item_cnt
), (UniChar
*)item_buffer
);
1076 item_ustr
= item_buffer
;
1078 udat_setSymbols(formatter
->_df
, UDAT_AM_PMS
, 1, item_ustr
, item_cnt
, &status
);
1080 formatter
->_property
. _PMSymbol
= (CFStringRef
)CFDateFormatterCopyProperty(formatter
, kCFDateFormatterPMSymbolKey
);
1083 CFAssert3(0, __kCFLogAssertion
, "%s(): unknown key %p (%@)", __PRETTY_FUNCTION__
, key
, key
);
1085 if (oldProperty
) CFRelease(oldProperty
);
1088 void CFDateFormatterSetProperty(CFDateFormatterRef formatter
, CFStringRef key
, CFTypeRef value
) {
1089 __CFDateFormatterSetProperty(formatter
, key
, value
, false);
1092 CFTypeRef
CFDateFormatterCopyProperty(CFDateFormatterRef formatter
, CFStringRef key
) {
1093 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
1094 __CFGenericValidateType(key
, CFStringGetTypeID());
1095 UErrorCode status
= U_ZERO_ERROR
;
1096 UChar ubuffer
[BUFFER_SIZE
];
1098 if (kCFDateFormatterIsLenientKey
== key
) {
1099 if (formatter
->_property
._IsLenient
) return CFRetain(formatter
->_property
._IsLenient
);
1100 return CFRetain(udat_isLenient(formatter
->_df
) ? kCFBooleanTrue
: kCFBooleanFalse
);
1101 } else if (kCFDateFormatterDoesRelativeDateFormattingKey
== key
) {
1102 if (formatter
->_property
._DoesRelativeDateFormatting
) return CFRetain(formatter
->_property
._DoesRelativeDateFormatting
);
1103 return CFRetain(kCFBooleanFalse
);
1104 } else if (kCFDateFormatterCalendarKey
== key
) {
1105 if (formatter
->_property
._Calendar
) return CFRetain(formatter
->_property
._Calendar
);
1106 CFCalendarRef calendar
= (CFCalendarRef
)CFLocaleGetValue(formatter
->_locale
, kCFLocaleCalendarKey
);
1107 return calendar
? CFRetain(calendar
) : NULL
;
1108 } else if (kCFDateFormatterCalendarIdentifierKey
== key
) {
1109 if (formatter
->_property
._CalendarName
) return CFRetain(formatter
->_property
._CalendarName
);
1110 CFStringRef ident
= (CFStringRef
)CFLocaleGetValue(formatter
->_locale
, kCFLocaleCalendarIdentifierKey
);
1111 return ident
? CFRetain(ident
) : NULL
;
1112 } else if (kCFDateFormatterTimeZoneKey
== key
) {
1113 if (formatter
->_property
._TwoDigitStartDate
) return CFRetain(formatter
->_property
._TwoDigitStartDate
);
1114 return CFRetain(formatter
->_property
._TimeZone
);
1115 } else if (kCFDateFormatterDefaultFormatKey
== key
) {
1116 return formatter
->_defformat
? CFRetain(formatter
->_defformat
) : NULL
;
1117 } else if (kCFDateFormatterTwoDigitStartDateKey
== key
) {
1118 if (formatter
->_property
._TwoDigitStartDate
) return CFRetain(formatter
->_property
._TwoDigitStartDate
);
1119 UDate udate
= udat_get2DigitYearStart(formatter
->_df
, &status
);
1120 if (U_SUCCESS(status
)) {
1121 CFAbsoluteTime at
= (double)udate
/ 1000.0 - kCFAbsoluteTimeIntervalSince1970
;
1122 return CFDateCreate(CFGetAllocator(formatter
), at
);
1124 } else if (kCFDateFormatterDefaultDateKey
== key
) {
1125 return formatter
->_property
._DefaultDate
? CFRetain(formatter
->_property
._DefaultDate
) : NULL
;
1126 } else if (kCFDateFormatterGregorianStartDateKey
== key
) {
1127 if (formatter
->_property
._GregorianStartDate
) return CFRetain(formatter
->_property
._GregorianStartDate
);
1128 UCalendar
*cal
= (UCalendar
*)udat_getCalendar(formatter
->_df
);
1129 UDate udate
= ucal_getGregorianChange(cal
, &status
);
1130 if (U_SUCCESS(status
)) {
1131 CFAbsoluteTime at
= (double)udate
/ 1000.0 - kCFAbsoluteTimeIntervalSince1970
;
1132 return CFDateCreate(CFGetAllocator(formatter
), at
);
1134 } else if (kCFDateFormatterEraSymbolsKey
== key
) {
1135 if (formatter
->_property
._EraSymbols
) return CFRetain(formatter
->_property
._EraSymbols
);
1136 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_ERAS
, 0);
1137 } else if (kCFDateFormatterLongEraSymbolsKey
== key
) {
1138 if (formatter
->_property
._LongEraSymbols
) return CFRetain(formatter
->_property
._LongEraSymbols
);
1139 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_ERA_NAMES
, 0);
1140 } else if (kCFDateFormatterMonthSymbolsKey
== key
) {
1141 if (formatter
->_property
._MonthSymbols
) return CFRetain(formatter
->_property
._MonthSymbols
);
1142 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_MONTHS
, 0);
1143 } else if (kCFDateFormatterShortMonthSymbolsKey
== key
) {
1144 if (formatter
->_property
._ShortMonthSymbols
) return CFRetain(formatter
->_property
._ShortMonthSymbols
);
1145 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_SHORT_MONTHS
, 0);
1146 } else if (kCFDateFormatterVeryShortMonthSymbolsKey
== key
) {
1147 if (formatter
->_property
._VeryShortMonthSymbols
) return CFRetain(formatter
->_property
._VeryShortMonthSymbols
);
1148 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_NARROW_MONTHS
, 0);
1149 } else if (kCFDateFormatterStandaloneMonthSymbolsKey
== key
) {
1150 if (formatter
->_property
._StandaloneMonthSymbols
) return CFRetain(formatter
->_property
._StandaloneMonthSymbols
);
1151 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_STANDALONE_MONTHS
, 0);
1152 } else if (kCFDateFormatterShortStandaloneMonthSymbolsKey
== key
) {
1153 if (formatter
->_property
._ShortStandaloneMonthSymbols
) return CFRetain(formatter
->_property
._ShortStandaloneMonthSymbols
);
1154 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_STANDALONE_SHORT_MONTHS
, 0);
1155 } else if (kCFDateFormatterVeryShortStandaloneMonthSymbolsKey
== key
) {
1156 if (formatter
->_property
._VeryShortStandaloneMonthSymbols
) return CFRetain(formatter
->_property
._VeryShortStandaloneMonthSymbols
);
1157 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_STANDALONE_NARROW_MONTHS
, 0);
1158 } else if (kCFDateFormatterWeekdaySymbolsKey
== key
) {
1159 if (formatter
->_property
._WeekdaySymbols
) return CFRetain(formatter
->_property
._WeekdaySymbols
);
1160 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_WEEKDAYS
, 1);
1161 } else if (kCFDateFormatterShortWeekdaySymbolsKey
== key
) {
1162 if (formatter
->_property
._ShortWeekdaySymbols
) return CFRetain(formatter
->_property
._ShortWeekdaySymbols
);
1163 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_SHORT_WEEKDAYS
, 1);
1164 } else if (kCFDateFormatterVeryShortWeekdaySymbolsKey
== key
) {
1165 if (formatter
->_property
._VeryShortWeekdaySymbols
) return CFRetain(formatter
->_property
._VeryShortWeekdaySymbols
);
1166 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_NARROW_WEEKDAYS
, 1);
1167 } else if (kCFDateFormatterStandaloneWeekdaySymbolsKey
== key
) {
1168 if (formatter
->_property
._StandaloneWeekdaySymbols
) return CFRetain(formatter
->_property
._StandaloneWeekdaySymbols
);
1169 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_STANDALONE_WEEKDAYS
, 1);
1170 } else if (kCFDateFormatterShortStandaloneWeekdaySymbolsKey
== key
) {
1171 if (formatter
->_property
._ShortStandaloneWeekdaySymbols
) return CFRetain(formatter
->_property
._ShortStandaloneWeekdaySymbols
);
1172 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_STANDALONE_SHORT_WEEKDAYS
, 1);
1173 } else if (kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey
== key
) {
1174 if (formatter
->_property
._VeryShortStandaloneWeekdaySymbols
) return CFRetain(formatter
->_property
._VeryShortStandaloneWeekdaySymbols
);
1175 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_STANDALONE_NARROW_WEEKDAYS
, 1);
1176 } else if (kCFDateFormatterQuarterSymbolsKey
== key
) {
1177 if (formatter
->_property
._QuarterSymbols
) return CFRetain(formatter
->_property
._QuarterSymbols
);
1178 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_QUARTERS
, 0);
1179 } else if (kCFDateFormatterShortQuarterSymbolsKey
== key
) {
1180 if (formatter
->_property
._ShortQuarterSymbols
) return CFRetain(formatter
->_property
._ShortQuarterSymbols
);
1181 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_SHORT_QUARTERS
, 0);
1182 } else if (kCFDateFormatterStandaloneQuarterSymbolsKey
== key
) {
1183 if (formatter
->_property
._StandaloneQuarterSymbols
) return CFRetain(formatter
->_property
._StandaloneQuarterSymbols
);
1184 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_STANDALONE_QUARTERS
, 0);
1185 } else if (kCFDateFormatterShortStandaloneQuarterSymbolsKey
== key
) {
1186 if (formatter
->_property
._ShortStandaloneQuarterSymbols
) return CFRetain(formatter
->_property
._ShortStandaloneQuarterSymbols
);
1187 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_STANDALONE_SHORT_QUARTERS
, 0);
1188 } else if (kCFDateFormatterAMSymbolKey
== key
) {
1189 if (formatter
->_property
._AMSymbol
) return CFRetain(formatter
->_property
._AMSymbol
);
1190 CFIndex cnt
= udat_countSymbols(formatter
->_df
, UDAT_AM_PMS
);
1192 CFIndex ucnt
= udat_getSymbols(formatter
->_df
, UDAT_AM_PMS
, 0, ubuffer
, BUFFER_SIZE
, &status
);
1193 if (U_SUCCESS(status
) && cnt
<= BUFFER_SIZE
) {
1194 return CFStringCreateWithCharacters(CFGetAllocator(formatter
), (UniChar
*)ubuffer
, ucnt
);
1197 } else if (kCFDateFormatterPMSymbolKey
== key
) {
1198 if (formatter
->_property
._PMSymbol
) return CFRetain(formatter
->_property
._PMSymbol
);
1199 CFIndex cnt
= udat_countSymbols(formatter
->_df
, UDAT_AM_PMS
);
1201 CFIndex ucnt
= udat_getSymbols(formatter
->_df
, UDAT_AM_PMS
, 1, ubuffer
, BUFFER_SIZE
, &status
);
1202 if (U_SUCCESS(status
) && cnt
<= BUFFER_SIZE
) {
1203 return CFStringCreateWithCharacters(CFGetAllocator(formatter
), (UniChar
*)ubuffer
, ucnt
);
1207 CFAssert3(0, __kCFLogAssertion
, "%s(): unknown key %p (%@)", __PRETTY_FUNCTION__
, key
, key
);