]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/udat.cpp
ICU-531.48.tar.gz
[apple/icu.git] / icuSources / i18n / udat.cpp
CommitLineData
b75a7d8f
A
1/*
2*******************************************************************************
57a6839d 3* Copyright (C) 1996-2014, International Business Machines
b75a7d8f
A
4* Corporation and others. All Rights Reserved.
5*******************************************************************************
6*/
7
8#include "unicode/utypes.h"
9
10#if !UCONFIG_NO_FORMATTING
11
12#include "unicode/udat.h"
13
14#include "unicode/uloc.h"
15#include "unicode/datefmt.h"
16#include "unicode/timezone.h"
17#include "unicode/smpdtfmt.h"
18#include "unicode/fieldpos.h"
19#include "unicode/parsepos.h"
20#include "unicode/calendar.h"
21#include "unicode/numfmt.h"
22#include "unicode/dtfmtsym.h"
23#include "unicode/ustring.h"
51004dcb 24#include "unicode/udisplaycontext.h"
b75a7d8f 25#include "cpputils.h"
46f4442e 26#include "reldtfmt.h"
4388f060 27#include "umutex.h"
b75a7d8f
A
28
29U_NAMESPACE_USE
30
46f4442e
A
31/**
32 * Verify that fmt is a SimpleDateFormat. Invalid error if not.
33 * @param fmt the UDateFormat, definitely a DateFormat, maybe something else
34 * @param status error code, will be set to failure if there is a familure or the fmt is NULL.
35 */
36static void verifyIsSimpleDateFormat(const UDateFormat* fmt, UErrorCode *status) {
729e4ab9
A
37 if(U_SUCCESS(*status) &&
38 dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))==NULL) {
46f4442e
A
39 *status = U_ILLEGAL_ARGUMENT_ERROR;
40 }
41}
42
729e4ab9
A
43// This mirrors the correspondence between the
44// SimpleDateFormat::fgPatternIndexToDateFormatField and
45// SimpleDateFormat::fgPatternIndexToCalendarField arrays.
46static UCalendarDateFields gDateFieldMapping[] = {
47 UCAL_ERA, // UDAT_ERA_FIELD = 0
48 UCAL_YEAR, // UDAT_YEAR_FIELD = 1
49 UCAL_MONTH, // UDAT_MONTH_FIELD = 2
50 UCAL_DATE, // UDAT_DATE_FIELD = 3
51 UCAL_HOUR_OF_DAY, // UDAT_HOUR_OF_DAY1_FIELD = 4
52 UCAL_HOUR_OF_DAY, // UDAT_HOUR_OF_DAY0_FIELD = 5
53 UCAL_MINUTE, // UDAT_MINUTE_FIELD = 6
54 UCAL_SECOND, // UDAT_SECOND_FIELD = 7
55 UCAL_MILLISECOND, // UDAT_FRACTIONAL_SECOND_FIELD = 8
56 UCAL_DAY_OF_WEEK, // UDAT_DAY_OF_WEEK_FIELD = 9
57 UCAL_DAY_OF_YEAR, // UDAT_DAY_OF_YEAR_FIELD = 10
58 UCAL_DAY_OF_WEEK_IN_MONTH, // UDAT_DAY_OF_WEEK_IN_MONTH_FIELD = 11
59 UCAL_WEEK_OF_YEAR, // UDAT_WEEK_OF_YEAR_FIELD = 12
60 UCAL_WEEK_OF_MONTH, // UDAT_WEEK_OF_MONTH_FIELD = 13
61 UCAL_AM_PM, // UDAT_AM_PM_FIELD = 14
62 UCAL_HOUR, // UDAT_HOUR1_FIELD = 15
63 UCAL_HOUR, // UDAT_HOUR0_FIELD = 16
64 UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_FIELD = 17
65 UCAL_YEAR_WOY, // UDAT_YEAR_WOY_FIELD = 18
66 UCAL_DOW_LOCAL, // UDAT_DOW_LOCAL_FIELD = 19
67 UCAL_EXTENDED_YEAR, // UDAT_EXTENDED_YEAR_FIELD = 20
68 UCAL_JULIAN_DAY, // UDAT_JULIAN_DAY_FIELD = 21
69 UCAL_MILLISECONDS_IN_DAY, // UDAT_MILLISECONDS_IN_DAY_FIELD = 22
57a6839d
A
70 UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_RFC_FIELD = 23 (also UCAL_DST_OFFSET)
71 UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_GENERIC_FIELD = 24 (also UCAL_DST_OFFSET)
729e4ab9
A
72 UCAL_DOW_LOCAL, // UDAT_STANDALONE_DAY_FIELD = 25
73 UCAL_MONTH, // UDAT_STANDALONE_MONTH_FIELD = 26
74 UCAL_MONTH, // UDAT_QUARTER_FIELD = 27
75 UCAL_MONTH, // UDAT_STANDALONE_QUARTER_FIELD = 28
57a6839d 76 UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_SPECIAL_FIELD = 29 (also UCAL_DST_OFFSET)
4388f060 77 UCAL_YEAR, // UDAT_YEAR_NAME_FIELD = 30
57a6839d
A
78 UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD = 31 (also UCAL_DST_OFFSET)
79 UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_ISO_FIELD = 32 (also UCAL_DST_OFFSET)
80 UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_ISO_LOCAL_FIELD = 33 (also UCAL_DST_OFFSET)
81 UCAL_EXTENDED_YEAR, // UDAT_RELATED_YEAR_FIELD = 34 (not an exact match)
82 UCAL_FIELD_COUNT, // UDAT_FIELD_COUNT = 35
729e4ab9
A
83 // UCAL_IS_LEAP_MONTH is not the target of a mapping
84};
85
86U_CAPI UCalendarDateFields U_EXPORT2
87udat_toCalendarDateField(UDateFormatField field) {
88 return gDateFieldMapping[field];
89}
90
4388f060
A
91/* For now- one opener. */
92static UDateFormatOpener gOpener = NULL;
93
94U_INTERNAL void U_EXPORT2
95udat_registerOpener(UDateFormatOpener opener, UErrorCode *status)
96{
97 if(U_FAILURE(*status)) return;
98 umtx_lock(NULL);
99 if(gOpener==NULL) {
100 gOpener = opener;
101 } else {
102 *status = U_ILLEGAL_ARGUMENT_ERROR;
103 }
104 umtx_unlock(NULL);
105}
106
107U_INTERNAL UDateFormatOpener U_EXPORT2
108udat_unregisterOpener(UDateFormatOpener opener, UErrorCode *status)
109{
110 if(U_FAILURE(*status)) return NULL;
111 UDateFormatOpener oldOpener = NULL;
112 umtx_lock(NULL);
113 if(gOpener==NULL || gOpener!=opener) {
114 *status = U_ILLEGAL_ARGUMENT_ERROR;
115 } else {
116 oldOpener=gOpener;
117 gOpener=NULL;
118 }
119 umtx_unlock(NULL);
120 return oldOpener;
121}
122
123
124
b75a7d8f
A
125U_CAPI UDateFormat* U_EXPORT2
126udat_open(UDateFormatStyle timeStyle,
127 UDateFormatStyle dateStyle,
128 const char *locale,
129 const UChar *tzID,
130 int32_t tzIDLength,
131 const UChar *pattern,
132 int32_t patternLength,
133 UErrorCode *status)
134{
73c04bcf
A
135 DateFormat *fmt;
136 if(U_FAILURE(*status)) {
b75a7d8f 137 return 0;
374ca955 138 }
4388f060
A
139 if(gOpener!=NULL) { // if it's registered
140 fmt = (DateFormat*) (*gOpener)(timeStyle,dateStyle,locale,tzID,tzIDLength,pattern,patternLength,status);
141 if(fmt!=NULL) {
142 return (UDateFormat*)fmt;
143 } // else fall through.
144 }
51004dcb 145 if(timeStyle != UDAT_PATTERN) {
73c04bcf 146 if(locale == 0) {
374ca955
A
147 fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle,
148 (DateFormat::EStyle)timeStyle);
73c04bcf
A
149 }
150 else {
374ca955
A
151 fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle,
152 (DateFormat::EStyle)timeStyle,
153 Locale(locale));
b75a7d8f 154 }
73c04bcf
A
155 }
156 else {
157 UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength);
374ca955 158
73c04bcf
A
159 if(locale == 0) {
160 fmt = new SimpleDateFormat(pat, *status);
161 }
162 else {
163 fmt = new SimpleDateFormat(pat, Locale(locale), *status);
374ca955 164 }
374ca955 165 }
374ca955 166
73c04bcf
A
167 if(fmt == 0) {
168 *status = U_MEMORY_ALLOCATION_ERROR;
169 return 0;
170 }
374ca955 171
73c04bcf
A
172 if(tzID != 0) {
173 TimeZone *zone = TimeZone::createTimeZone(UnicodeString((UBool)(tzIDLength == -1), tzID, tzIDLength));
174 if(zone == 0) {
374ca955 175 *status = U_MEMORY_ALLOCATION_ERROR;
73c04bcf 176 delete fmt;
374ca955
A
177 return 0;
178 }
73c04bcf 179 fmt->adoptTimeZone(zone);
374ca955 180 }
73c04bcf
A
181
182 return (UDateFormat*)fmt;
b75a7d8f
A
183}
184
185
186U_CAPI void U_EXPORT2
187udat_close(UDateFormat* format)
188{
374ca955 189 delete (DateFormat*)format;
b75a7d8f
A
190}
191
192U_CAPI UDateFormat* U_EXPORT2
193udat_clone(const UDateFormat *fmt,
194 UErrorCode *status)
195{
374ca955 196 if(U_FAILURE(*status)) return 0;
b75a7d8f 197
46f4442e 198 Format *res = ((DateFormat*)fmt)->clone();
b75a7d8f 199
374ca955
A
200 if(res == 0) {
201 *status = U_MEMORY_ALLOCATION_ERROR;
202 return 0;
203 }
b75a7d8f 204
374ca955 205 return (UDateFormat*) res;
b75a7d8f
A
206}
207
208U_CAPI int32_t U_EXPORT2
209udat_format( const UDateFormat* format,
210 UDate dateToFormat,
211 UChar* result,
212 int32_t resultLength,
213 UFieldPosition* position,
214 UErrorCode* status)
215{
374ca955
A
216 if(U_FAILURE(*status)) return -1;
217
218 UnicodeString res;
219 if(!(result==NULL && resultLength==0)) {
220 // NULL destination for pure preflighting: empty dummy string
221 // otherwise, alias the destination buffer
222 res.setTo(result, 0, resultLength);
223 }
224
225 FieldPosition fp;
b75a7d8f 226
374ca955
A
227 if(position != 0)
228 fp.setField(position->field);
229
230 ((DateFormat*)format)->format(dateToFormat, res, fp);
231
232 if(position != 0) {
233 position->beginIndex = fp.getBeginIndex();
234 position->endIndex = fp.getEndIndex();
235 }
236
237 return res.extract(result, resultLength, *status);
b75a7d8f
A
238}
239
240U_CAPI UDate U_EXPORT2
241udat_parse( const UDateFormat* format,
242 const UChar* text,
243 int32_t textLength,
244 int32_t *parsePos,
245 UErrorCode *status)
246{
374ca955 247 if(U_FAILURE(*status)) return (UDate)0;
b75a7d8f 248
374ca955
A
249 const UnicodeString src((UBool)(textLength == -1), text, textLength);
250 ParsePosition pp;
251 int32_t stackParsePos = 0;
252 UDate res;
b75a7d8f 253
374ca955
A
254 if(parsePos == NULL) {
255 parsePos = &stackParsePos;
256 }
b75a7d8f 257
b75a7d8f
A
258 pp.setIndex(*parsePos);
259
374ca955 260 res = ((DateFormat*)format)->parse(src, pp);
b75a7d8f 261
b75a7d8f 262 if(pp.getErrorIndex() == -1)
374ca955 263 *parsePos = pp.getIndex();
b75a7d8f 264 else {
374ca955
A
265 *parsePos = pp.getErrorIndex();
266 *status = U_PARSE_ERROR;
b75a7d8f 267 }
374ca955
A
268
269 return res;
b75a7d8f
A
270}
271
272U_CAPI void U_EXPORT2
273udat_parseCalendar(const UDateFormat* format,
274 UCalendar* calendar,
275 const UChar* text,
276 int32_t textLength,
277 int32_t *parsePos,
278 UErrorCode *status)
279{
374ca955 280 if(U_FAILURE(*status)) return;
b75a7d8f 281
374ca955
A
282 const UnicodeString src((UBool)(textLength == -1), text, textLength);
283 ParsePosition pp;
b75a7d8f 284
374ca955
A
285 if(parsePos != 0)
286 pp.setIndex(*parsePos);
b75a7d8f 287
374ca955 288 ((DateFormat*)format)->parse(src, *(Calendar*)calendar, pp);
b75a7d8f 289
374ca955
A
290 if(parsePos != 0) {
291 if(pp.getErrorIndex() == -1)
292 *parsePos = pp.getIndex();
293 else {
294 *parsePos = pp.getErrorIndex();
295 *status = U_PARSE_ERROR;
296 }
b75a7d8f 297 }
b75a7d8f
A
298}
299
300U_CAPI UBool U_EXPORT2
301udat_isLenient(const UDateFormat* fmt)
302{
374ca955 303 return ((DateFormat*)fmt)->isLenient();
b75a7d8f
A
304}
305
306U_CAPI void U_EXPORT2
307udat_setLenient( UDateFormat* fmt,
308 UBool isLenient)
309{
374ca955 310 ((DateFormat*)fmt)->setLenient(isLenient);
b75a7d8f
A
311}
312
57a6839d
A
313U_DRAFT UBool U_EXPORT2
314udat_getBooleanAttribute(const UDateFormat* fmt,
315 UDateFormatBooleanAttribute attr,
316 UErrorCode* status)
317{
318 if(U_FAILURE(*status)) return FALSE;
319 return ((DateFormat*)fmt)->getBooleanAttribute(attr, *status);
320 //return FALSE;
321}
322
323U_DRAFT void U_EXPORT2
324udat_setBooleanAttribute(UDateFormat *fmt,
325 UDateFormatBooleanAttribute attr,
326 UBool newValue,
327 UErrorCode* status)
328{
329 if(U_FAILURE(*status)) return;
330 ((DateFormat*)fmt)->setBooleanAttribute(attr, newValue, *status);
331}
332
b75a7d8f
A
333U_CAPI const UCalendar* U_EXPORT2
334udat_getCalendar(const UDateFormat* fmt)
335{
374ca955 336 return (const UCalendar*) ((DateFormat*)fmt)->getCalendar();
b75a7d8f
A
337}
338
339U_CAPI void U_EXPORT2
374ca955
A
340udat_setCalendar(UDateFormat* fmt,
341 const UCalendar* calendarToSet)
b75a7d8f 342{
374ca955 343 ((DateFormat*)fmt)->setCalendar(*((Calendar*)calendarToSet));
b75a7d8f
A
344}
345
346U_CAPI const UNumberFormat* U_EXPORT2
347udat_getNumberFormat(const UDateFormat* fmt)
348{
374ca955 349 return (const UNumberFormat*) ((DateFormat*)fmt)->getNumberFormat();
b75a7d8f
A
350}
351
352U_CAPI void U_EXPORT2
374ca955
A
353udat_setNumberFormat(UDateFormat* fmt,
354 const UNumberFormat* numberFormatToSet)
b75a7d8f 355{
374ca955 356 ((DateFormat*)fmt)->setNumberFormat(*((NumberFormat*)numberFormatToSet));
b75a7d8f
A
357}
358
359U_CAPI const char* U_EXPORT2
360udat_getAvailable(int32_t index)
361{
374ca955 362 return uloc_getAvailable(index);
b75a7d8f
A
363}
364
365U_CAPI int32_t U_EXPORT2
366udat_countAvailable()
367{
374ca955 368 return uloc_countAvailable();
b75a7d8f
A
369}
370
371U_CAPI UDate U_EXPORT2
372udat_get2DigitYearStart( const UDateFormat *fmt,
374ca955 373 UErrorCode *status)
b75a7d8f 374{
46f4442e 375 verifyIsSimpleDateFormat(fmt, status);
374ca955
A
376 if(U_FAILURE(*status)) return (UDate)0;
377 return ((SimpleDateFormat*)fmt)->get2DigitYearStart(*status);
b75a7d8f
A
378}
379
380U_CAPI void U_EXPORT2
381udat_set2DigitYearStart( UDateFormat *fmt,
374ca955
A
382 UDate d,
383 UErrorCode *status)
b75a7d8f 384{
46f4442e 385 verifyIsSimpleDateFormat(fmt, status);
374ca955
A
386 if(U_FAILURE(*status)) return;
387 ((SimpleDateFormat*)fmt)->set2DigitYearStart(d, *status);
b75a7d8f
A
388}
389
390U_CAPI int32_t U_EXPORT2
391udat_toPattern( const UDateFormat *fmt,
392 UBool localized,
393 UChar *result,
394 int32_t resultLength,
395 UErrorCode *status)
396{
374ca955 397 if(U_FAILURE(*status)) return -1;
b75a7d8f 398
374ca955
A
399 UnicodeString res;
400 if(!(result==NULL && resultLength==0)) {
401 // NULL destination for pure preflighting: empty dummy string
402 // otherwise, alias the destination buffer
403 res.setTo(result, 0, resultLength);
404 }
b75a7d8f 405
729e4ab9
A
406 const DateFormat *df=reinterpret_cast<const DateFormat *>(fmt);
407 const SimpleDateFormat *sdtfmt=dynamic_cast<const SimpleDateFormat *>(df);
408 const RelativeDateFormat *reldtfmt;
409 if (sdtfmt!=NULL) {
46f4442e 410 if(localized)
729e4ab9 411 sdtfmt->toLocalizedPattern(res, *status);
46f4442e 412 else
729e4ab9
A
413 sdtfmt->toPattern(res);
414 } else if (!localized && (reldtfmt=dynamic_cast<const RelativeDateFormat *>(df))!=NULL) {
415 reldtfmt->toPattern(res, *status);
46f4442e
A
416 } else {
417 *status = U_ILLEGAL_ARGUMENT_ERROR;
418 return -1;
419 }
b75a7d8f 420
374ca955 421 return res.extract(result, resultLength, *status);
b75a7d8f
A
422}
423
729e4ab9
A
424// TODO: should this take an UErrorCode?
425// A: Yes. Of course.
b75a7d8f 426U_CAPI void U_EXPORT2
374ca955 427udat_applyPattern( UDateFormat *format,
b75a7d8f
A
428 UBool localized,
429 const UChar *pattern,
430 int32_t patternLength)
431{
729e4ab9 432 const UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength);
374ca955 433 UErrorCode status = U_ZERO_ERROR;
729e4ab9 434
46f4442e
A
435 verifyIsSimpleDateFormat(format, &status);
436 if(U_FAILURE(status)) {
437 return;
438 }
729e4ab9 439
374ca955
A
440 if(localized)
441 ((SimpleDateFormat*)format)->applyLocalizedPattern(pat, status);
442 else
443 ((SimpleDateFormat*)format)->applyPattern(pat);
b75a7d8f
A
444}
445
446U_CAPI int32_t U_EXPORT2
374ca955
A
447udat_getSymbols(const UDateFormat *fmt,
448 UDateFormatSymbolType type,
449 int32_t index,
450 UChar *result,
451 int32_t resultLength,
452 UErrorCode *status)
b75a7d8f 453{
729e4ab9
A
454 const DateFormatSymbols *syms;
455 const SimpleDateFormat* sdtfmt;
456 const RelativeDateFormat* rdtfmt;
457 if ((sdtfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
51004dcb 458 syms = sdtfmt->getDateFormatSymbols();
729e4ab9 459 } else if ((rdtfmt = dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
51004dcb 460 syms = rdtfmt->getDateFormatSymbols();
729e4ab9
A
461 } else {
462 return -1;
463 }
374ca955 464 int32_t count;
73c04bcf 465 const UnicodeString *res = NULL;
374ca955
A
466
467 switch(type) {
468 case UDAT_ERAS:
469 res = syms->getEras(count);
73c04bcf
A
470 break;
471
472 case UDAT_ERA_NAMES:
473 res = syms->getEraNames(count);
374ca955 474 break;
b75a7d8f 475
374ca955
A
476 case UDAT_MONTHS:
477 res = syms->getMonths(count);
374ca955 478 break;
b75a7d8f 479
374ca955
A
480 case UDAT_SHORT_MONTHS:
481 res = syms->getShortMonths(count);
374ca955 482 break;
b75a7d8f 483
374ca955
A
484 case UDAT_WEEKDAYS:
485 res = syms->getWeekdays(count);
374ca955 486 break;
b75a7d8f 487
374ca955
A
488 case UDAT_SHORT_WEEKDAYS:
489 res = syms->getShortWeekdays(count);
374ca955 490 break;
b75a7d8f 491
374ca955
A
492 case UDAT_AM_PMS:
493 res = syms->getAmPmStrings(count);
374ca955
A
494 break;
495
496 case UDAT_LOCALIZED_CHARS:
497 {
498 UnicodeString res1;
499 if(!(result==NULL && resultLength==0)) {
500 // NULL destination for pure preflighting: empty dummy string
501 // otherwise, alias the destination buffer
502 res1.setTo(result, 0, resultLength);
503 }
504 syms->getLocalPatternChars(res1);
505 return res1.extract(result, resultLength, *status);
506 }
73c04bcf
A
507
508 case UDAT_NARROW_MONTHS:
509 res = syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
510 break;
511
51004dcb
A
512 case UDAT_SHORTER_WEEKDAYS:
513 res = syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::SHORT);
514 break;
515
73c04bcf
A
516 case UDAT_NARROW_WEEKDAYS:
517 res = syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
518 break;
519
520 case UDAT_STANDALONE_MONTHS:
521 res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
522 break;
523
524 case UDAT_STANDALONE_SHORT_MONTHS:
525 res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
526 break;
527
528 case UDAT_STANDALONE_NARROW_MONTHS:
529 res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
530 break;
531
532 case UDAT_STANDALONE_WEEKDAYS:
533 res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
534 break;
535
536 case UDAT_STANDALONE_SHORT_WEEKDAYS:
537 res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
538 break;
539
51004dcb
A
540 case UDAT_STANDALONE_SHORTER_WEEKDAYS:
541 res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::SHORT);
542 break;
543
73c04bcf
A
544 case UDAT_STANDALONE_NARROW_WEEKDAYS:
545 res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
546 break;
547
548 case UDAT_QUARTERS:
549 res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
550 break;
551
552 case UDAT_SHORT_QUARTERS:
553 res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
554 break;
555
556 case UDAT_STANDALONE_QUARTERS:
557 res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
558 break;
559
560 case UDAT_STANDALONE_SHORT_QUARTERS:
561 res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
562 break;
563
57a6839d
A
564 case UADAT_CYCLIC_ZODIAC_NAMES:
565 res = syms->getZodiacNames(count);
566 index = (index > 0)? (index - 1) % 12: 0;
567 break;
568
b75a7d8f 569 }
b75a7d8f 570
73c04bcf
A
571 if(index < count) {
572 return res[index].extract(result, resultLength, *status);
573 }
374ca955 574 return 0;
b75a7d8f
A
575}
576
729e4ab9 577// TODO: also needs an errorCode.
b75a7d8f
A
578U_CAPI int32_t U_EXPORT2
579udat_countSymbols( const UDateFormat *fmt,
580 UDateFormatSymbolType type)
581{
729e4ab9
A
582 const DateFormatSymbols *syms;
583 const SimpleDateFormat* sdtfmt;
584 const RelativeDateFormat* rdtfmt;
585 if ((sdtfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
51004dcb 586 syms = sdtfmt->getDateFormatSymbols();
729e4ab9 587 } else if ((rdtfmt = dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
51004dcb 588 syms = rdtfmt->getDateFormatSymbols();
729e4ab9 589 } else {
46f4442e
A
590 return 0;
591 }
374ca955
A
592 int32_t count = 0;
593
594 switch(type) {
595 case UDAT_ERAS:
596 syms->getEras(count);
597 break;
598
599 case UDAT_MONTHS:
600 syms->getMonths(count);
601 break;
602
603 case UDAT_SHORT_MONTHS:
604 syms->getShortMonths(count);
605 break;
606
607 case UDAT_WEEKDAYS:
608 syms->getWeekdays(count);
609 break;
610
611 case UDAT_SHORT_WEEKDAYS:
612 syms->getShortWeekdays(count);
613 break;
614
615 case UDAT_AM_PMS:
616 syms->getAmPmStrings(count);
617 break;
618
619 case UDAT_LOCALIZED_CHARS:
620 count = 1;
621 break;
73c04bcf
A
622
623 case UDAT_ERA_NAMES:
624 syms->getEraNames(count);
625 break;
626
627 case UDAT_NARROW_MONTHS:
628 syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
629 break;
630
51004dcb
A
631 case UDAT_SHORTER_WEEKDAYS:
632 syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::SHORT);
633 break;
634
73c04bcf
A
635 case UDAT_NARROW_WEEKDAYS:
636 syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
637 break;
638
639 case UDAT_STANDALONE_MONTHS:
640 syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
641 break;
642
643 case UDAT_STANDALONE_SHORT_MONTHS:
644 syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
645 break;
646
647 case UDAT_STANDALONE_NARROW_MONTHS:
648 syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
649 break;
650
651 case UDAT_STANDALONE_WEEKDAYS:
652 syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
653 break;
654
655 case UDAT_STANDALONE_SHORT_WEEKDAYS:
656 syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
657 break;
658
51004dcb
A
659 case UDAT_STANDALONE_SHORTER_WEEKDAYS:
660 syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::SHORT);
661 break;
662
73c04bcf
A
663 case UDAT_STANDALONE_NARROW_WEEKDAYS:
664 syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
665 break;
666
667 case UDAT_QUARTERS:
668 syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
669 break;
670
671 case UDAT_SHORT_QUARTERS:
672 syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
673 break;
674
675 case UDAT_STANDALONE_QUARTERS:
676 syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
677 break;
678
679 case UDAT_STANDALONE_SHORT_QUARTERS:
680 syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
681 break;
682
57a6839d
A
683 case UADAT_CYCLIC_ZODIAC_NAMES:
684 syms->getZodiacNames(count);
685 break;
686 }
b75a7d8f 687
374ca955 688 return count;
b75a7d8f
A
689}
690
691U_NAMESPACE_BEGIN
692
693/*
694 * This DateFormatSymbolsSingleSetter class is a friend of DateFormatSymbols
695 * solely for the purpose of avoiding to clone the array of strings
696 * just to modify one of them and then setting all of them back.
697 * For example, the old code looked like this:
698 * case UDAT_MONTHS:
699 * res = syms->getMonths(count);
700 * array = new UnicodeString[count];
701 * if(array == 0) {
702 * *status = U_MEMORY_ALLOCATION_ERROR;
703 * return;
704 * }
705 * uprv_arrayCopy(res, array, count);
706 * if(index < count)
707 * array[index] = val;
708 * syms->setMonths(array, count);
709 * break;
710 *
711 * Even worse, the old code actually cloned the entire DateFormatSymbols object,
712 * cloned one value array, changed one value, and then made the SimpleDateFormat
713 * replace its DateFormatSymbols object with the new one.
714 *
715 * markus 2002-oct-14
716 */
717class DateFormatSymbolsSingleSetter /* not : public UObject because all methods are static */ {
718public:
374ca955
A
719 static void
720 setSymbol(UnicodeString *array, int32_t count, int32_t index,
721 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
722 {
723 if(array!=NULL) {
724 if(index>=count) {
725 errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
726 } else if(value==NULL) {
727 errorCode=U_ILLEGAL_ARGUMENT_ERROR;
728 } else {
729 array[index].setTo(value, valueLength);
730 }
731 }
732 }
733
734 static void
735 setEra(DateFormatSymbols *syms, int32_t index,
736 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
737 {
738 setSymbol(syms->fEras, syms->fErasCount, index, value, valueLength, errorCode);
739 }
740
73c04bcf
A
741 static void
742 setEraName(DateFormatSymbols *syms, int32_t index,
743 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
744 {
745 setSymbol(syms->fEraNames, syms->fEraNamesCount, index, value, valueLength, errorCode);
746 }
747
374ca955
A
748 static void
749 setMonth(DateFormatSymbols *syms, int32_t index,
750 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
751 {
752 setSymbol(syms->fMonths, syms->fMonthsCount, index, value, valueLength, errorCode);
753 }
754
755 static void
756 setShortMonth(DateFormatSymbols *syms, int32_t index,
757 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
758 {
759 setSymbol(syms->fShortMonths, syms->fShortMonthsCount, index, value, valueLength, errorCode);
760 }
761
73c04bcf
A
762 static void
763 setNarrowMonth(DateFormatSymbols *syms, int32_t index,
764 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
765 {
766 setSymbol(syms->fNarrowMonths, syms->fNarrowMonthsCount, index, value, valueLength, errorCode);
767 }
768
769 static void
770 setStandaloneMonth(DateFormatSymbols *syms, int32_t index,
771 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
772 {
773 setSymbol(syms->fStandaloneMonths, syms->fStandaloneMonthsCount, index, value, valueLength, errorCode);
774 }
775
776 static void
777 setStandaloneShortMonth(DateFormatSymbols *syms, int32_t index,
778 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
779 {
780 setSymbol(syms->fStandaloneShortMonths, syms->fStandaloneShortMonthsCount, index, value, valueLength, errorCode);
781 }
782
783 static void
784 setStandaloneNarrowMonth(DateFormatSymbols *syms, int32_t index,
785 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
786 {
787 setSymbol(syms->fStandaloneNarrowMonths, syms->fStandaloneNarrowMonthsCount, index, value, valueLength, errorCode);
788 }
789
374ca955
A
790 static void
791 setWeekday(DateFormatSymbols *syms, int32_t index,
792 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
793 {
794 setSymbol(syms->fWeekdays, syms->fWeekdaysCount, index, value, valueLength, errorCode);
795 }
796
797 static void
798 setShortWeekday(DateFormatSymbols *syms, int32_t index,
799 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
800 {
801 setSymbol(syms->fShortWeekdays, syms->fShortWeekdaysCount, index, value, valueLength, errorCode);
802 }
803
51004dcb
A
804 static void
805 setShorterWeekday(DateFormatSymbols *syms, int32_t index,
806 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
807 {
808 setSymbol(syms->fShorterWeekdays, syms->fShorterWeekdaysCount, index, value, valueLength, errorCode);
809 }
810
73c04bcf
A
811 static void
812 setNarrowWeekday(DateFormatSymbols *syms, int32_t index,
813 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
814 {
815 setSymbol(syms->fNarrowWeekdays, syms->fNarrowWeekdaysCount, index, value, valueLength, errorCode);
816 }
817
818 static void
819 setStandaloneWeekday(DateFormatSymbols *syms, int32_t index,
820 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
821 {
822 setSymbol(syms->fStandaloneWeekdays, syms->fStandaloneWeekdaysCount, index, value, valueLength, errorCode);
823 }
824
825 static void
826 setStandaloneShortWeekday(DateFormatSymbols *syms, int32_t index,
827 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
828 {
829 setSymbol(syms->fStandaloneShortWeekdays, syms->fStandaloneShortWeekdaysCount, index, value, valueLength, errorCode);
830 }
831
51004dcb
A
832 static void
833 setStandaloneShorterWeekday(DateFormatSymbols *syms, int32_t index,
834 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
835 {
836 setSymbol(syms->fStandaloneShorterWeekdays, syms->fStandaloneShorterWeekdaysCount, index, value, valueLength, errorCode);
837 }
838
73c04bcf
A
839 static void
840 setStandaloneNarrowWeekday(DateFormatSymbols *syms, int32_t index,
841 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
842 {
843 setSymbol(syms->fStandaloneNarrowWeekdays, syms->fStandaloneNarrowWeekdaysCount, index, value, valueLength, errorCode);
844 }
845
846 static void
847 setQuarter(DateFormatSymbols *syms, int32_t index,
848 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
849 {
850 setSymbol(syms->fQuarters, syms->fQuartersCount, index, value, valueLength, errorCode);
851 }
852
853 static void
854 setShortQuarter(DateFormatSymbols *syms, int32_t index,
855 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
856 {
857 setSymbol(syms->fShortQuarters, syms->fShortQuartersCount, index, value, valueLength, errorCode);
858 }
859
860 static void
861 setStandaloneQuarter(DateFormatSymbols *syms, int32_t index,
862 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
863 {
864 setSymbol(syms->fStandaloneQuarters, syms->fStandaloneQuartersCount, index, value, valueLength, errorCode);
865 }
866
867 static void
868 setStandaloneShortQuarter(DateFormatSymbols *syms, int32_t index,
869 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
870 {
871 setSymbol(syms->fStandaloneShortQuarters, syms->fStandaloneShortQuartersCount, index, value, valueLength, errorCode);
872 }
873
374ca955
A
874 static void
875 setAmPm(DateFormatSymbols *syms, int32_t index,
876 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
877 {
878 setSymbol(syms->fAmPms, syms->fAmPmsCount, index, value, valueLength, errorCode);
879 }
880
881 static void
882 setLocalPatternChars(DateFormatSymbols *syms,
883 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
884 {
885 setSymbol(&syms->fLocalPatternChars, 1, 0, value, valueLength, errorCode);
b75a7d8f 886 }
b75a7d8f
A
887};
888
889U_NAMESPACE_END
890
891U_CAPI void U_EXPORT2
892udat_setSymbols( UDateFormat *format,
893 UDateFormatSymbolType type,
894 int32_t index,
895 UChar *value,
896 int32_t valueLength,
897 UErrorCode *status)
898{
46f4442e 899 verifyIsSimpleDateFormat(format, status);
374ca955 900 if(U_FAILURE(*status)) return;
b75a7d8f 901
374ca955 902 DateFormatSymbols *syms = (DateFormatSymbols *)((SimpleDateFormat *)format)->getDateFormatSymbols();
b75a7d8f 903
374ca955
A
904 switch(type) {
905 case UDAT_ERAS:
906 DateFormatSymbolsSingleSetter::setEra(syms, index, value, valueLength, *status);
907 break;
b75a7d8f 908
73c04bcf
A
909 case UDAT_ERA_NAMES:
910 DateFormatSymbolsSingleSetter::setEraName(syms, index, value, valueLength, *status);
911 break;
912
374ca955
A
913 case UDAT_MONTHS:
914 DateFormatSymbolsSingleSetter::setMonth(syms, index, value, valueLength, *status);
915 break;
b75a7d8f 916
374ca955
A
917 case UDAT_SHORT_MONTHS:
918 DateFormatSymbolsSingleSetter::setShortMonth(syms, index, value, valueLength, *status);
919 break;
b75a7d8f 920
73c04bcf
A
921 case UDAT_NARROW_MONTHS:
922 DateFormatSymbolsSingleSetter::setNarrowMonth(syms, index, value, valueLength, *status);
923 break;
924
925 case UDAT_STANDALONE_MONTHS:
926 DateFormatSymbolsSingleSetter::setStandaloneMonth(syms, index, value, valueLength, *status);
927 break;
928
929 case UDAT_STANDALONE_SHORT_MONTHS:
930 DateFormatSymbolsSingleSetter::setStandaloneShortMonth(syms, index, value, valueLength, *status);
931 break;
932
933 case UDAT_STANDALONE_NARROW_MONTHS:
934 DateFormatSymbolsSingleSetter::setStandaloneNarrowMonth(syms, index, value, valueLength, *status);
935 break;
936
374ca955
A
937 case UDAT_WEEKDAYS:
938 DateFormatSymbolsSingleSetter::setWeekday(syms, index, value, valueLength, *status);
939 break;
b75a7d8f 940
374ca955
A
941 case UDAT_SHORT_WEEKDAYS:
942 DateFormatSymbolsSingleSetter::setShortWeekday(syms, index, value, valueLength, *status);
943 break;
b75a7d8f 944
51004dcb
A
945 case UDAT_SHORTER_WEEKDAYS:
946 DateFormatSymbolsSingleSetter::setShorterWeekday(syms, index, value, valueLength, *status);
947 break;
948
73c04bcf
A
949 case UDAT_NARROW_WEEKDAYS:
950 DateFormatSymbolsSingleSetter::setNarrowWeekday(syms, index, value, valueLength, *status);
951 break;
952
953 case UDAT_STANDALONE_WEEKDAYS:
954 DateFormatSymbolsSingleSetter::setStandaloneWeekday(syms, index, value, valueLength, *status);
955 break;
956
957 case UDAT_STANDALONE_SHORT_WEEKDAYS:
958 DateFormatSymbolsSingleSetter::setStandaloneShortWeekday(syms, index, value, valueLength, *status);
959 break;
960
51004dcb
A
961 case UDAT_STANDALONE_SHORTER_WEEKDAYS:
962 DateFormatSymbolsSingleSetter::setStandaloneShorterWeekday(syms, index, value, valueLength, *status);
963 break;
964
73c04bcf
A
965 case UDAT_STANDALONE_NARROW_WEEKDAYS:
966 DateFormatSymbolsSingleSetter::setStandaloneNarrowWeekday(syms, index, value, valueLength, *status);
967 break;
968
969 case UDAT_QUARTERS:
970 DateFormatSymbolsSingleSetter::setQuarter(syms, index, value, valueLength, *status);
971 break;
972
973 case UDAT_SHORT_QUARTERS:
974 DateFormatSymbolsSingleSetter::setShortQuarter(syms, index, value, valueLength, *status);
975 break;
976
977 case UDAT_STANDALONE_QUARTERS:
978 DateFormatSymbolsSingleSetter::setStandaloneQuarter(syms, index, value, valueLength, *status);
979 break;
980
981 case UDAT_STANDALONE_SHORT_QUARTERS:
982 DateFormatSymbolsSingleSetter::setStandaloneShortQuarter(syms, index, value, valueLength, *status);
983 break;
984
374ca955
A
985 case UDAT_AM_PMS:
986 DateFormatSymbolsSingleSetter::setAmPm(syms, index, value, valueLength, *status);
987 break;
b75a7d8f 988
374ca955
A
989 case UDAT_LOCALIZED_CHARS:
990 DateFormatSymbolsSingleSetter::setLocalPatternChars(syms, value, valueLength, *status);
991 break;
73c04bcf
A
992
993 default:
994 *status = U_UNSUPPORTED_ERROR;
995 break;
996
374ca955 997 }
b75a7d8f
A
998}
999
374ca955
A
1000U_CAPI const char* U_EXPORT2
1001udat_getLocaleByType(const UDateFormat *fmt,
1002 ULocDataLocaleType type,
1003 UErrorCode* status)
1004{
1005 if (fmt == NULL) {
1006 if (U_SUCCESS(*status)) {
1007 *status = U_ILLEGAL_ARGUMENT_ERROR;
1008 }
1009 return NULL;
1010 }
1011 return ((Format*)fmt)->getLocaleID(type, *status);
1012}
46f4442e 1013
4388f060 1014U_CAPI void U_EXPORT2
51004dcb 1015udat_setContext(UDateFormat* fmt, UDisplayContext value, UErrorCode* status)
4388f060 1016{
4388f060
A
1017 if (U_FAILURE(*status)) {
1018 return;
1019 }
57a6839d
A
1020 ((DateFormat*)fmt)->setContext(value, *status);
1021 return;
4388f060
A
1022}
1023
51004dcb 1024U_CAPI UDisplayContext U_EXPORT2
57a6839d 1025udat_getContext(const UDateFormat* fmt, UDisplayContextType type, UErrorCode* status)
4388f060 1026{
4388f060 1027 if (U_FAILURE(*status)) {
51004dcb 1028 return (UDisplayContext)0;
4388f060 1029 }
57a6839d 1030 return ((const DateFormat*)fmt)->getContext(type, *status);
4388f060
A
1031}
1032
1033
46f4442e
A
1034/**
1035 * Verify that fmt is a RelativeDateFormat. Invalid error if not.
1036 * @param fmt the UDateFormat, definitely a DateFormat, maybe something else
1037 * @param status error code, will be set to failure if there is a familure or the fmt is NULL.
1038 */
1039static void verifyIsRelativeDateFormat(const UDateFormat* fmt, UErrorCode *status) {
729e4ab9
A
1040 if(U_SUCCESS(*status) &&
1041 dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))==NULL) {
46f4442e
A
1042 *status = U_ILLEGAL_ARGUMENT_ERROR;
1043 }
1044}
1045
1046
1047U_CAPI int32_t U_EXPORT2
1048udat_toPatternRelativeDate(const UDateFormat *fmt,
1049 UChar *result,
1050 int32_t resultLength,
1051 UErrorCode *status)
1052{
1053 verifyIsRelativeDateFormat(fmt, status);
1054 if(U_FAILURE(*status)) return -1;
1055
1056 UnicodeString datePattern;
1057 if(!(result==NULL && resultLength==0)) {
1058 // NULL destination for pure preflighting: empty dummy string
1059 // otherwise, alias the destination buffer
1060 datePattern.setTo(result, 0, resultLength);
1061 }
1062 ((RelativeDateFormat*)fmt)->toPatternDate(datePattern, *status);
1063 return datePattern.extract(result, resultLength, *status);
1064}
1065
1066U_CAPI int32_t U_EXPORT2
1067udat_toPatternRelativeTime(const UDateFormat *fmt,
1068 UChar *result,
1069 int32_t resultLength,
1070 UErrorCode *status)
1071{
1072 verifyIsRelativeDateFormat(fmt, status);
1073 if(U_FAILURE(*status)) return -1;
1074
1075 UnicodeString timePattern;
1076 if(!(result==NULL && resultLength==0)) {
1077 // NULL destination for pure preflighting: empty dummy string
1078 // otherwise, alias the destination buffer
1079 timePattern.setTo(result, 0, resultLength);
1080 }
1081 ((RelativeDateFormat*)fmt)->toPatternTime(timePattern, *status);
1082 return timePattern.extract(result, resultLength, *status);
1083}
1084
1085U_CAPI void U_EXPORT2
1086udat_applyPatternRelative(UDateFormat *format,
1087 const UChar *datePattern,
1088 int32_t datePatternLength,
1089 const UChar *timePattern,
1090 int32_t timePatternLength,
1091 UErrorCode *status)
1092{
1093 verifyIsRelativeDateFormat(format, status);
1094 if(U_FAILURE(*status)) return;
1095 const UnicodeString datePat((UBool)(datePatternLength == -1), datePattern, datePatternLength);
1096 const UnicodeString timePat((UBool)(timePatternLength == -1), timePattern, timePatternLength);
1097 ((RelativeDateFormat*)format)->applyPatterns(datePat, timePat, *status);
1098}
1099
b75a7d8f 1100#endif /* #if !UCONFIG_NO_FORMATTING */