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