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