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