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@
24 Copyright (c) 2002-2009, Apple Inc. All rights reserved.
25 Responsibility: Christopher Kane
28 #include <CoreFoundation/CFDateFormatter.h>
29 #include <CoreFoundation/CFDate.h>
30 #include <CoreFoundation/CFTimeZone.h>
31 #include <CoreFoundation/CFCalendar.h>
32 #include <CoreFoundation/CFNumber.h>
33 #include "CFInternal.h"
34 #include "CFLocaleInternal.h"
35 #include <unicode/udat.h>
36 #include <unicode/udatpg.h>
40 extern UCalendar
*__CFCalendarCreateUCalendar(CFStringRef calendarID
, CFStringRef localeID
, CFTimeZoneRef tz
);
41 static void __CFDateFormatterCustomize(CFDateFormatterRef formatter
);
43 CF_EXPORT
const CFStringRef kCFDateFormatterCalendarIdentifierKey
;
45 #undef CFReleaseIfNotNull
46 #define CFReleaseIfNotNull(X) if (X) CFRelease(X)
48 #define BUFFER_SIZE 768
50 CFStringRef
CFDateFormatterCreateDateFormatFromTemplate(CFAllocatorRef allocator
, CFStringRef tmplate
, CFOptionFlags options
, CFLocaleRef locale
) {
51 if (allocator
) __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
52 if (locale
) __CFGenericValidateType(locale
, CFLocaleGetTypeID());
53 __CFGenericValidateType(tmplate
, CFStringGetTypeID());
55 CFStringRef localeName
= locale
? CFLocaleGetIdentifier(locale
) : CFSTR("");
56 char buffer
[BUFFER_SIZE
];
57 const char *cstr
= CFStringGetCStringPtr(localeName
, kCFStringEncodingASCII
);
59 if (CFStringGetCString(localeName
, buffer
, BUFFER_SIZE
, kCFStringEncodingASCII
)) cstr
= buffer
;
65 UErrorCode status
= U_ZERO_ERROR
;
66 UDateTimePatternGenerator
*ptg
= udatpg_open(cstr
, &status
);
67 if (NULL
== ptg
|| U_FAILURE(status
)) {
71 CFIndex jCount
= 0; // the only interesting cases are 0, 1, and 2 (adjacent)
72 CFRange r
= CFStringFind(tmplate
, CFSTR("j"), 0);
73 if (kCFNotFound
!= r
.location
) {
75 if ((r
.location
+ 1 < CFStringGetLength(tmplate
)) && ('j' == CFStringGetCharacterAtIndex(tmplate
, r
.location
+ 1))) {
80 UChar pattern
[BUFFER_SIZE
], skel
[BUFFER_SIZE
], bpat
[BUFFER_SIZE
];
81 CFIndex cnt
= CFStringGetLength(tmplate
);
82 if (BUFFER_SIZE
< cnt
) cnt
= BUFFER_SIZE
;
83 CFStringGetCharacters(tmplate
, CFRangeMake(0, cnt
), (UniChar
*)pattern
);
86 status
= U_ZERO_ERROR
;
87 int32_t skellen
= udatpg_getSkeleton(ptg
, pattern
, patlen
, skel
, sizeof(skel
) / sizeof(skel
[0]), &status
);
88 if (U_FAILURE(status
)) {
92 if ((0 < jCount
) && (skellen
+ jCount
< (sizeof(skel
) / sizeof(skel
[0])))) {
93 skel
[skellen
++] = 'j';
94 if (1 < jCount
) skel
[skellen
++] = 'j';
97 status
= U_ZERO_ERROR
;
98 int32_t bpatlen
= udatpg_getBestPattern(ptg
, skel
, skellen
, bpat
, sizeof(bpat
) / sizeof(bpat
[0]), &status
);
99 if (U_FAILURE(status
)) {
104 return CFStringCreateWithCharacters(allocator
, (const UniChar
*)bpat
, bpatlen
);
107 struct __CFDateFormatter
{
111 CFDateFormatterStyle _timeStyle
;
112 CFDateFormatterStyle _dateStyle
;
114 CFStringRef _defformat
;
116 CFBooleanRef _IsLenient
;
117 CFBooleanRef _DoesRelativeDateFormatting
;
118 CFBooleanRef _HasCustomFormat
;
119 CFTimeZoneRef _TimeZone
;
120 CFCalendarRef _Calendar
;
121 CFStringRef _CalendarName
;
122 CFDateRef _TwoDigitStartDate
;
123 CFDateRef _DefaultDate
;
124 CFDateRef _GregorianStartDate
;
125 CFArrayRef _EraSymbols
;
126 CFArrayRef _LongEraSymbols
;
127 CFArrayRef _MonthSymbols
;
128 CFArrayRef _ShortMonthSymbols
;
129 CFArrayRef _VeryShortMonthSymbols
;
130 CFArrayRef _StandaloneMonthSymbols
;
131 CFArrayRef _ShortStandaloneMonthSymbols
;
132 CFArrayRef _VeryShortStandaloneMonthSymbols
;
133 CFArrayRef _WeekdaySymbols
;
134 CFArrayRef _ShortWeekdaySymbols
;
135 CFArrayRef _VeryShortWeekdaySymbols
;
136 CFArrayRef _StandaloneWeekdaySymbols
;
137 CFArrayRef _ShortStandaloneWeekdaySymbols
;
138 CFArrayRef _VeryShortStandaloneWeekdaySymbols
;
139 CFArrayRef _QuarterSymbols
;
140 CFArrayRef _ShortQuarterSymbols
;
141 CFArrayRef _StandaloneQuarterSymbols
;
142 CFArrayRef _ShortStandaloneQuarterSymbols
;
143 CFStringRef _AMSymbol
;
144 CFStringRef _PMSymbol
;
148 static CFStringRef
__CFDateFormatterCopyDescription(CFTypeRef cf
) {
149 CFDateFormatterRef formatter
= (CFDateFormatterRef
)cf
;
150 return CFStringCreateWithFormat(CFGetAllocator(formatter
), NULL
, CFSTR("<CFDateFormatter %p [%p]>"), cf
, CFGetAllocator(formatter
));
153 static void __CFDateFormatterDeallocate(CFTypeRef cf
) {
154 CFDateFormatterRef formatter
= (CFDateFormatterRef
)cf
;
155 if (formatter
->_df
) udat_close(formatter
->_df
);
156 if (formatter
->_locale
) CFRelease(formatter
->_locale
);
157 if (formatter
->_format
) CFRelease(formatter
->_format
);
158 if (formatter
->_defformat
) CFRelease(formatter
->_defformat
);
159 CFReleaseIfNotNull(formatter
->_property
._IsLenient
);
160 CFReleaseIfNotNull(formatter
->_property
._DoesRelativeDateFormatting
);
161 CFReleaseIfNotNull(formatter
->_property
._TimeZone
);
162 CFReleaseIfNotNull(formatter
->_property
._Calendar
);
163 CFReleaseIfNotNull(formatter
->_property
._CalendarName
);
164 CFReleaseIfNotNull(formatter
->_property
._TwoDigitStartDate
);
165 CFReleaseIfNotNull(formatter
->_property
._DefaultDate
);
166 CFReleaseIfNotNull(formatter
->_property
._GregorianStartDate
);
167 CFReleaseIfNotNull(formatter
->_property
._EraSymbols
);
168 CFReleaseIfNotNull(formatter
->_property
._LongEraSymbols
);
169 CFReleaseIfNotNull(formatter
->_property
._MonthSymbols
);
170 CFReleaseIfNotNull(formatter
->_property
._ShortMonthSymbols
);
171 CFReleaseIfNotNull(formatter
->_property
._VeryShortMonthSymbols
);
172 CFReleaseIfNotNull(formatter
->_property
._StandaloneMonthSymbols
);
173 CFReleaseIfNotNull(formatter
->_property
._ShortStandaloneMonthSymbols
);
174 CFReleaseIfNotNull(formatter
->_property
._VeryShortStandaloneMonthSymbols
);
175 CFReleaseIfNotNull(formatter
->_property
._WeekdaySymbols
);
176 CFReleaseIfNotNull(formatter
->_property
._ShortWeekdaySymbols
);
177 CFReleaseIfNotNull(formatter
->_property
._VeryShortWeekdaySymbols
);
178 CFReleaseIfNotNull(formatter
->_property
._StandaloneWeekdaySymbols
);
179 CFReleaseIfNotNull(formatter
->_property
._ShortStandaloneWeekdaySymbols
);
180 CFReleaseIfNotNull(formatter
->_property
._VeryShortStandaloneWeekdaySymbols
);
181 CFReleaseIfNotNull(formatter
->_property
._QuarterSymbols
);
182 CFReleaseIfNotNull(formatter
->_property
._ShortQuarterSymbols
);
183 CFReleaseIfNotNull(formatter
->_property
._StandaloneQuarterSymbols
);
184 CFReleaseIfNotNull(formatter
->_property
._ShortStandaloneQuarterSymbols
);
185 CFReleaseIfNotNull(formatter
->_property
._AMSymbol
);
186 CFReleaseIfNotNull(formatter
->_property
._PMSymbol
);
189 static CFStringRef
__CFDateFormatterCreateForcedString(CFDateFormatterRef formatter
, CFStringRef inString
);
191 static void __CFDateFormatterSetProperty(CFDateFormatterRef formatter
, CFStringRef key
, CFTypeRef value
, Boolean directToICU
);
193 #define RESET_PROPERTY(C, K) \
194 if (df->_property. C) __CFDateFormatterSetProperty(df, K, df->_property. C, true);
196 static void __ResetUDateFormat(CFDateFormatterRef df
, Boolean goingToHaveCustomFormat
) {
197 if (df
->_df
) udat_close(df
->_df
);
200 // uses _timeStyle, _dateStyle, _locale, _property._TimeZone; sets _df, _format, _defformat
201 char loc_buffer
[BUFFER_SIZE
];
203 CFStringRef tmpLocName
= df
->_locale
? CFLocaleGetIdentifier(df
->_locale
) : CFSTR("");
204 CFStringGetCString(tmpLocName
, loc_buffer
, BUFFER_SIZE
, kCFStringEncodingASCII
);
206 UChar tz_buffer
[BUFFER_SIZE
];
208 CFStringRef tmpTZName
= df
->_property
._TimeZone
? CFTimeZoneGetName(df
->_property
._TimeZone
) : CFSTR("GMT");
209 CFStringGetCharacters(tmpTZName
, CFRangeMake(0, CFStringGetLength(tmpTZName
)), (UniChar
*)tz_buffer
);
211 df
->_property
._HasCustomFormat
= kCFBooleanFalse
;
213 int32_t udstyle
= 0, utstyle
= 0;
214 switch (df
->_dateStyle
) {
215 case kCFDateFormatterNoStyle
: udstyle
= UDAT_NONE
; break;
216 case kCFDateFormatterShortStyle
: udstyle
= UDAT_SHORT
; break;
217 case kCFDateFormatterMediumStyle
: udstyle
= UDAT_MEDIUM
; break;
218 case kCFDateFormatterLongStyle
: udstyle
= UDAT_LONG
; break;
219 case kCFDateFormatterFullStyle
: udstyle
= UDAT_FULL
; break;
221 switch (df
->_timeStyle
) {
222 case kCFDateFormatterNoStyle
: utstyle
= UDAT_NONE
; break;
223 case kCFDateFormatterShortStyle
: utstyle
= UDAT_SHORT
; break;
224 case kCFDateFormatterMediumStyle
: utstyle
= UDAT_MEDIUM
; break;
225 case kCFDateFormatterLongStyle
: utstyle
= UDAT_LONG
; break;
226 case kCFDateFormatterFullStyle
: utstyle
= UDAT_FULL
; break;
228 Boolean wantRelative
= (NULL
!= df
->_property
._DoesRelativeDateFormatting
&& df
->_property
._DoesRelativeDateFormatting
== kCFBooleanTrue
);
229 Boolean hasFormat
= (NULL
!= df
->_property
._HasCustomFormat
&& df
->_property
._HasCustomFormat
== kCFBooleanTrue
) || goingToHaveCustomFormat
;
230 if (wantRelative
&& !hasFormat
) {
231 udstyle
|= UDAT_RELATIVE
;
234 UErrorCode status
= U_ZERO_ERROR
;
235 UDateFormat
*icudf
= udat_open((UDateFormatStyle
)utstyle
, (UDateFormatStyle
)udstyle
, loc_buffer
, tz_buffer
, CFStringGetLength(tmpTZName
), NULL
, 0, &status
);
236 if (NULL
== icudf
|| U_FAILURE(status
)) {
239 udat_setLenient(icudf
, 0);
240 if (kCFDateFormatterNoStyle
== df
->_dateStyle
&& kCFDateFormatterNoStyle
== df
->_timeStyle
) {
241 udat_applyPattern(icudf
, false, NULL
, 0);
243 CFStringRef calident
= (CFStringRef
)CFLocaleGetValue(df
->_locale
, kCFLocaleCalendarIdentifierKey
);
244 if (calident
&& CFEqual(calident
, kCFCalendarIdentifierGregorian
)) {
245 status
= U_ZERO_ERROR
;
246 udat_set2DigitYearStart(icudf
, -631152000000.0, &status
); // 1950-01-01 00:00:00 GMT
250 __CFDateFormatterCustomize(df
);
252 UChar ubuffer
[BUFFER_SIZE
];
253 status
= U_ZERO_ERROR
;
254 int32_t ret
= udat_toPattern(icudf
, false, ubuffer
, BUFFER_SIZE
, &status
);
255 if (U_SUCCESS(status
) && ret
<= BUFFER_SIZE
) {
256 CFStringRef newFormat
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (const UniChar
*)ubuffer
, ret
);
257 CFStringRef formatString
= __CFDateFormatterCreateForcedString(df
, newFormat
);
258 CFIndex cnt
= CFStringGetLength(formatString
);
259 CFAssert1(cnt
<= 1024, __kCFLogAssertion
, "%s(): format string too long", __PRETTY_FUNCTION__
);
260 if (df
->_format
!= formatString
&& cnt
<= 1024) {
261 STACK_BUFFER_DECL(UChar
, ubuffer
, cnt
);
262 const UChar
*ustr
= (UChar
*)CFStringGetCharactersPtr((CFStringRef
)formatString
);
264 CFStringGetCharacters(formatString
, CFRangeMake(0, cnt
), (UniChar
*)ubuffer
);
267 UErrorCode status
= U_ZERO_ERROR
;
268 // udat_applyPattern(df->_df, false, ustr, cnt, &status);
269 udat_applyPattern(df
->_df
, false, ustr
, cnt
);
270 if (U_SUCCESS(status
)) {
271 if (df
->_format
) CFRelease(df
->_format
);
272 df
->_format
= (CFStringRef
)CFStringCreateCopy(CFGetAllocator(df
), formatString
);
275 CFRelease(formatString
);
276 CFRelease(newFormat
);
278 if (df
->_defformat
) CFRelease(df
->_defformat
);
279 df
->_defformat
= df
->_format
? (CFStringRef
)CFRetain(df
->_format
) : NULL
;
281 RESET_PROPERTY(_IsLenient
, kCFDateFormatterIsLenientKey
);
282 RESET_PROPERTY(_DoesRelativeDateFormatting
, kCFDateFormatterDoesRelativeDateFormattingKey
);
283 RESET_PROPERTY(_Calendar
, kCFDateFormatterCalendarKey
);
284 RESET_PROPERTY(_CalendarName
, kCFDateFormatterCalendarIdentifierKey
);
285 RESET_PROPERTY(_TimeZone
, kCFDateFormatterTimeZoneKey
);
286 RESET_PROPERTY(_TwoDigitStartDate
, kCFDateFormatterTwoDigitStartDateKey
);
287 RESET_PROPERTY(_DefaultDate
, kCFDateFormatterDefaultDateKey
);
288 RESET_PROPERTY(_GregorianStartDate
, kCFDateFormatterGregorianStartDateKey
);
289 RESET_PROPERTY(_EraSymbols
, kCFDateFormatterEraSymbolsKey
);
290 RESET_PROPERTY(_LongEraSymbols
, kCFDateFormatterLongEraSymbolsKey
);
291 RESET_PROPERTY(_MonthSymbols
, kCFDateFormatterMonthSymbolsKey
);
292 RESET_PROPERTY(_ShortMonthSymbols
, kCFDateFormatterShortMonthSymbolsKey
);
293 RESET_PROPERTY(_VeryShortMonthSymbols
, kCFDateFormatterVeryShortMonthSymbolsKey
);
294 RESET_PROPERTY(_StandaloneMonthSymbols
, kCFDateFormatterStandaloneMonthSymbolsKey
);
295 RESET_PROPERTY(_ShortStandaloneMonthSymbols
, kCFDateFormatterShortStandaloneMonthSymbolsKey
);
296 RESET_PROPERTY(_VeryShortStandaloneMonthSymbols
, kCFDateFormatterVeryShortStandaloneMonthSymbolsKey
);
297 RESET_PROPERTY(_WeekdaySymbols
, kCFDateFormatterWeekdaySymbolsKey
);
298 RESET_PROPERTY(_ShortWeekdaySymbols
, kCFDateFormatterShortWeekdaySymbolsKey
);
299 RESET_PROPERTY(_VeryShortWeekdaySymbols
, kCFDateFormatterVeryShortWeekdaySymbolsKey
);
300 RESET_PROPERTY(_StandaloneWeekdaySymbols
, kCFDateFormatterStandaloneWeekdaySymbolsKey
);
301 RESET_PROPERTY(_ShortStandaloneWeekdaySymbols
, kCFDateFormatterShortStandaloneWeekdaySymbolsKey
);
302 RESET_PROPERTY(_VeryShortStandaloneWeekdaySymbols
, kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey
);
303 RESET_PROPERTY(_QuarterSymbols
, kCFDateFormatterQuarterSymbolsKey
);
304 RESET_PROPERTY(_ShortQuarterSymbols
, kCFDateFormatterShortQuarterSymbolsKey
);
305 RESET_PROPERTY(_StandaloneQuarterSymbols
, kCFDateFormatterStandaloneQuarterSymbolsKey
);
306 RESET_PROPERTY(_ShortStandaloneQuarterSymbols
, kCFDateFormatterShortStandaloneQuarterSymbolsKey
);
307 RESET_PROPERTY(_AMSymbol
, kCFDateFormatterAMSymbolKey
);
308 RESET_PROPERTY(_PMSymbol
, kCFDateFormatterPMSymbolKey
);
311 static CFTypeID __kCFDateFormatterTypeID
= _kCFRuntimeNotATypeID
;
313 static const CFRuntimeClass __CFDateFormatterClass
= {
318 __CFDateFormatterDeallocate
,
322 __CFDateFormatterCopyDescription
325 static void __CFDateFormatterInitialize(void) {
326 __kCFDateFormatterTypeID
= _CFRuntimeRegisterClass(&__CFDateFormatterClass
);
329 CFTypeID
CFDateFormatterGetTypeID(void) {
330 if (_kCFRuntimeNotATypeID
== __kCFDateFormatterTypeID
) __CFDateFormatterInitialize();
331 return __kCFDateFormatterTypeID
;
334 CFDateFormatterRef
CFDateFormatterCreate(CFAllocatorRef allocator
, CFLocaleRef locale
, CFDateFormatterStyle dateStyle
, CFDateFormatterStyle timeStyle
) {
335 struct __CFDateFormatter
*memory
;
336 uint32_t size
= sizeof(struct __CFDateFormatter
) - sizeof(CFRuntimeBase
);
337 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
338 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
339 if (locale
) __CFGenericValidateType(locale
, CFLocaleGetTypeID());
340 memory
= (struct __CFDateFormatter
*)_CFRuntimeCreateInstance(allocator
, CFDateFormatterGetTypeID(), size
, NULL
);
341 if (NULL
== memory
) {
345 memory
->_locale
= NULL
;
346 memory
->_format
= NULL
;
347 memory
->_defformat
= NULL
;
348 memory
->_dateStyle
= dateStyle
;
349 memory
->_timeStyle
= timeStyle
;
350 memory
->_property
._IsLenient
= NULL
;
351 memory
->_property
._DoesRelativeDateFormatting
= NULL
;
352 memory
->_property
._HasCustomFormat
= NULL
;
353 memory
->_property
._TimeZone
= NULL
;
354 memory
->_property
._Calendar
= NULL
;
355 memory
->_property
._CalendarName
= NULL
;
356 memory
->_property
._TwoDigitStartDate
= NULL
;
357 memory
->_property
._DefaultDate
= NULL
;
358 memory
->_property
._GregorianStartDate
= NULL
;
359 memory
->_property
._EraSymbols
= NULL
;
360 memory
->_property
._LongEraSymbols
= NULL
;
361 memory
->_property
._MonthSymbols
= NULL
;
362 memory
->_property
._ShortMonthSymbols
= NULL
;
363 memory
->_property
._VeryShortMonthSymbols
= NULL
;
364 memory
->_property
._StandaloneMonthSymbols
= NULL
;
365 memory
->_property
._ShortStandaloneMonthSymbols
= NULL
;
366 memory
->_property
._VeryShortStandaloneMonthSymbols
= NULL
;
367 memory
->_property
._WeekdaySymbols
= NULL
;
368 memory
->_property
._ShortWeekdaySymbols
= NULL
;
369 memory
->_property
._VeryShortWeekdaySymbols
= NULL
;
370 memory
->_property
._StandaloneWeekdaySymbols
= NULL
;
371 memory
->_property
._ShortStandaloneWeekdaySymbols
= NULL
;
372 memory
->_property
._VeryShortStandaloneWeekdaySymbols
= NULL
;
373 memory
->_property
._QuarterSymbols
= NULL
;
374 memory
->_property
._ShortQuarterSymbols
= NULL
;
375 memory
->_property
._StandaloneQuarterSymbols
= NULL
;
376 memory
->_property
._ShortStandaloneQuarterSymbols
= NULL
;
377 memory
->_property
._AMSymbol
= NULL
;
378 memory
->_property
._PMSymbol
= NULL
;
381 case kCFDateFormatterNoStyle
:
382 case kCFDateFormatterShortStyle
:
383 case kCFDateFormatterMediumStyle
:
384 case kCFDateFormatterLongStyle
:
385 case kCFDateFormatterFullStyle
: break;
387 CFAssert2(0, __kCFLogAssertion
, "%s(): unknown date style %d", __PRETTY_FUNCTION__
, dateStyle
);
388 memory
->_dateStyle
= kCFDateFormatterMediumStyle
;
392 case kCFDateFormatterNoStyle
:
393 case kCFDateFormatterShortStyle
:
394 case kCFDateFormatterMediumStyle
:
395 case kCFDateFormatterLongStyle
:
396 case kCFDateFormatterFullStyle
: break;
398 CFAssert2(0, __kCFLogAssertion
, "%s(): unknown time style %d", __PRETTY_FUNCTION__
, timeStyle
);
399 memory
->_timeStyle
= kCFDateFormatterMediumStyle
;
403 memory
->_locale
= locale
? CFLocaleCreateCopy(allocator
, locale
) : (CFLocaleRef
)CFRetain(CFLocaleGetSystem());
404 memory
->_property
._TimeZone
= CFTimeZoneCopyDefault();
405 __ResetUDateFormat(memory
, false);
410 return (CFDateFormatterRef
)memory
;
413 extern CFDictionaryRef
__CFLocaleGetPrefs(CFLocaleRef locale
);
415 static void __substituteFormatStringFromPrefsDFRelative(CFDateFormatterRef formatter
) {
416 CFDictionaryRef prefs
= __CFLocaleGetPrefs(formatter
->_locale
);
418 CFIndex dateLen
= -1;
419 UChar dateBuffer
[BUFFER_SIZE
];
420 if (kCFDateFormatterNoStyle
!= formatter
->_dateStyle
) {
421 CFPropertyListRef metapref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleICUDateFormatStrings")) : NULL
;
422 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFDictionaryGetTypeID()) {
424 switch (formatter
->_dateStyle
) {
425 case kCFDateFormatterShortStyle
: key
= CFSTR("1"); break;
426 case kCFDateFormatterMediumStyle
: key
= CFSTR("2"); break;
427 case kCFDateFormatterLongStyle
: key
= CFSTR("3"); break;
428 case kCFDateFormatterFullStyle
: key
= CFSTR("4"); break;
429 default: key
= CFSTR("0"); break;
431 CFStringRef pref
= (CFStringRef
)CFDictionaryGetValue((CFDictionaryRef
)metapref
, key
);
432 if (NULL
!= pref
&& CFGetTypeID(pref
) == CFStringGetTypeID()) {
433 dateLen
= __CFMin(CFStringGetLength(pref
), BUFFER_SIZE
);
434 CFStringGetCharacters(pref
, CFRangeMake(0, dateLen
), (UniChar
*)dateBuffer
);
439 UErrorCode status
= U_ZERO_ERROR
;
440 int32_t ret
= udat_toPatternRelativeDate(formatter
->_df
, dateBuffer
, BUFFER_SIZE
, &status
);
441 if (!U_FAILURE(status
)) {
446 CFIndex timeLen
= -1;
447 UChar timeBuffer
[BUFFER_SIZE
];
448 if (kCFDateFormatterNoStyle
!= formatter
->_timeStyle
) {
449 CFPropertyListRef metapref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleICUTimeFormatStrings")) : NULL
;
450 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFDictionaryGetTypeID()) {
452 switch (formatter
->_timeStyle
) {
453 case kCFDateFormatterShortStyle
: key
= CFSTR("1"); break;
454 case kCFDateFormatterMediumStyle
: key
= CFSTR("2"); break;
455 case kCFDateFormatterLongStyle
: key
= CFSTR("3"); break;
456 case kCFDateFormatterFullStyle
: key
= CFSTR("4"); break;
457 default: key
= CFSTR("0"); break;
459 CFStringRef pref
= (CFStringRef
)CFDictionaryGetValue((CFDictionaryRef
)metapref
, key
);
460 if (NULL
!= pref
&& CFGetTypeID(pref
) == CFStringGetTypeID()) {
461 timeLen
= __CFMin(CFStringGetLength(pref
), BUFFER_SIZE
);
462 CFStringGetCharacters(pref
, CFRangeMake(0, timeLen
), (UniChar
*)timeBuffer
);
467 UErrorCode status
= U_ZERO_ERROR
;
468 int32_t ret
= udat_toPatternRelativeTime(formatter
->_df
, timeBuffer
, BUFFER_SIZE
, &status
);
469 if (!U_FAILURE(status
)) {
474 UErrorCode status
= U_ZERO_ERROR
;
475 udat_applyPatternRelative(formatter
->_df
, (0 <= dateLen
) ? dateBuffer
: NULL
, (0 <= dateLen
) ? dateLen
: 0, (0 <= timeLen
) ? timeBuffer
: NULL
, (0 <= timeLen
) ? timeLen
: 0, &status
);
478 static void __substituteFormatStringFromPrefsDF(CFDateFormatterRef formatter
, bool doTime
) {
479 CFIndex formatStyle
= doTime
? formatter
->_timeStyle
: formatter
->_dateStyle
;
480 CFStringRef prefName
= doTime
? CFSTR("AppleICUTimeFormatStrings") : CFSTR("AppleICUDateFormatStrings");
481 if (kCFDateFormatterNoStyle
!= formatStyle
) {
482 CFStringRef pref
= NULL
;
483 CFDictionaryRef prefs
= __CFLocaleGetPrefs(formatter
->_locale
);
484 CFPropertyListRef metapref
= prefs
? CFDictionaryGetValue(prefs
, prefName
) : NULL
;
485 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFDictionaryGetTypeID()) {
487 switch (formatStyle
) {
488 case kCFDateFormatterShortStyle
: key
= CFSTR("1"); break;
489 case kCFDateFormatterMediumStyle
: key
= CFSTR("2"); break;
490 case kCFDateFormatterLongStyle
: key
= CFSTR("3"); break;
491 case kCFDateFormatterFullStyle
: key
= CFSTR("4"); break;
492 default: key
= CFSTR("0"); break;
494 pref
= (CFStringRef
)CFDictionaryGetValue((CFDictionaryRef
)metapref
, key
);
496 if (NULL
!= pref
&& CFGetTypeID(pref
) == CFStringGetTypeID()) {
497 int32_t icustyle
= UDAT_NONE
;
498 switch (formatStyle
) {
499 case kCFDateFormatterShortStyle
: icustyle
= UDAT_SHORT
; break;
500 case kCFDateFormatterMediumStyle
: icustyle
= UDAT_MEDIUM
; break;
501 case kCFDateFormatterLongStyle
: icustyle
= UDAT_LONG
; break;
502 case kCFDateFormatterFullStyle
: icustyle
= UDAT_FULL
; break;
504 CFStringRef localeName
= CFLocaleGetIdentifier(formatter
->_locale
);
505 char buffer
[BUFFER_SIZE
];
506 const char *cstr
= CFStringGetCStringPtr(localeName
, kCFStringEncodingASCII
);
508 if (CFStringGetCString(localeName
, buffer
, BUFFER_SIZE
, kCFStringEncodingASCII
)) cstr
= buffer
;
510 UErrorCode status
= U_ZERO_ERROR
;
511 UDateFormat
*df
= udat_open((UDateFormatStyle
)(doTime
? icustyle
: UDAT_NONE
), (UDateFormatStyle
)(doTime
? UDAT_NONE
: icustyle
), cstr
, NULL
, 0, NULL
, 0, &status
);
513 UChar ubuffer
[BUFFER_SIZE
];
514 status
= U_ZERO_ERROR
;
515 int32_t date_len
= udat_toPattern(df
, false, ubuffer
, BUFFER_SIZE
, &status
);
516 if (U_SUCCESS(status
) && date_len
<= BUFFER_SIZE
) {
517 CFStringRef dateString
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (UniChar
*)ubuffer
, date_len
);
518 status
= U_ZERO_ERROR
;
519 int32_t formatter_len
= udat_toPattern(formatter
->_df
, false, ubuffer
, BUFFER_SIZE
, &status
);
520 if (U_SUCCESS(status
) && formatter_len
<= BUFFER_SIZE
) {
521 CFMutableStringRef formatString
= CFStringCreateMutable(kCFAllocatorSystemDefault
, 0);
522 CFStringAppendCharacters(formatString
, (UniChar
*)ubuffer
, formatter_len
);
523 // find dateString inside formatString, substitute the pref in that range
525 if (CFStringFindWithOptions(formatString
, dateString
, CFRangeMake(0, formatter_len
), 0, &result
)) {
526 CFStringReplace(formatString
, result
, pref
);
527 int32_t new_len
= CFStringGetLength(formatString
);
528 STACK_BUFFER_DECL(UChar
, new_buffer
, new_len
);
529 const UChar
*new_ustr
= (UChar
*)CFStringGetCharactersPtr(formatString
);
530 if (NULL
== new_ustr
) {
531 CFStringGetCharacters(formatString
, CFRangeMake(0, new_len
), (UniChar
*)new_buffer
);
532 new_ustr
= new_buffer
;
534 status
= U_ZERO_ERROR
;
535 // udat_applyPattern(formatter->_df, false, new_ustr, new_len, &status);
536 udat_applyPattern(formatter
->_df
, false, new_ustr
, new_len
);
538 CFRelease(formatString
);
540 CFRelease(dateString
);
548 static void __CFDateFormatterApplySymbolPrefs(const void *key
, const void *value
, void *context
) {
549 if (CFGetTypeID(key
) == CFStringGetTypeID() && CFGetTypeID(value
) == CFArrayGetTypeID()) {
550 CFDateFormatterRef formatter
= (CFDateFormatterRef
)context
;
551 UDateFormatSymbolType sym
= (UDateFormatSymbolType
)CFStringGetIntValue((CFStringRef
)key
);
552 CFArrayRef array
= (CFArrayRef
)value
;
553 CFIndex idx
, cnt
= CFArrayGetCount(array
);
554 for (idx
= 0; idx
< cnt
; idx
++) {
555 CFStringRef item
= (CFStringRef
)CFArrayGetValueAtIndex(array
, idx
);
556 if (CFGetTypeID(item
) != CFStringGetTypeID()) continue;
557 CFIndex item_cnt
= CFStringGetLength(item
);
558 STACK_BUFFER_DECL(UChar
, item_buffer
, __CFMin(BUFFER_SIZE
, item_cnt
));
559 UChar
*item_ustr
= (UChar
*)CFStringGetCharactersPtr(item
);
560 if (NULL
== item_ustr
) {
561 item_cnt
= __CFMin(BUFFER_SIZE
, item_cnt
);
562 CFStringGetCharacters(item
, CFRangeMake(0, item_cnt
), (UniChar
*)item_buffer
);
563 item_ustr
= item_buffer
;
565 UErrorCode status
= U_ZERO_ERROR
;
566 udat_setSymbols(formatter
->_df
, sym
, idx
, item_ustr
, item_cnt
, &status
);
571 static CFStringRef
__CFDateFormatterCreateForcedString(CFDateFormatterRef formatter
, CFStringRef inString
) {
572 if (!inString
) return NULL
;
573 Boolean doForce24
= false, doForce12
= false;
574 CFDictionaryRef prefs
= __CFLocaleGetPrefs(formatter
->_locale
);
575 CFPropertyListRef pref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleICUForce24HourTime")) : NULL
;
576 if (NULL
!= pref
&& CFGetTypeID(pref
) == CFBooleanGetTypeID()) {
577 doForce24
= CFBooleanGetValue((CFBooleanRef
)pref
);
579 pref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleICUForce12HourTime")) : NULL
;
580 if (NULL
!= pref
&& CFGetTypeID(pref
) == CFBooleanGetTypeID()) {
581 doForce12
= CFBooleanGetValue((CFBooleanRef
)pref
);
583 if (!doForce24
&& !doForce12
) return (CFStringRef
)CFRetain(inString
);
584 if (doForce24
) doForce12
= false; // if both are set, Force24 wins, period
585 CFMutableStringRef outString
= CFStringCreateMutable(kCFAllocatorSystemDefault
, 0);
586 CFIndex cnt
= CFStringGetLength(inString
);
587 CFIndex lastSecond
= -1, lastMinute
= -1, firstHour
= -1;
588 Boolean isInQuote
= false, hasA
= false, had12Hour
= false, had24Hour
= false;
589 for (CFIndex idx
= 0; idx
< cnt
; idx
++) {
591 UniChar ch
= CFStringGetCharacterAtIndex(inString
, idx
);
593 case '\'': isInQuote
= !isInQuote
; break;
594 case 'h': if (!isInQuote
) {if (-1 == firstHour
) firstHour
= CFStringGetLength(outString
); had12Hour
= true; if (doForce24
) ch
= 'H';} break; // switch 12-hour to 24-hour
595 case 'K': if (!isInQuote
) {if (-1 == firstHour
) firstHour
= CFStringGetLength(outString
); had12Hour
= true; if (doForce24
) ch
= 'k';} break; // switch 12-hour to 24-hour
596 case 'H': if (!isInQuote
) {if (-1 == firstHour
) firstHour
= CFStringGetLength(outString
); had24Hour
= true; if (doForce12
) ch
= 'h';} break; // switch 24-hour to 12-hour
597 case 'k': if (!isInQuote
) {if (-1 == firstHour
) firstHour
= CFStringGetLength(outString
); had24Hour
= true; if (doForce12
) ch
= 'K';} break; // switch 24-hour to 12-hour
598 case 'm': if (!isInQuote
) lastMinute
= CFStringGetLength(outString
); break;
599 case 's': if (!isInQuote
) lastSecond
= CFStringGetLength(outString
); break;
600 case 'a': if (!isInQuote
) hasA
= true;
601 if (!isInQuote
&& doForce24
) {
602 // skip 'a' and one optional trailing space
604 if (idx
+ 1 < cnt
&& ' ' == CFStringGetCharacterAtIndex(inString
, idx
+ 1)) idx
++;
608 if (!isInQuote
&& doForce24
) {
609 // if next character is 'a' AND we have seen the hour designator, skip space and 'a'
610 if (idx
+ 1 < cnt
&& 'a' == CFStringGetCharacterAtIndex(inString
, idx
+ 1) && -1 != firstHour
) {
617 if (emit
) CFStringAppendCharacters(outString
, &ch
, 1);
619 if (doForce12
&& !hasA
&& had24Hour
) {
620 CFStringRef locName
= CFLocaleGetIdentifier(formatter
->_locale
);
621 if (-1 != firstHour
&& (CFStringHasPrefix(locName
, CFSTR("ko")) || CFEqual(locName
, CFSTR("zh_SG")))) {
622 CFStringInsert(outString
, firstHour
, CFSTR("a "));
623 } else if (-1 != firstHour
&& (CFStringHasPrefix(locName
, CFSTR("zh")) || CFStringHasPrefix(locName
, CFSTR("ja")))) {
624 CFStringInsert(outString
, firstHour
, CFSTR("a"));
626 CFIndex lastPos
= (-1 != lastSecond
) ? lastSecond
: ((-1 != lastMinute
) ? lastMinute
: -1);
628 cnt
= CFStringGetLength(outString
);
630 UniChar ch
= (lastPos
< cnt
) ? CFStringGetCharacterAtIndex(outString
, lastPos
) : 0;
632 case '\"': lastPos
++; break;
637 ch
= (lastPos
< cnt
) ? CFStringGetCharacterAtIndex(outString
, lastPos
) : 0;
638 } while ('\'' != ch
&& '\0' != ch
);
639 if ('\'' == ch
) lastPos
++;
640 ch
= (lastPos
< cnt
) ? CFStringGetCharacterAtIndex(outString
, lastPos
) : 0;
641 if ('\'' == ch
) goto again
;
644 CFStringInsert(outString
, lastPos
, CFSTR(" a"));
651 static void __CFDateFormatterCustomize(CFDateFormatterRef formatter
) {
652 Boolean wantRelative
= (NULL
!= formatter
->_property
._DoesRelativeDateFormatting
&& formatter
->_property
._DoesRelativeDateFormatting
== kCFBooleanTrue
);
653 Boolean hasFormat
= (NULL
!= formatter
->_property
._HasCustomFormat
&& formatter
->_property
._HasCustomFormat
== kCFBooleanTrue
);
654 if (wantRelative
&& !hasFormat
) {
655 __substituteFormatStringFromPrefsDFRelative(formatter
);
657 __substituteFormatStringFromPrefsDF(formatter
, false);
658 __substituteFormatStringFromPrefsDF(formatter
, true);
660 CFDictionaryRef prefs
= __CFLocaleGetPrefs(formatter
->_locale
);
661 CFPropertyListRef metapref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleICUDateTimeSymbols")) : NULL
;
662 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFDictionaryGetTypeID()) {
663 CFDictionaryApplyFunction((CFDictionaryRef
)metapref
, __CFDateFormatterApplySymbolPrefs
, formatter
);
665 metapref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleFirstWeekday")) : NULL
;
666 CFStringRef calID
= (CFStringRef
)CFLocaleGetValue(formatter
->_locale
, kCFLocaleCalendarIdentifierKey
);
667 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFDictionaryGetTypeID()) {
668 metapref
= (CFNumberRef
)CFDictionaryGetValue((CFDictionaryRef
)metapref
, calID
);
670 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFNumberGetTypeID()) {
672 if (CFNumberGetValue((CFNumberRef
)metapref
, kCFNumberCFIndexType
, &wkdy
)) {
673 UCalendar
*cal
= (UCalendar
*)udat_getCalendar(formatter
->_df
);
674 if (cal
) ucal_setAttribute(cal
, UCAL_FIRST_DAY_OF_WEEK
, wkdy
);
677 metapref
= prefs
? CFDictionaryGetValue(prefs
, CFSTR("AppleMinDaysInFirstWeek")) : NULL
;
678 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFDictionaryGetTypeID()) {
679 metapref
= (CFNumberRef
)CFDictionaryGetValue((CFDictionaryRef
)metapref
, calID
);
681 if (NULL
!= metapref
&& CFGetTypeID(metapref
) == CFNumberGetTypeID()) {
683 if (CFNumberGetValue((CFNumberRef
)metapref
, kCFNumberCFIndexType
, &mwd
)) {
684 UCalendar
*cal
= (UCalendar
*)udat_getCalendar(formatter
->_df
);
685 if (cal
) ucal_setAttribute(cal
, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK
, mwd
);
690 CFLocaleRef
CFDateFormatterGetLocale(CFDateFormatterRef formatter
) {
691 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
692 return formatter
->_locale
;
695 CFDateFormatterStyle
CFDateFormatterGetDateStyle(CFDateFormatterRef formatter
) {
696 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
697 return formatter
->_dateStyle
;
700 CFDateFormatterStyle
CFDateFormatterGetTimeStyle(CFDateFormatterRef formatter
) {
701 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
702 return formatter
->_timeStyle
;
705 CFStringRef
CFDateFormatterGetFormat(CFDateFormatterRef formatter
) {
706 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
707 return formatter
->_format
;
710 void CFDateFormatterSetFormat(CFDateFormatterRef formatter
, CFStringRef formatString
) {
711 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
712 __CFGenericValidateType(formatString
, CFStringGetTypeID());
713 formatString
= __CFDateFormatterCreateForcedString(formatter
, formatString
);
714 CFIndex cnt
= CFStringGetLength(formatString
);
715 CFAssert1(cnt
<= 1024, __kCFLogAssertion
, "%s(): format string too long", __PRETTY_FUNCTION__
);
716 if (formatter
->_format
!= formatString
&& cnt
<= 1024) {
717 __ResetUDateFormat(formatter
, true);
718 STACK_BUFFER_DECL(UChar
, ubuffer
, cnt
);
719 const UChar
*ustr
= (UChar
*)CFStringGetCharactersPtr((CFStringRef
)formatString
);
721 CFStringGetCharacters(formatString
, CFRangeMake(0, cnt
), (UniChar
*)ubuffer
);
724 UErrorCode status
= U_ZERO_ERROR
;
725 // udat_applyPattern(formatter->_df, false, ustr, cnt, &status);
726 udat_applyPattern(formatter
->_df
, false, ustr
, cnt
);
727 if (U_SUCCESS(status
)) {
728 if (formatter
->_format
) CFRelease(formatter
->_format
);
729 formatter
->_format
= (CFStringRef
)CFStringCreateCopy(CFGetAllocator(formatter
), formatString
);
732 if (formatString
) CFRelease(formatString
);
735 CFStringRef
CFDateFormatterCreateStringWithDate(CFAllocatorRef allocator
, CFDateFormatterRef formatter
, CFDateRef date
) {
736 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
737 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
738 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
739 __CFGenericValidateType(date
, CFDateGetTypeID());
740 return CFDateFormatterCreateStringWithAbsoluteTime(allocator
, formatter
, CFDateGetAbsoluteTime(date
));
743 CFStringRef
CFDateFormatterCreateStringWithAbsoluteTime(CFAllocatorRef allocator
, CFDateFormatterRef formatter
, CFAbsoluteTime at
) {
744 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
745 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
746 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
747 UChar
*ustr
= NULL
, ubuffer
[BUFFER_SIZE
];
748 UErrorCode status
= U_ZERO_ERROR
;
749 CFIndex used
, cnt
= BUFFER_SIZE
;
750 UDate ud
= (at
+ kCFAbsoluteTimeIntervalSince1970
) * 1000.0 + 0.5;
751 used
= udat_format(formatter
->_df
, ud
, ubuffer
, cnt
, NULL
, &status
);
752 if (status
== U_BUFFER_OVERFLOW_ERROR
|| cnt
< used
) {
754 ustr
= (UChar
*)CFAllocatorAllocate(kCFAllocatorSystemDefault
, sizeof(UChar
) * cnt
, 0);
755 status
= U_ZERO_ERROR
;
756 used
= udat_format(formatter
->_df
, ud
, ustr
, cnt
, NULL
, &status
);
758 CFStringRef string
= NULL
;
759 if (U_SUCCESS(status
)) {
760 string
= CFStringCreateWithCharacters(allocator
, (const UniChar
*)(ustr
? ustr
: ubuffer
), used
);
762 if (ustr
) CFAllocatorDeallocate(kCFAllocatorSystemDefault
, ustr
);
766 CFDateRef
CFDateFormatterCreateDateFromString(CFAllocatorRef allocator
, CFDateFormatterRef formatter
, CFStringRef string
, CFRange
*rangep
) {
767 if (allocator
== NULL
) allocator
= __CFGetDefaultAllocator();
768 __CFGenericValidateType(allocator
, CFAllocatorGetTypeID());
769 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
770 __CFGenericValidateType(string
, CFStringGetTypeID());
772 if (CFDateFormatterGetAbsoluteTimeFromString(formatter
, string
, rangep
, &at
)) {
773 return CFDateCreate(allocator
, at
);
778 Boolean
CFDateFormatterGetAbsoluteTimeFromString(CFDateFormatterRef formatter
, CFStringRef string
, CFRange
*rangep
, CFAbsoluteTime
*atp
) {
779 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
780 __CFGenericValidateType(string
, CFStringGetTypeID());
781 CFRange range
= {0, 0};
785 range
.length
= CFStringGetLength(string
);
787 if (1024 < range
.length
) range
.length
= 1024;
788 const UChar
*ustr
= (UChar
*)CFStringGetCharactersPtr(string
);
789 STACK_BUFFER_DECL(UChar
, ubuffer
, (NULL
== ustr
) ? range
.length
: 1);
791 CFStringGetCharacters(string
, range
, (UniChar
*)ubuffer
);
794 ustr
+= range
.location
;
798 UErrorCode status
= U_ZERO_ERROR
;
799 if (formatter
->_property
._DefaultDate
) {
800 CFAbsoluteTime at
= CFDateGetAbsoluteTime(formatter
->_property
._DefaultDate
);
801 udate
= (at
+ kCFAbsoluteTimeIntervalSince1970
) * 1000.0;
802 UDateFormat
*df2
= udat_clone(formatter
->_df
, &status
);
803 UCalendar
*cal2
= (UCalendar
*)udat_getCalendar(df2
);
804 ucal_setMillis(cal2
, udate
, &status
);
805 udat_parseCalendar(formatter
->_df
, cal2
, ustr
, range
.length
, &dpos
, &status
);
806 udate
= ucal_getMillis(cal2
, &status
);
809 udate
= udat_parse(formatter
->_df
, ustr
, range
.length
, &dpos
, &status
);
811 if (rangep
) rangep
->length
= dpos
;
812 if (U_FAILURE(status
)) {
816 *atp
= (double)udate
/ 1000.0 - kCFAbsoluteTimeIntervalSince1970
;
821 static void __CFDateFormatterSetSymbolsArray(UDateFormat
*icudf
, int32_t icucode
, int index_base
, CFTypeRef value
) {
822 UErrorCode status
= U_ZERO_ERROR
;
823 __CFGenericValidateType(value
, CFArrayGetTypeID());
824 CFArrayRef array
= (CFArrayRef
)value
;
825 CFIndex idx
, cnt
= CFArrayGetCount(array
);
826 for (idx
= 0; idx
< cnt
; idx
++) {
827 CFStringRef item
= (CFStringRef
)CFArrayGetValueAtIndex(array
, idx
);
828 __CFGenericValidateType(item
, CFStringGetTypeID());
829 CFIndex item_cnt
= CFStringGetLength(item
);
830 STACK_BUFFER_DECL(UChar
, item_buffer
, __CFMin(BUFFER_SIZE
, item_cnt
));
831 UChar
*item_ustr
= (UChar
*)CFStringGetCharactersPtr(item
);
832 if (NULL
== item_ustr
) {
833 item_cnt
= __CFMin(BUFFER_SIZE
, item_cnt
);
834 CFStringGetCharacters(item
, CFRangeMake(0, item_cnt
), (UniChar
*)item_buffer
);
835 item_ustr
= item_buffer
;
837 status
= U_ZERO_ERROR
;
838 udat_setSymbols(icudf
, (UDateFormatSymbolType
)icucode
, idx
+ index_base
, item_ustr
, item_cnt
, &status
);
842 static CFArrayRef
__CFDateFormatterGetSymbolsArray(UDateFormat
*icudf
, int32_t icucode
, int index_base
) {
843 UErrorCode status
= U_ZERO_ERROR
;
844 CFIndex idx
, cnt
= udat_countSymbols(icudf
, (UDateFormatSymbolType
)icucode
) - index_base
;
845 STACK_BUFFER_DECL(CFStringRef
, strings
, cnt
);
846 for (idx
= 0; idx
< cnt
; idx
++) {
847 UChar ubuffer
[BUFFER_SIZE
];
848 CFStringRef str
= NULL
;
849 status
= U_ZERO_ERROR
;
850 CFIndex ucnt
= udat_getSymbols(icudf
, (UDateFormatSymbolType
)icucode
, idx
+ index_base
, ubuffer
, BUFFER_SIZE
, &status
);
851 if (U_SUCCESS(status
) && cnt
<= BUFFER_SIZE
) {
852 str
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, (const UniChar
*)ubuffer
, ucnt
);
854 strings
[idx
] = !str
? (CFStringRef
)CFRetain(CFSTR("<error>")) : str
;
856 CFArrayRef array
= CFArrayCreate(kCFAllocatorSystemDefault
, (const void **)strings
, cnt
, &kCFTypeArrayCallBacks
);
858 CFRelease(strings
[cnt
]);
863 #define SET_SYMBOLS_ARRAY(A, B, C) \
864 if (!directToICU) { \
865 oldProperty = formatter->_property. C; \
866 formatter->_property. C = NULL; \
868 __CFDateFormatterSetSymbolsArray(formatter->_df, A, B, value); \
869 if (!directToICU) { \
870 formatter->_property. C = __CFDateFormatterGetSymbolsArray(formatter->_df, A, B); \
873 static void __CFDateFormatterSetProperty(CFDateFormatterRef formatter
, CFStringRef key
, CFTypeRef value
, Boolean directToICU
) {
874 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
875 __CFGenericValidateType(key
, CFStringGetTypeID());
876 CFTypeRef oldProperty
= NULL
;
877 UErrorCode status
= U_ZERO_ERROR
;
878 UChar ubuffer
[BUFFER_SIZE
];
880 if (kCFDateFormatterIsLenientKey
== key
) {
882 oldProperty
= formatter
->_property
. _IsLenient
;
883 formatter
->_property
. _IsLenient
= NULL
;
885 __CFGenericValidateType(value
, CFBooleanGetTypeID());
886 udat_setLenient(formatter
->_df
, (kCFBooleanTrue
== value
));
887 UCalendar
*cal
= (UCalendar
*)udat_getCalendar(formatter
->_df
);
888 if (cal
) ucal_setAttribute(cal
, UCAL_LENIENT
, (kCFBooleanTrue
== value
));
890 formatter
->_property
. _IsLenient
= (CFBooleanRef
)CFDateFormatterCopyProperty(formatter
, kCFDateFormatterIsLenientKey
);
892 } else if (kCFDateFormatterDoesRelativeDateFormattingKey
== key
) {
894 oldProperty
= formatter
->_property
. _DoesRelativeDateFormatting
;
895 formatter
->_property
. _DoesRelativeDateFormatting
= NULL
;
897 __CFGenericValidateType(value
, CFBooleanGetTypeID());
899 if (kCFBooleanTrue
!= value
) value
= kCFBooleanFalse
;
900 formatter
->_property
. _DoesRelativeDateFormatting
= value
? (CFBooleanRef
)CFRetain(value
) : NULL
;
901 __ResetUDateFormat(formatter
, false);
903 } else if (kCFDateFormatterCalendarKey
== key
) {
905 oldProperty
= formatter
->_property
. _Calendar
;
906 formatter
->_property
. _Calendar
= NULL
;
908 __CFGenericValidateType(value
, CFCalendarGetTypeID());
909 CFStringRef localeName
= CFLocaleGetIdentifier(formatter
->_locale
);
910 CFDictionaryRef components
= CFLocaleCreateComponentsFromLocaleIdentifier(kCFAllocatorSystemDefault
, localeName
);
911 CFMutableDictionaryRef mcomponents
= CFDictionaryCreateMutableCopy(kCFAllocatorSystemDefault
, 0, components
);
912 CFDictionarySetValue(mcomponents
, kCFLocaleCalendarIdentifierKey
, CFCalendarGetIdentifier((CFCalendarRef
)value
));
913 localeName
= CFLocaleCreateLocaleIdentifierFromComponents(kCFAllocatorSystemDefault
, mcomponents
);
914 CFRelease(mcomponents
);
915 CFRelease(components
);
916 CFLocaleRef newLocale
= CFLocaleCreate(CFGetAllocator(formatter
->_locale
), localeName
);
917 CFRelease(localeName
);
918 CFRelease(formatter
->_locale
);
919 formatter
->_locale
= newLocale
;
920 UCalendar
*cal
= __CFCalendarCreateUCalendar(NULL
, CFLocaleGetIdentifier(formatter
->_locale
), formatter
->_property
._TimeZone
);
921 if (cal
) ucal_setAttribute(cal
, UCAL_FIRST_DAY_OF_WEEK
, CFCalendarGetFirstWeekday((CFCalendarRef
)value
));
922 if (cal
) ucal_setAttribute(cal
, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK
, CFCalendarGetMinimumDaysInFirstWeek((CFCalendarRef
)value
));
923 if (cal
) udat_setCalendar(formatter
->_df
, cal
);
924 if (cal
) ucal_close(cal
);
926 formatter
->_property
. _Calendar
= (CFCalendarRef
)CFDateFormatterCopyProperty(formatter
, kCFDateFormatterCalendarKey
);
928 } else if (kCFDateFormatterCalendarIdentifierKey
== key
) {
930 oldProperty
= formatter
->_property
. _CalendarName
;
931 formatter
->_property
. _CalendarName
= NULL
;
933 __CFGenericValidateType(value
, CFStringGetTypeID());
934 CFStringRef localeName
= CFLocaleGetIdentifier(formatter
->_locale
);
935 CFDictionaryRef components
= CFLocaleCreateComponentsFromLocaleIdentifier(kCFAllocatorSystemDefault
, localeName
);
936 CFMutableDictionaryRef mcomponents
= CFDictionaryCreateMutableCopy(kCFAllocatorSystemDefault
, 0, components
);
937 CFDictionarySetValue(mcomponents
, kCFLocaleCalendarIdentifierKey
, value
);
938 localeName
= CFLocaleCreateLocaleIdentifierFromComponents(kCFAllocatorSystemDefault
, mcomponents
);
939 CFRelease(mcomponents
);
940 CFRelease(components
);
941 CFLocaleRef newLocale
= CFLocaleCreate(CFGetAllocator(formatter
->_locale
), localeName
);
942 CFRelease(localeName
);
943 CFRelease(formatter
->_locale
);
944 formatter
->_locale
= newLocale
;
945 UCalendar
*cal
= __CFCalendarCreateUCalendar(NULL
, CFLocaleGetIdentifier(formatter
->_locale
), formatter
->_property
._TimeZone
);
946 if (cal
) udat_setCalendar(formatter
->_df
, cal
);
947 if (cal
) ucal_close(cal
);
949 formatter
->_property
. _CalendarName
= (CFStringRef
)CFDateFormatterCopyProperty(formatter
, kCFDateFormatterCalendarIdentifierKey
);
951 } else if (kCFDateFormatterTimeZoneKey
== key
) {
952 if (formatter
->_property
. _TimeZone
!= value
) {
954 oldProperty
= formatter
->_property
. _TimeZone
;
955 formatter
->_property
. _TimeZone
= NULL
;
957 __CFGenericValidateType(value
, CFTimeZoneGetTypeID());
958 CFTimeZoneRef old
= formatter
->_property
._TimeZone
;
959 formatter
->_property
._TimeZone
= value
? (CFTimeZoneRef
)CFRetain(value
) : CFTimeZoneCopyDefault();
960 if (old
) CFRelease(old
);
961 CFStringRef tznam
= CFTimeZoneGetName(formatter
->_property
._TimeZone
);
962 UCalendar
*cal
= (UCalendar
*)udat_getCalendar(formatter
->_df
);
963 CFIndex ucnt
= CFStringGetLength(tznam
);
964 if (BUFFER_SIZE
< ucnt
) ucnt
= BUFFER_SIZE
;
965 CFStringGetCharacters(tznam
, CFRangeMake(0, ucnt
), (UniChar
*)ubuffer
);
966 ucal_setTimeZone(cal
, ubuffer
, ucnt
, &status
);
968 old
= formatter
->_property
._TimeZone
;
969 formatter
->_property
. _TimeZone
= (CFTimeZoneRef
)CFDateFormatterCopyProperty(formatter
, kCFDateFormatterTimeZoneKey
);
970 if (old
) CFRelease(old
);
973 } else if (kCFDateFormatterDefaultFormatKey
== key
) {
974 // read-only attribute
975 } else if (kCFDateFormatterTwoDigitStartDateKey
== key
) {
977 oldProperty
= formatter
->_property
. _TwoDigitStartDate
;
978 formatter
->_property
. _TwoDigitStartDate
= NULL
;
980 __CFGenericValidateType(value
, CFDateGetTypeID());
981 CFAbsoluteTime at
= CFDateGetAbsoluteTime((CFDateRef
)value
);
982 UDate udate
= (at
+ kCFAbsoluteTimeIntervalSince1970
) * 1000.0;
983 udat_set2DigitYearStart(formatter
->_df
, udate
, &status
);
985 formatter
->_property
. _TwoDigitStartDate
= (CFDateRef
)CFDateFormatterCopyProperty(formatter
, kCFDateFormatterTwoDigitStartDateKey
);
987 } else if (kCFDateFormatterDefaultDateKey
== key
) {
989 oldProperty
= formatter
->_property
. _DefaultDate
;
990 formatter
->_property
. _DefaultDate
= NULL
;
992 __CFGenericValidateType(value
, CFDateGetTypeID());
994 formatter
->_property
._DefaultDate
= value
? (CFDateRef
)CFRetain(value
) : NULL
;
996 } else if (kCFDateFormatterGregorianStartDateKey
== key
) {
998 oldProperty
= formatter
->_property
. _GregorianStartDate
;
999 formatter
->_property
. _GregorianStartDate
= NULL
;
1001 __CFGenericValidateType(value
, CFDateGetTypeID());
1002 CFAbsoluteTime at
= CFDateGetAbsoluteTime((CFDateRef
)value
);
1003 UDate udate
= (at
+ kCFAbsoluteTimeIntervalSince1970
) * 1000.0;
1004 UCalendar
*cal
= (UCalendar
*)udat_getCalendar(formatter
->_df
);
1005 ucal_setGregorianChange(cal
, udate
, &status
);
1007 formatter
->_property
. _GregorianStartDate
= (CFDateRef
)CFDateFormatterCopyProperty(formatter
, kCFDateFormatterGregorianStartDateKey
);
1009 } else if (kCFDateFormatterEraSymbolsKey
== key
) {
1010 SET_SYMBOLS_ARRAY(UDAT_ERAS
, 0, _EraSymbols
)
1011 } else if (kCFDateFormatterLongEraSymbolsKey
== key
) {
1012 SET_SYMBOLS_ARRAY(UDAT_ERA_NAMES
, 0, _LongEraSymbols
)
1013 } else if (kCFDateFormatterMonthSymbolsKey
== key
) {
1014 SET_SYMBOLS_ARRAY(UDAT_MONTHS
, 0, _MonthSymbols
)
1015 } else if (kCFDateFormatterShortMonthSymbolsKey
== key
) {
1016 SET_SYMBOLS_ARRAY(UDAT_SHORT_MONTHS
, 0, _ShortMonthSymbols
)
1017 } else if (kCFDateFormatterVeryShortMonthSymbolsKey
== key
) {
1018 SET_SYMBOLS_ARRAY(UDAT_NARROW_MONTHS
, 0, _VeryShortMonthSymbols
)
1019 } else if (kCFDateFormatterStandaloneMonthSymbolsKey
== key
) {
1020 SET_SYMBOLS_ARRAY(UDAT_STANDALONE_MONTHS
, 0, _StandaloneMonthSymbols
)
1021 } else if (kCFDateFormatterShortStandaloneMonthSymbolsKey
== key
) {
1022 SET_SYMBOLS_ARRAY(UDAT_STANDALONE_SHORT_MONTHS
, 0, _ShortStandaloneMonthSymbols
)
1023 } else if (kCFDateFormatterVeryShortStandaloneMonthSymbolsKey
== key
) {
1024 SET_SYMBOLS_ARRAY(UDAT_STANDALONE_NARROW_MONTHS
, 0, _VeryShortStandaloneMonthSymbols
)
1025 } else if (kCFDateFormatterWeekdaySymbolsKey
== key
) {
1026 SET_SYMBOLS_ARRAY(UDAT_WEEKDAYS
, 1, _WeekdaySymbols
)
1027 } else if (kCFDateFormatterShortWeekdaySymbolsKey
== key
) {
1028 SET_SYMBOLS_ARRAY(UDAT_SHORT_WEEKDAYS
, 1, _ShortWeekdaySymbols
)
1029 } else if (kCFDateFormatterVeryShortWeekdaySymbolsKey
== key
) {
1030 SET_SYMBOLS_ARRAY(UDAT_NARROW_WEEKDAYS
, 1, _VeryShortWeekdaySymbols
)
1031 } else if (kCFDateFormatterStandaloneWeekdaySymbolsKey
== key
) {
1032 SET_SYMBOLS_ARRAY(UDAT_STANDALONE_WEEKDAYS
, 1, _StandaloneWeekdaySymbols
)
1033 } else if (kCFDateFormatterShortStandaloneWeekdaySymbolsKey
== key
) {
1034 SET_SYMBOLS_ARRAY(UDAT_STANDALONE_SHORT_WEEKDAYS
, 1, _ShortStandaloneWeekdaySymbols
)
1035 } else if (kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey
== key
) {
1036 SET_SYMBOLS_ARRAY(UDAT_STANDALONE_NARROW_WEEKDAYS
, 1, _VeryShortStandaloneWeekdaySymbols
)
1037 } else if (kCFDateFormatterQuarterSymbolsKey
== key
) {
1038 SET_SYMBOLS_ARRAY(UDAT_QUARTERS
, 0, _QuarterSymbols
)
1039 } else if (kCFDateFormatterShortQuarterSymbolsKey
== key
) {
1040 SET_SYMBOLS_ARRAY(UDAT_SHORT_QUARTERS
, 0, _ShortQuarterSymbols
)
1041 } else if (kCFDateFormatterStandaloneQuarterSymbolsKey
== key
) {
1042 SET_SYMBOLS_ARRAY(UDAT_STANDALONE_QUARTERS
, 0, _StandaloneQuarterSymbols
)
1043 } else if (kCFDateFormatterShortStandaloneQuarterSymbolsKey
== key
) {
1044 SET_SYMBOLS_ARRAY(UDAT_STANDALONE_SHORT_QUARTERS
, 0, _ShortStandaloneQuarterSymbols
)
1045 } else if (kCFDateFormatterAMSymbolKey
== key
) {
1047 oldProperty
= formatter
->_property
. _AMSymbol
;
1048 formatter
->_property
. _AMSymbol
= NULL
;
1050 __CFGenericValidateType(value
, CFStringGetTypeID());
1051 CFIndex item_cnt
= CFStringGetLength((CFStringRef
)value
);
1052 STACK_BUFFER_DECL(UChar
, item_buffer
, __CFMin(BUFFER_SIZE
, item_cnt
));
1053 UChar
*item_ustr
= (UChar
*)CFStringGetCharactersPtr((CFStringRef
)value
);
1054 if (NULL
== item_ustr
) {
1055 item_cnt
= __CFMin(BUFFER_SIZE
, item_cnt
);
1056 CFStringGetCharacters((CFStringRef
)value
, CFRangeMake(0, item_cnt
), (UniChar
*)item_buffer
);
1057 item_ustr
= item_buffer
;
1059 udat_setSymbols(formatter
->_df
, UDAT_AM_PMS
, 0, item_ustr
, item_cnt
, &status
);
1061 formatter
->_property
. _AMSymbol
= (CFStringRef
)CFDateFormatterCopyProperty(formatter
, kCFDateFormatterAMSymbolKey
);
1063 } else if (kCFDateFormatterPMSymbolKey
== key
) {
1065 oldProperty
= formatter
->_property
. _PMSymbol
;
1066 formatter
->_property
. _PMSymbol
= NULL
;
1068 __CFGenericValidateType(value
, CFStringGetTypeID());
1069 CFIndex item_cnt
= CFStringGetLength((CFStringRef
)value
);
1070 STACK_BUFFER_DECL(UChar
, item_buffer
, __CFMin(BUFFER_SIZE
, item_cnt
));
1071 UChar
*item_ustr
= (UChar
*)CFStringGetCharactersPtr((CFStringRef
)value
);
1072 if (NULL
== item_ustr
) {
1073 item_cnt
= __CFMin(BUFFER_SIZE
, item_cnt
);
1074 CFStringGetCharacters((CFStringRef
)value
, CFRangeMake(0, item_cnt
), (UniChar
*)item_buffer
);
1075 item_ustr
= item_buffer
;
1077 udat_setSymbols(formatter
->_df
, UDAT_AM_PMS
, 1, item_ustr
, item_cnt
, &status
);
1079 formatter
->_property
. _PMSymbol
= (CFStringRef
)CFDateFormatterCopyProperty(formatter
, kCFDateFormatterPMSymbolKey
);
1082 CFAssert3(0, __kCFLogAssertion
, "%s(): unknown key %p (%@)", __PRETTY_FUNCTION__
, key
, key
);
1084 if (oldProperty
) CFRelease(oldProperty
);
1087 void CFDateFormatterSetProperty(CFDateFormatterRef formatter
, CFStringRef key
, CFTypeRef value
) {
1088 __CFDateFormatterSetProperty(formatter
, key
, value
, false);
1091 CFTypeRef
CFDateFormatterCopyProperty(CFDateFormatterRef formatter
, CFStringRef key
) {
1092 __CFGenericValidateType(formatter
, CFDateFormatterGetTypeID());
1093 __CFGenericValidateType(key
, CFStringGetTypeID());
1094 UErrorCode status
= U_ZERO_ERROR
;
1095 UChar ubuffer
[BUFFER_SIZE
];
1097 if (kCFDateFormatterIsLenientKey
== key
) {
1098 if (formatter
->_property
._IsLenient
) return CFRetain(formatter
->_property
._IsLenient
);
1099 return CFRetain(udat_isLenient(formatter
->_df
) ? kCFBooleanTrue
: kCFBooleanFalse
);
1100 } else if (kCFDateFormatterDoesRelativeDateFormattingKey
== key
) {
1101 if (formatter
->_property
._DoesRelativeDateFormatting
) return CFRetain(formatter
->_property
._DoesRelativeDateFormatting
);
1102 return CFRetain(kCFBooleanFalse
);
1103 } else if (kCFDateFormatterCalendarKey
== key
) {
1104 if (formatter
->_property
._Calendar
) return CFRetain(formatter
->_property
._Calendar
);
1105 CFCalendarRef calendar
= (CFCalendarRef
)CFLocaleGetValue(formatter
->_locale
, kCFLocaleCalendarKey
);
1106 return calendar
? CFRetain(calendar
) : NULL
;
1107 } else if (kCFDateFormatterCalendarIdentifierKey
== key
) {
1108 if (formatter
->_property
._CalendarName
) return CFRetain(formatter
->_property
._CalendarName
);
1109 CFStringRef ident
= (CFStringRef
)CFLocaleGetValue(formatter
->_locale
, kCFLocaleCalendarIdentifierKey
);
1110 return ident
? CFRetain(ident
) : NULL
;
1111 } else if (kCFDateFormatterTimeZoneKey
== key
) {
1112 if (formatter
->_property
._TwoDigitStartDate
) return CFRetain(formatter
->_property
._TwoDigitStartDate
);
1113 return CFRetain(formatter
->_property
._TimeZone
);
1114 } else if (kCFDateFormatterDefaultFormatKey
== key
) {
1115 return formatter
->_defformat
? CFRetain(formatter
->_defformat
) : NULL
;
1116 } else if (kCFDateFormatterTwoDigitStartDateKey
== key
) {
1117 if (formatter
->_property
._TwoDigitStartDate
) return CFRetain(formatter
->_property
._TwoDigitStartDate
);
1118 UDate udate
= udat_get2DigitYearStart(formatter
->_df
, &status
);
1119 if (U_SUCCESS(status
)) {
1120 CFAbsoluteTime at
= (double)udate
/ 1000.0 - kCFAbsoluteTimeIntervalSince1970
;
1121 return CFDateCreate(CFGetAllocator(formatter
), at
);
1123 } else if (kCFDateFormatterDefaultDateKey
== key
) {
1124 return formatter
->_property
._DefaultDate
? CFRetain(formatter
->_property
._DefaultDate
) : NULL
;
1125 } else if (kCFDateFormatterGregorianStartDateKey
== key
) {
1126 if (formatter
->_property
._GregorianStartDate
) return CFRetain(formatter
->_property
._GregorianStartDate
);
1127 UCalendar
*cal
= (UCalendar
*)udat_getCalendar(formatter
->_df
);
1128 UDate udate
= ucal_getGregorianChange(cal
, &status
);
1129 if (U_SUCCESS(status
)) {
1130 CFAbsoluteTime at
= (double)udate
/ 1000.0 - kCFAbsoluteTimeIntervalSince1970
;
1131 return CFDateCreate(CFGetAllocator(formatter
), at
);
1133 } else if (kCFDateFormatterEraSymbolsKey
== key
) {
1134 if (formatter
->_property
._EraSymbols
) return CFRetain(formatter
->_property
._EraSymbols
);
1135 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_ERAS
, 0);
1136 } else if (kCFDateFormatterLongEraSymbolsKey
== key
) {
1137 if (formatter
->_property
._LongEraSymbols
) return CFRetain(formatter
->_property
._LongEraSymbols
);
1138 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_ERA_NAMES
, 0);
1139 } else if (kCFDateFormatterMonthSymbolsKey
== key
) {
1140 if (formatter
->_property
._MonthSymbols
) return CFRetain(formatter
->_property
._MonthSymbols
);
1141 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_MONTHS
, 0);
1142 } else if (kCFDateFormatterShortMonthSymbolsKey
== key
) {
1143 if (formatter
->_property
._ShortMonthSymbols
) return CFRetain(formatter
->_property
._ShortMonthSymbols
);
1144 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_SHORT_MONTHS
, 0);
1145 } else if (kCFDateFormatterVeryShortMonthSymbolsKey
== key
) {
1146 if (formatter
->_property
._VeryShortMonthSymbols
) return CFRetain(formatter
->_property
._VeryShortMonthSymbols
);
1147 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_NARROW_MONTHS
, 0);
1148 } else if (kCFDateFormatterStandaloneMonthSymbolsKey
== key
) {
1149 if (formatter
->_property
._StandaloneMonthSymbols
) return CFRetain(formatter
->_property
._StandaloneMonthSymbols
);
1150 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_STANDALONE_MONTHS
, 0);
1151 } else if (kCFDateFormatterShortStandaloneMonthSymbolsKey
== key
) {
1152 if (formatter
->_property
._ShortStandaloneMonthSymbols
) return CFRetain(formatter
->_property
._ShortStandaloneMonthSymbols
);
1153 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_STANDALONE_SHORT_MONTHS
, 0);
1154 } else if (kCFDateFormatterVeryShortStandaloneMonthSymbolsKey
== key
) {
1155 if (formatter
->_property
._VeryShortStandaloneMonthSymbols
) return CFRetain(formatter
->_property
._VeryShortStandaloneMonthSymbols
);
1156 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_STANDALONE_NARROW_MONTHS
, 0);
1157 } else if (kCFDateFormatterWeekdaySymbolsKey
== key
) {
1158 if (formatter
->_property
._WeekdaySymbols
) return CFRetain(formatter
->_property
._WeekdaySymbols
);
1159 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_WEEKDAYS
, 1);
1160 } else if (kCFDateFormatterShortWeekdaySymbolsKey
== key
) {
1161 if (formatter
->_property
._ShortWeekdaySymbols
) return CFRetain(formatter
->_property
._ShortWeekdaySymbols
);
1162 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_SHORT_WEEKDAYS
, 1);
1163 } else if (kCFDateFormatterVeryShortWeekdaySymbolsKey
== key
) {
1164 if (formatter
->_property
._VeryShortWeekdaySymbols
) return CFRetain(formatter
->_property
._VeryShortWeekdaySymbols
);
1165 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_NARROW_WEEKDAYS
, 1);
1166 } else if (kCFDateFormatterStandaloneWeekdaySymbolsKey
== key
) {
1167 if (formatter
->_property
._StandaloneWeekdaySymbols
) return CFRetain(formatter
->_property
._StandaloneWeekdaySymbols
);
1168 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_STANDALONE_WEEKDAYS
, 1);
1169 } else if (kCFDateFormatterShortStandaloneWeekdaySymbolsKey
== key
) {
1170 if (formatter
->_property
._ShortStandaloneWeekdaySymbols
) return CFRetain(formatter
->_property
._ShortStandaloneWeekdaySymbols
);
1171 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_STANDALONE_SHORT_WEEKDAYS
, 1);
1172 } else if (kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey
== key
) {
1173 if (formatter
->_property
._VeryShortStandaloneWeekdaySymbols
) return CFRetain(formatter
->_property
._VeryShortStandaloneWeekdaySymbols
);
1174 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_STANDALONE_NARROW_WEEKDAYS
, 1);
1175 } else if (kCFDateFormatterQuarterSymbolsKey
== key
) {
1176 if (formatter
->_property
._QuarterSymbols
) return CFRetain(formatter
->_property
._QuarterSymbols
);
1177 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_QUARTERS
, 0);
1178 } else if (kCFDateFormatterShortQuarterSymbolsKey
== key
) {
1179 if (formatter
->_property
._ShortQuarterSymbols
) return CFRetain(formatter
->_property
._ShortQuarterSymbols
);
1180 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_SHORT_QUARTERS
, 0);
1181 } else if (kCFDateFormatterStandaloneQuarterSymbolsKey
== key
) {
1182 if (formatter
->_property
._StandaloneQuarterSymbols
) return CFRetain(formatter
->_property
._StandaloneQuarterSymbols
);
1183 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_STANDALONE_QUARTERS
, 0);
1184 } else if (kCFDateFormatterShortStandaloneQuarterSymbolsKey
== key
) {
1185 if (formatter
->_property
._ShortStandaloneQuarterSymbols
) return CFRetain(formatter
->_property
._ShortStandaloneQuarterSymbols
);
1186 return __CFDateFormatterGetSymbolsArray(formatter
->_df
, UDAT_STANDALONE_SHORT_QUARTERS
, 0);
1187 } else if (kCFDateFormatterAMSymbolKey
== key
) {
1188 if (formatter
->_property
._AMSymbol
) return CFRetain(formatter
->_property
._AMSymbol
);
1189 CFIndex cnt
= udat_countSymbols(formatter
->_df
, UDAT_AM_PMS
);
1191 CFIndex ucnt
= udat_getSymbols(formatter
->_df
, UDAT_AM_PMS
, 0, ubuffer
, BUFFER_SIZE
, &status
);
1192 if (U_SUCCESS(status
) && cnt
<= BUFFER_SIZE
) {
1193 return CFStringCreateWithCharacters(CFGetAllocator(formatter
), (UniChar
*)ubuffer
, ucnt
);
1196 } else if (kCFDateFormatterPMSymbolKey
== key
) {
1197 if (formatter
->_property
._PMSymbol
) return CFRetain(formatter
->_property
._PMSymbol
);
1198 CFIndex cnt
= udat_countSymbols(formatter
->_df
, UDAT_AM_PMS
);
1200 CFIndex ucnt
= udat_getSymbols(formatter
->_df
, UDAT_AM_PMS
, 1, ubuffer
, BUFFER_SIZE
, &status
);
1201 if (U_SUCCESS(status
) && cnt
<= BUFFER_SIZE
) {
1202 return CFStringCreateWithCharacters(CFGetAllocator(formatter
), (UniChar
*)ubuffer
, ucnt
);
1206 CFAssert3(0, __kCFLogAssertion
, "%s(): unknown key %p (%@)", __PRETTY_FUNCTION__
, key
, key
);