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