Home | History | Annotate | Download | only in i18n
      1 /*
      2 *******************************************************************************
      3 *   Copyright (C) 1996-2010, 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  */
     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
     81 udat_toCalendarDateField(UDateFormatField field) {
     82   return gDateFieldMapping[field];
     83 }
     84 
     85 U_CAPI UDateFormat* U_EXPORT2
     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
    141 udat_close(UDateFormat* format)
    142 {
    143     delete (DateFormat*)format;
    144 }
    145 
    146 U_CAPI UDateFormat* U_EXPORT2
    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
    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
    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
    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
    255 udat_isLenient(const UDateFormat* fmt)
    256 {
    257     return ((DateFormat*)fmt)->isLenient();
    258 }
    259 
    260 U_CAPI void U_EXPORT2
    261 udat_setLenient(    UDateFormat*    fmt,
    262             UBool          isLenient)
    263 {
    264     ((DateFormat*)fmt)->setLenient(isLenient);
    265 }
    266 
    267 U_CAPI const UCalendar* U_EXPORT2
    268 udat_getCalendar(const UDateFormat* fmt)
    269 {
    270     return (const UCalendar*) ((DateFormat*)fmt)->getCalendar();
    271 }
    272 
    273 U_CAPI void U_EXPORT2
    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
    281 udat_getNumberFormat(const UDateFormat* fmt)
    282 {
    283     return (const UNumberFormat*) ((DateFormat*)fmt)->getNumberFormat();
    284 }
    285 
    286 U_CAPI void U_EXPORT2
    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
    294 udat_getAvailable(int32_t index)
    295 {
    296     return uloc_getAvailable(index);
    297 }
    298 
    299 U_CAPI int32_t U_EXPORT2
    300 udat_countAvailable()
    301 {
    302     return uloc_countAvailable();
    303 }
    304 
    305 U_CAPI UDate U_EXPORT2
    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
    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
    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
    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
    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     verifyIsSimpleDateFormat(fmt, status);
    389     if(U_FAILURE(*status)) return -1;
    390 
    391     const DateFormatSymbols *syms =
    392         ((SimpleDateFormat*)fmt)->getDateFormatSymbols();
    393     int32_t count;
    394     const UnicodeString *res = NULL;
    395 
    396     switch(type) {
    397     case UDAT_ERAS:
    398         res = syms->getEras(count);
    399         break;
    400 
    401     case UDAT_ERA_NAMES:
    402         res = syms->getEraNames(count);
    403         break;
    404 
    405     case UDAT_MONTHS:
    406         res = syms->getMonths(count);
    407         break;
    408 
    409     case UDAT_SHORT_MONTHS:
    410         res = syms->getShortMonths(count);
    411         break;
    412 
    413     case UDAT_WEEKDAYS:
    414         res = syms->getWeekdays(count);
    415         break;
    416 
    417     case UDAT_SHORT_WEEKDAYS:
    418         res = syms->getShortWeekdays(count);
    419         break;
    420 
    421     case UDAT_AM_PMS:
    422         res = syms->getAmPmStrings(count);
    423         break;
    424 
    425     case UDAT_LOCALIZED_CHARS:
    426         {
    427             UnicodeString res1;
    428             if(!(result==NULL && resultLength==0)) {
    429                 // NULL destination for pure preflighting: empty dummy string
    430                 // otherwise, alias the destination buffer
    431                 res1.setTo(result, 0, resultLength);
    432             }
    433             syms->getLocalPatternChars(res1);
    434             return res1.extract(result, resultLength, *status);
    435         }
    436 
    437     case UDAT_NARROW_MONTHS:
    438         res = syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    439         break;
    440 
    441     case UDAT_NARROW_WEEKDAYS:
    442         res = syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    443         break;
    444 
    445     case UDAT_STANDALONE_MONTHS:
    446         res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    447         break;
    448 
    449     case UDAT_STANDALONE_SHORT_MONTHS:
    450         res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    451         break;
    452 
    453     case UDAT_STANDALONE_NARROW_MONTHS:
    454         res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    455         break;
    456 
    457     case UDAT_STANDALONE_WEEKDAYS:
    458         res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    459         break;
    460 
    461     case UDAT_STANDALONE_SHORT_WEEKDAYS:
    462         res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    463         break;
    464 
    465     case UDAT_STANDALONE_NARROW_WEEKDAYS:
    466         res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    467         break;
    468 
    469     case UDAT_QUARTERS:
    470         res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
    471         break;
    472 
    473     case UDAT_SHORT_QUARTERS:
    474         res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
    475         break;
    476 
    477     case UDAT_STANDALONE_QUARTERS:
    478         res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    479         break;
    480 
    481     case UDAT_STANDALONE_SHORT_QUARTERS:
    482         res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    483         break;
    484 
    485     }
    486 
    487     if(index < count) {
    488         return res[index].extract(result, resultLength, *status);
    489     }
    490     return 0;
    491 }
    492 
    493 // TODO: also needs an errorCode.
    494 U_CAPI int32_t U_EXPORT2
    495 udat_countSymbols(    const    UDateFormat                *fmt,
    496             UDateFormatSymbolType    type)
    497 {
    498     UErrorCode status = U_ZERO_ERROR;
    499 
    500     verifyIsSimpleDateFormat(fmt, &status);
    501     if(U_FAILURE(status)) {
    502         return 0;
    503     }
    504 
    505     const DateFormatSymbols *syms =
    506         ((SimpleDateFormat*)fmt)->getDateFormatSymbols();
    507     int32_t count = 0;
    508 
    509     switch(type) {
    510     case UDAT_ERAS:
    511         syms->getEras(count);
    512         break;
    513 
    514     case UDAT_MONTHS:
    515         syms->getMonths(count);
    516         break;
    517 
    518     case UDAT_SHORT_MONTHS:
    519         syms->getShortMonths(count);
    520         break;
    521 
    522     case UDAT_WEEKDAYS:
    523         syms->getWeekdays(count);
    524         break;
    525 
    526     case UDAT_SHORT_WEEKDAYS:
    527         syms->getShortWeekdays(count);
    528         break;
    529 
    530     case UDAT_AM_PMS:
    531         syms->getAmPmStrings(count);
    532         break;
    533 
    534     case UDAT_LOCALIZED_CHARS:
    535         count = 1;
    536         break;
    537 
    538     case UDAT_ERA_NAMES:
    539         syms->getEraNames(count);
    540         break;
    541 
    542     case UDAT_NARROW_MONTHS:
    543         syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    544         break;
    545 
    546     case UDAT_NARROW_WEEKDAYS:
    547         syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    548         break;
    549 
    550     case UDAT_STANDALONE_MONTHS:
    551         syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    552         break;
    553 
    554     case UDAT_STANDALONE_SHORT_MONTHS:
    555         syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    556         break;
    557 
    558     case UDAT_STANDALONE_NARROW_MONTHS:
    559         syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    560         break;
    561 
    562     case UDAT_STANDALONE_WEEKDAYS:
    563         syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    564         break;
    565 
    566     case UDAT_STANDALONE_SHORT_WEEKDAYS:
    567         syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    568         break;
    569 
    570     case UDAT_STANDALONE_NARROW_WEEKDAYS:
    571         syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    572         break;
    573 
    574     case UDAT_QUARTERS:
    575         syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
    576         break;
    577 
    578     case UDAT_SHORT_QUARTERS:
    579         syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
    580         break;
    581 
    582     case UDAT_STANDALONE_QUARTERS:
    583         syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    584         break;
    585 
    586     case UDAT_STANDALONE_SHORT_QUARTERS:
    587         syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    588         break;
    589 
    590     }
    591 
    592     return count;
    593 }
    594 
    595 U_NAMESPACE_BEGIN
    596 
    597 /*
    598  * This DateFormatSymbolsSingleSetter class is a friend of DateFormatSymbols
    599  * solely for the purpose of avoiding to clone the array of strings
    600  * just to modify one of them and then setting all of them back.
    601  * For example, the old code looked like this:
    602  *  case UDAT_MONTHS:
    603  *    res = syms->getMonths(count);
    604  *    array = new UnicodeString[count];
    605  *    if(array == 0) {
    606  *      *status = U_MEMORY_ALLOCATION_ERROR;
    607  *      return;
    608  *    }
    609  *    uprv_arrayCopy(res, array, count);
    610  *    if(index < count)
    611  *      array[index] = val;
    612  *    syms->setMonths(array, count);
    613  *    break;
    614  *
    615  * Even worse, the old code actually cloned the entire DateFormatSymbols object,
    616  * cloned one value array, changed one value, and then made the SimpleDateFormat
    617  * replace its DateFormatSymbols object with the new one.
    618  *
    619  * markus 2002-oct-14
    620  */
    621 class DateFormatSymbolsSingleSetter /* not : public UObject because all methods are static */ {
    622 public:
    623     static void
    624         setSymbol(UnicodeString *array, int32_t count, int32_t index,
    625         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    626     {
    627         if(array!=NULL) {
    628             if(index>=count) {
    629                 errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
    630             } else if(value==NULL) {
    631                 errorCode=U_ILLEGAL_ARGUMENT_ERROR;
    632             } else {
    633                 array[index].setTo(value, valueLength);
    634             }
    635         }
    636     }
    637 
    638     static void
    639         setEra(DateFormatSymbols *syms, int32_t index,
    640         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    641     {
    642         setSymbol(syms->fEras, syms->fErasCount, index, value, valueLength, errorCode);
    643     }
    644 
    645     static void
    646         setEraName(DateFormatSymbols *syms, int32_t index,
    647         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    648     {
    649         setSymbol(syms->fEraNames, syms->fEraNamesCount, index, value, valueLength, errorCode);
    650     }
    651 
    652     static void
    653         setMonth(DateFormatSymbols *syms, int32_t index,
    654         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    655     {
    656         setSymbol(syms->fMonths, syms->fMonthsCount, index, value, valueLength, errorCode);
    657     }
    658 
    659     static void
    660         setShortMonth(DateFormatSymbols *syms, int32_t index,
    661         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    662     {
    663         setSymbol(syms->fShortMonths, syms->fShortMonthsCount, index, value, valueLength, errorCode);
    664     }
    665 
    666     static void
    667         setNarrowMonth(DateFormatSymbols *syms, int32_t index,
    668         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    669     {
    670         setSymbol(syms->fNarrowMonths, syms->fNarrowMonthsCount, index, value, valueLength, errorCode);
    671     }
    672 
    673     static void
    674         setStandaloneMonth(DateFormatSymbols *syms, int32_t index,
    675         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    676     {
    677         setSymbol(syms->fStandaloneMonths, syms->fStandaloneMonthsCount, index, value, valueLength, errorCode);
    678     }
    679 
    680     static void
    681         setStandaloneShortMonth(DateFormatSymbols *syms, int32_t index,
    682         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    683     {
    684         setSymbol(syms->fStandaloneShortMonths, syms->fStandaloneShortMonthsCount, index, value, valueLength, errorCode);
    685     }
    686 
    687     static void
    688         setStandaloneNarrowMonth(DateFormatSymbols *syms, int32_t index,
    689         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    690     {
    691         setSymbol(syms->fStandaloneNarrowMonths, syms->fStandaloneNarrowMonthsCount, index, value, valueLength, errorCode);
    692     }
    693 
    694     static void
    695         setWeekday(DateFormatSymbols *syms, int32_t index,
    696         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    697     {
    698         setSymbol(syms->fWeekdays, syms->fWeekdaysCount, index, value, valueLength, errorCode);
    699     }
    700 
    701     static void
    702         setShortWeekday(DateFormatSymbols *syms, int32_t index,
    703         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    704     {
    705         setSymbol(syms->fShortWeekdays, syms->fShortWeekdaysCount, index, value, valueLength, errorCode);
    706     }
    707 
    708     static void
    709         setNarrowWeekday(DateFormatSymbols *syms, int32_t index,
    710         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    711     {
    712         setSymbol(syms->fNarrowWeekdays, syms->fNarrowWeekdaysCount, index, value, valueLength, errorCode);
    713     }
    714 
    715     static void
    716         setStandaloneWeekday(DateFormatSymbols *syms, int32_t index,
    717         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    718     {
    719         setSymbol(syms->fStandaloneWeekdays, syms->fStandaloneWeekdaysCount, index, value, valueLength, errorCode);
    720     }
    721 
    722     static void
    723         setStandaloneShortWeekday(DateFormatSymbols *syms, int32_t index,
    724         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    725     {
    726         setSymbol(syms->fStandaloneShortWeekdays, syms->fStandaloneShortWeekdaysCount, index, value, valueLength, errorCode);
    727     }
    728 
    729     static void
    730         setStandaloneNarrowWeekday(DateFormatSymbols *syms, int32_t index,
    731         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    732     {
    733         setSymbol(syms->fStandaloneNarrowWeekdays, syms->fStandaloneNarrowWeekdaysCount, index, value, valueLength, errorCode);
    734     }
    735 
    736     static void
    737         setQuarter(DateFormatSymbols *syms, int32_t index,
    738         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    739     {
    740         setSymbol(syms->fQuarters, syms->fQuartersCount, index, value, valueLength, errorCode);
    741     }
    742 
    743     static void
    744         setShortQuarter(DateFormatSymbols *syms, int32_t index,
    745         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    746     {
    747         setSymbol(syms->fShortQuarters, syms->fShortQuartersCount, index, value, valueLength, errorCode);
    748     }
    749 
    750     static void
    751         setStandaloneQuarter(DateFormatSymbols *syms, int32_t index,
    752         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    753     {
    754         setSymbol(syms->fStandaloneQuarters, syms->fStandaloneQuartersCount, index, value, valueLength, errorCode);
    755     }
    756 
    757     static void
    758         setStandaloneShortQuarter(DateFormatSymbols *syms, int32_t index,
    759         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    760     {
    761         setSymbol(syms->fStandaloneShortQuarters, syms->fStandaloneShortQuartersCount, index, value, valueLength, errorCode);
    762     }
    763 
    764     static void
    765         setAmPm(DateFormatSymbols *syms, int32_t index,
    766         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    767     {
    768         setSymbol(syms->fAmPms, syms->fAmPmsCount, index, value, valueLength, errorCode);
    769     }
    770 
    771     static void
    772         setLocalPatternChars(DateFormatSymbols *syms,
    773         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    774     {
    775         setSymbol(&syms->fLocalPatternChars, 1, 0, value, valueLength, errorCode);
    776     }
    777 };
    778 
    779 U_NAMESPACE_END
    780 
    781 U_CAPI void U_EXPORT2
    782 udat_setSymbols(    UDateFormat             *format,
    783             UDateFormatSymbolType   type,
    784             int32_t                 index,
    785             UChar                   *value,
    786             int32_t                 valueLength,
    787             UErrorCode              *status)
    788 {
    789     verifyIsSimpleDateFormat(format, status);
    790     if(U_FAILURE(*status)) return;
    791 
    792     DateFormatSymbols *syms = (DateFormatSymbols *)((SimpleDateFormat *)format)->getDateFormatSymbols();
    793 
    794     switch(type) {
    795     case UDAT_ERAS:
    796         DateFormatSymbolsSingleSetter::setEra(syms, index, value, valueLength, *status);
    797         break;
    798 
    799     case UDAT_ERA_NAMES:
    800         DateFormatSymbolsSingleSetter::setEraName(syms, index, value, valueLength, *status);
    801         break;
    802 
    803     case UDAT_MONTHS:
    804         DateFormatSymbolsSingleSetter::setMonth(syms, index, value, valueLength, *status);
    805         break;
    806 
    807     case UDAT_SHORT_MONTHS:
    808         DateFormatSymbolsSingleSetter::setShortMonth(syms, index, value, valueLength, *status);
    809         break;
    810 
    811     case UDAT_NARROW_MONTHS:
    812         DateFormatSymbolsSingleSetter::setNarrowMonth(syms, index, value, valueLength, *status);
    813         break;
    814 
    815     case UDAT_STANDALONE_MONTHS:
    816         DateFormatSymbolsSingleSetter::setStandaloneMonth(syms, index, value, valueLength, *status);
    817         break;
    818 
    819     case UDAT_STANDALONE_SHORT_MONTHS:
    820         DateFormatSymbolsSingleSetter::setStandaloneShortMonth(syms, index, value, valueLength, *status);
    821         break;
    822 
    823     case UDAT_STANDALONE_NARROW_MONTHS:
    824         DateFormatSymbolsSingleSetter::setStandaloneNarrowMonth(syms, index, value, valueLength, *status);
    825         break;
    826 
    827     case UDAT_WEEKDAYS:
    828         DateFormatSymbolsSingleSetter::setWeekday(syms, index, value, valueLength, *status);
    829         break;
    830 
    831     case UDAT_SHORT_WEEKDAYS:
    832         DateFormatSymbolsSingleSetter::setShortWeekday(syms, index, value, valueLength, *status);
    833         break;
    834 
    835     case UDAT_NARROW_WEEKDAYS:
    836         DateFormatSymbolsSingleSetter::setNarrowWeekday(syms, index, value, valueLength, *status);
    837         break;
    838 
    839     case UDAT_STANDALONE_WEEKDAYS:
    840         DateFormatSymbolsSingleSetter::setStandaloneWeekday(syms, index, value, valueLength, *status);
    841         break;
    842 
    843     case UDAT_STANDALONE_SHORT_WEEKDAYS:
    844         DateFormatSymbolsSingleSetter::setStandaloneShortWeekday(syms, index, value, valueLength, *status);
    845         break;
    846 
    847     case UDAT_STANDALONE_NARROW_WEEKDAYS:
    848         DateFormatSymbolsSingleSetter::setStandaloneNarrowWeekday(syms, index, value, valueLength, *status);
    849         break;
    850 
    851     case UDAT_QUARTERS:
    852         DateFormatSymbolsSingleSetter::setQuarter(syms, index, value, valueLength, *status);
    853         break;
    854 
    855     case UDAT_SHORT_QUARTERS:
    856         DateFormatSymbolsSingleSetter::setShortQuarter(syms, index, value, valueLength, *status);
    857         break;
    858 
    859     case UDAT_STANDALONE_QUARTERS:
    860         DateFormatSymbolsSingleSetter::setStandaloneQuarter(syms, index, value, valueLength, *status);
    861         break;
    862 
    863     case UDAT_STANDALONE_SHORT_QUARTERS:
    864         DateFormatSymbolsSingleSetter::setStandaloneShortQuarter(syms, index, value, valueLength, *status);
    865         break;
    866 
    867     case UDAT_AM_PMS:
    868         DateFormatSymbolsSingleSetter::setAmPm(syms, index, value, valueLength, *status);
    869         break;
    870 
    871     case UDAT_LOCALIZED_CHARS:
    872         DateFormatSymbolsSingleSetter::setLocalPatternChars(syms, value, valueLength, *status);
    873         break;
    874 
    875     default:
    876         *status = U_UNSUPPORTED_ERROR;
    877         break;
    878 
    879     }
    880 }
    881 
    882 U_CAPI const char* U_EXPORT2
    883 udat_getLocaleByType(const UDateFormat *fmt,
    884                      ULocDataLocaleType type,
    885                      UErrorCode* status)
    886 {
    887     if (fmt == NULL) {
    888         if (U_SUCCESS(*status)) {
    889             *status = U_ILLEGAL_ARGUMENT_ERROR;
    890         }
    891         return NULL;
    892     }
    893     return ((Format*)fmt)->getLocaleID(type, *status);
    894 }
    895 
    896 /**
    897  * Verify that fmt is a RelativeDateFormat. Invalid error if not.
    898  * @param fmt the UDateFormat, definitely a DateFormat, maybe something else
    899  * @param status error code, will be set to failure if there is a familure or the fmt is NULL.
    900  */
    901 static void verifyIsRelativeDateFormat(const UDateFormat* fmt, UErrorCode *status) {
    902    if(U_SUCCESS(*status) &&
    903        dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))==NULL) {
    904        *status = U_ILLEGAL_ARGUMENT_ERROR;
    905    }
    906 }
    907 
    908 
    909 U_CAPI int32_t U_EXPORT2
    910 udat_toPatternRelativeDate(const UDateFormat *fmt,
    911                            UChar             *result,
    912                            int32_t           resultLength,
    913                            UErrorCode        *status)
    914 {
    915     verifyIsRelativeDateFormat(fmt, status);
    916     if(U_FAILURE(*status)) return -1;
    917 
    918     UnicodeString datePattern;
    919     if(!(result==NULL && resultLength==0)) {
    920         // NULL destination for pure preflighting: empty dummy string
    921         // otherwise, alias the destination buffer
    922         datePattern.setTo(result, 0, resultLength);
    923     }
    924     ((RelativeDateFormat*)fmt)->toPatternDate(datePattern, *status);
    925     return datePattern.extract(result, resultLength, *status);
    926 }
    927 
    928 U_CAPI int32_t U_EXPORT2
    929 udat_toPatternRelativeTime(const UDateFormat *fmt,
    930                            UChar             *result,
    931                            int32_t           resultLength,
    932                            UErrorCode        *status)
    933 {
    934     verifyIsRelativeDateFormat(fmt, status);
    935     if(U_FAILURE(*status)) return -1;
    936 
    937     UnicodeString timePattern;
    938     if(!(result==NULL && resultLength==0)) {
    939         // NULL destination for pure preflighting: empty dummy string
    940         // otherwise, alias the destination buffer
    941         timePattern.setTo(result, 0, resultLength);
    942     }
    943     ((RelativeDateFormat*)fmt)->toPatternTime(timePattern, *status);
    944     return timePattern.extract(result, resultLength, *status);
    945 }
    946 
    947 U_CAPI void U_EXPORT2
    948 udat_applyPatternRelative(UDateFormat *format,
    949                           const UChar *datePattern,
    950                           int32_t     datePatternLength,
    951                           const UChar *timePattern,
    952                           int32_t     timePatternLength,
    953                           UErrorCode  *status)
    954 {
    955     verifyIsRelativeDateFormat(format, status);
    956     if(U_FAILURE(*status)) return;
    957     const UnicodeString datePat((UBool)(datePatternLength == -1), datePattern, datePatternLength);
    958     const UnicodeString timePat((UBool)(timePatternLength == -1), timePattern, timePatternLength);
    959     ((RelativeDateFormat*)format)->applyPatterns(datePat, timePat, *status);
    960 }
    961 
    962 #endif /* #if !UCONFIG_NO_FORMATTING */
    963