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