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