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