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