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