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