/* ******************************************************************************* * Copyright (C) 1996-2013, International Business Machines * Corporation and others. All Rights Reserved. ******************************************************************************* */ #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING #include "unicode/udat.h" #include "unicode/uloc.h" #include "unicode/datefmt.h" #include "unicode/timezone.h" #include "unicode/smpdtfmt.h" #include "unicode/fieldpos.h" #include "unicode/parsepos.h" #include "unicode/calendar.h" #include "unicode/numfmt.h" #include "unicode/dtfmtsym.h" #include "unicode/ustring.h" #include "unicode/udisplaycontext.h" #include "cpputils.h" #include "reldtfmt.h" #include "umutex.h" U_NAMESPACE_USE /** * Verify that fmt is a SimpleDateFormat. Invalid error if not. * @param fmt the UDateFormat, definitely a DateFormat, maybe something else * @param status error code, will be set to failure if there is a familure or the fmt is NULL. */ static void verifyIsSimpleDateFormat(const UDateFormat* fmt, UErrorCode *status) { if(U_SUCCESS(*status) && dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))==NULL) { *status = U_ILLEGAL_ARGUMENT_ERROR; } } // This mirrors the correspondence between the // SimpleDateFormat::fgPatternIndexToDateFormatField and // SimpleDateFormat::fgPatternIndexToCalendarField arrays. static UCalendarDateFields gDateFieldMapping[] = { UCAL_ERA, // UDAT_ERA_FIELD = 0 UCAL_YEAR, // UDAT_YEAR_FIELD = 1 UCAL_MONTH, // UDAT_MONTH_FIELD = 2 UCAL_DATE, // UDAT_DATE_FIELD = 3 UCAL_HOUR_OF_DAY, // UDAT_HOUR_OF_DAY1_FIELD = 4 UCAL_HOUR_OF_DAY, // UDAT_HOUR_OF_DAY0_FIELD = 5 UCAL_MINUTE, // UDAT_MINUTE_FIELD = 6 UCAL_SECOND, // UDAT_SECOND_FIELD = 7 UCAL_MILLISECOND, // UDAT_FRACTIONAL_SECOND_FIELD = 8 UCAL_DAY_OF_WEEK, // UDAT_DAY_OF_WEEK_FIELD = 9 UCAL_DAY_OF_YEAR, // UDAT_DAY_OF_YEAR_FIELD = 10 UCAL_DAY_OF_WEEK_IN_MONTH, // UDAT_DAY_OF_WEEK_IN_MONTH_FIELD = 11 UCAL_WEEK_OF_YEAR, // UDAT_WEEK_OF_YEAR_FIELD = 12 UCAL_WEEK_OF_MONTH, // UDAT_WEEK_OF_MONTH_FIELD = 13 UCAL_AM_PM, // UDAT_AM_PM_FIELD = 14 UCAL_HOUR, // UDAT_HOUR1_FIELD = 15 UCAL_HOUR, // UDAT_HOUR0_FIELD = 16 UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_FIELD = 17 UCAL_YEAR_WOY, // UDAT_YEAR_WOY_FIELD = 18 UCAL_DOW_LOCAL, // UDAT_DOW_LOCAL_FIELD = 19 UCAL_EXTENDED_YEAR, // UDAT_EXTENDED_YEAR_FIELD = 20 UCAL_JULIAN_DAY, // UDAT_JULIAN_DAY_FIELD = 21 UCAL_MILLISECONDS_IN_DAY, // UDAT_MILLISECONDS_IN_DAY_FIELD = 22 UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_RFC_FIELD = 23 // UCAL_DST_OFFSET also UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_GENERIC_FIELD = 24 UCAL_DOW_LOCAL, // UDAT_STANDALONE_DAY_FIELD = 25 UCAL_MONTH, // UDAT_STANDALONE_MONTH_FIELD = 26 UCAL_MONTH, // UDAT_QUARTER_FIELD = 27 UCAL_MONTH, // UDAT_STANDALONE_QUARTER_FIELD = 28 UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_SPECIAL_FIELD = 29 UCAL_YEAR, // UDAT_YEAR_NAME_FIELD = 30 UCAL_FIELD_COUNT, // UDAT_FIELD_COUNT = 31 // UCAL_IS_LEAP_MONTH is not the target of a mapping }; U_CAPI UCalendarDateFields U_EXPORT2 udat_toCalendarDateField(UDateFormatField field) { return gDateFieldMapping[field]; } /* For now- one opener. */ static UDateFormatOpener gOpener = NULL; U_INTERNAL void U_EXPORT2 udat_registerOpener(UDateFormatOpener opener, UErrorCode *status) { if(U_FAILURE(*status)) return; umtx_lock(NULL); if(gOpener==NULL) { gOpener = opener; } else { *status = U_ILLEGAL_ARGUMENT_ERROR; } umtx_unlock(NULL); } U_INTERNAL UDateFormatOpener U_EXPORT2 udat_unregisterOpener(UDateFormatOpener opener, UErrorCode *status) { if(U_FAILURE(*status)) return NULL; UDateFormatOpener oldOpener = NULL; umtx_lock(NULL); if(gOpener==NULL || gOpener!=opener) { *status = U_ILLEGAL_ARGUMENT_ERROR; } else { oldOpener=gOpener; gOpener=NULL; } umtx_unlock(NULL); return oldOpener; } U_CAPI UDateFormat* U_EXPORT2 udat_open(UDateFormatStyle timeStyle, UDateFormatStyle dateStyle, const char *locale, const UChar *tzID, int32_t tzIDLength, const UChar *pattern, int32_t patternLength, UErrorCode *status) { DateFormat *fmt; if(U_FAILURE(*status)) { return 0; } if(gOpener!=NULL) { // if it's registered fmt = (DateFormat*) (*gOpener)(timeStyle,dateStyle,locale,tzID,tzIDLength,pattern,patternLength,status); if(fmt!=NULL) { return (UDateFormat*)fmt; } // else fall through. } if(timeStyle != UDAT_PATTERN) { if(locale == 0) { fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle, (DateFormat::EStyle)timeStyle); } else { fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle, (DateFormat::EStyle)timeStyle, Locale(locale)); } } else { UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength); if(locale == 0) { fmt = new SimpleDateFormat(pat, *status); } else { fmt = new SimpleDateFormat(pat, Locale(locale), *status); } } if(fmt == 0) { *status = U_MEMORY_ALLOCATION_ERROR; return 0; } if(tzID != 0) { TimeZone *zone = TimeZone::createTimeZone(UnicodeString((UBool)(tzIDLength == -1), tzID, tzIDLength)); if(zone == 0) { *status = U_MEMORY_ALLOCATION_ERROR; delete fmt; return 0; } fmt->adoptTimeZone(zone); } return (UDateFormat*)fmt; } U_CAPI void U_EXPORT2 udat_close(UDateFormat* format) { delete (DateFormat*)format; } U_CAPI UDateFormat* U_EXPORT2 udat_clone(const UDateFormat *fmt, UErrorCode *status) { if(U_FAILURE(*status)) return 0; Format *res = ((DateFormat*)fmt)->clone(); if(res == 0) { *status = U_MEMORY_ALLOCATION_ERROR; return 0; } return (UDateFormat*) res; } U_CAPI int32_t U_EXPORT2 udat_format( const UDateFormat* format, UDate dateToFormat, UChar* result, int32_t resultLength, UFieldPosition* position, UErrorCode* status) { if(U_FAILURE(*status)) return -1; UnicodeString res; if(!(result==NULL && resultLength==0)) { // NULL destination for pure preflighting: empty dummy string // otherwise, alias the destination buffer res.setTo(result, 0, resultLength); } FieldPosition fp; if(position != 0) fp.setField(position->field); ((DateFormat*)format)->format(dateToFormat, res, fp); if(position != 0) { position->beginIndex = fp.getBeginIndex(); position->endIndex = fp.getEndIndex(); } return res.extract(result, resultLength, *status); } U_CAPI UDate U_EXPORT2 udat_parse( const UDateFormat* format, const UChar* text, int32_t textLength, int32_t *parsePos, UErrorCode *status) { if(U_FAILURE(*status)) return (UDate)0; const UnicodeString src((UBool)(textLength == -1), text, textLength); ParsePosition pp; int32_t stackParsePos = 0; UDate res; if(parsePos == NULL) { parsePos = &stackParsePos; } pp.setIndex(*parsePos); res = ((DateFormat*)format)->parse(src, pp); if(pp.getErrorIndex() == -1) *parsePos = pp.getIndex(); else { *parsePos = pp.getErrorIndex(); *status = U_PARSE_ERROR; } return res; } U_CAPI void U_EXPORT2 udat_parseCalendar(const UDateFormat* format, UCalendar* calendar, const UChar* text, int32_t textLength, int32_t *parsePos, UErrorCode *status) { if(U_FAILURE(*status)) return; const UnicodeString src((UBool)(textLength == -1), text, textLength); ParsePosition pp; if(parsePos != 0) pp.setIndex(*parsePos); ((DateFormat*)format)->parse(src, *(Calendar*)calendar, pp); if(parsePos != 0) { if(pp.getErrorIndex() == -1) *parsePos = pp.getIndex(); else { *parsePos = pp.getErrorIndex(); *status = U_PARSE_ERROR; } } } U_CAPI UBool U_EXPORT2 udat_isLenient(const UDateFormat* fmt) { return ((DateFormat*)fmt)->isLenient(); } U_CAPI void U_EXPORT2 udat_setLenient( UDateFormat* fmt, UBool isLenient) { ((DateFormat*)fmt)->setLenient(isLenient); } U_CAPI const UCalendar* U_EXPORT2 udat_getCalendar(const UDateFormat* fmt) { return (const UCalendar*) ((DateFormat*)fmt)->getCalendar(); } U_CAPI void U_EXPORT2 udat_setCalendar(UDateFormat* fmt, const UCalendar* calendarToSet) { ((DateFormat*)fmt)->setCalendar(*((Calendar*)calendarToSet)); } U_CAPI const UNumberFormat* U_EXPORT2 udat_getNumberFormat(const UDateFormat* fmt) { return (const UNumberFormat*) ((DateFormat*)fmt)->getNumberFormat(); } U_CAPI void U_EXPORT2 udat_setNumberFormat(UDateFormat* fmt, const UNumberFormat* numberFormatToSet) { ((DateFormat*)fmt)->setNumberFormat(*((NumberFormat*)numberFormatToSet)); } U_CAPI const char* U_EXPORT2 udat_getAvailable(int32_t index) { return uloc_getAvailable(index); } U_CAPI int32_t U_EXPORT2 udat_countAvailable() { return uloc_countAvailable(); } U_CAPI UDate U_EXPORT2 udat_get2DigitYearStart( const UDateFormat *fmt, UErrorCode *status) { verifyIsSimpleDateFormat(fmt, status); if(U_FAILURE(*status)) return (UDate)0; return ((SimpleDateFormat*)fmt)->get2DigitYearStart(*status); } U_CAPI void U_EXPORT2 udat_set2DigitYearStart( UDateFormat *fmt, UDate d, UErrorCode *status) { verifyIsSimpleDateFormat(fmt, status); if(U_FAILURE(*status)) return; ((SimpleDateFormat*)fmt)->set2DigitYearStart(d, *status); } U_CAPI int32_t U_EXPORT2 udat_toPattern( const UDateFormat *fmt, UBool localized, UChar *result, int32_t resultLength, UErrorCode *status) { if(U_FAILURE(*status)) return -1; UnicodeString res; if(!(result==NULL && resultLength==0)) { // NULL destination for pure preflighting: empty dummy string // otherwise, alias the destination buffer res.setTo(result, 0, resultLength); } const DateFormat *df=reinterpret_cast<const DateFormat *>(fmt); const SimpleDateFormat *sdtfmt=dynamic_cast<const SimpleDateFormat *>(df); const RelativeDateFormat *reldtfmt; if (sdtfmt!=NULL) { if(localized) sdtfmt->toLocalizedPattern(res, *status); else sdtfmt->toPattern(res); } else if (!localized && (reldtfmt=dynamic_cast<const RelativeDateFormat *>(df))!=NULL) { reldtfmt->toPattern(res, *status); } else { *status = U_ILLEGAL_ARGUMENT_ERROR; return -1; } return res.extract(result, resultLength, *status); } // TODO: should this take an UErrorCode? // A: Yes. Of course. U_CAPI void U_EXPORT2 udat_applyPattern( UDateFormat *format, UBool localized, const UChar *pattern, int32_t patternLength) { const UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength); UErrorCode status = U_ZERO_ERROR; verifyIsSimpleDateFormat(format, &status); if(U_FAILURE(status)) { return; } if(localized) ((SimpleDateFormat*)format)->applyLocalizedPattern(pat, status); else ((SimpleDateFormat*)format)->applyPattern(pat); } U_CAPI int32_t U_EXPORT2 udat_getSymbols(const UDateFormat *fmt, UDateFormatSymbolType type, int32_t index, UChar *result, int32_t resultLength, UErrorCode *status) { const DateFormatSymbols *syms; const SimpleDateFormat* sdtfmt; const RelativeDateFormat* rdtfmt; if ((sdtfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) { syms = sdtfmt->getDateFormatSymbols(); } else if ((rdtfmt = dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) { syms = rdtfmt->getDateFormatSymbols(); } else { return -1; } int32_t count; const UnicodeString *res = NULL; switch(type) { case UDAT_ERAS: res = syms->getEras(count); break; case UDAT_ERA_NAMES: res = syms->getEraNames(count); break; case UDAT_MONTHS: res = syms->getMonths(count); break; case UDAT_SHORT_MONTHS: res = syms->getShortMonths(count); break; case UDAT_WEEKDAYS: res = syms->getWeekdays(count); break; case UDAT_SHORT_WEEKDAYS: res = syms->getShortWeekdays(count); break; case UDAT_AM_PMS: res = syms->getAmPmStrings(count); break; case UDAT_LOCALIZED_CHARS: { UnicodeString res1; if(!(result==NULL && resultLength==0)) { // NULL destination for pure preflighting: empty dummy string // otherwise, alias the destination buffer res1.setTo(result, 0, resultLength); } syms->getLocalPatternChars(res1); return res1.extract(result, resultLength, *status); } case UDAT_NARROW_MONTHS: res = syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); break; case UDAT_SHORTER_WEEKDAYS: res = syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::SHORT); break; case UDAT_NARROW_WEEKDAYS: res = syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); break; case UDAT_STANDALONE_MONTHS: res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); break; case UDAT_STANDALONE_SHORT_MONTHS: res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); break; case UDAT_STANDALONE_NARROW_MONTHS: res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW); break; case UDAT_STANDALONE_WEEKDAYS: res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); break; case UDAT_STANDALONE_SHORT_WEEKDAYS: res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); break; case UDAT_STANDALONE_SHORTER_WEEKDAYS: res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::SHORT); break; case UDAT_STANDALONE_NARROW_WEEKDAYS: res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW); break; case UDAT_QUARTERS: res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); break; case UDAT_SHORT_QUARTERS: res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); break; case UDAT_STANDALONE_QUARTERS: res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); break; case UDAT_STANDALONE_SHORT_QUARTERS: res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); break; } if(index < count) { return res[index].extract(result, resultLength, *status); } return 0; } // TODO: also needs an errorCode. U_CAPI int32_t U_EXPORT2 udat_countSymbols( const UDateFormat *fmt, UDateFormatSymbolType type) { const DateFormatSymbols *syms; const SimpleDateFormat* sdtfmt; const RelativeDateFormat* rdtfmt; if ((sdtfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) { syms = sdtfmt->getDateFormatSymbols(); } else if ((rdtfmt = dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) { syms = rdtfmt->getDateFormatSymbols(); } else { return 0; } int32_t count = 0; switch(type) { case UDAT_ERAS: syms->getEras(count); break; case UDAT_MONTHS: syms->getMonths(count); break; case UDAT_SHORT_MONTHS: syms->getShortMonths(count); break; case UDAT_WEEKDAYS: syms->getWeekdays(count); break; case UDAT_SHORT_WEEKDAYS: syms->getShortWeekdays(count); break; case UDAT_AM_PMS: syms->getAmPmStrings(count); break; case UDAT_LOCALIZED_CHARS: count = 1; break; case UDAT_ERA_NAMES: syms->getEraNames(count); break; case UDAT_NARROW_MONTHS: syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); break; case UDAT_SHORTER_WEEKDAYS: syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::SHORT); break; case UDAT_NARROW_WEEKDAYS: syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); break; case UDAT_STANDALONE_MONTHS: syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); break; case UDAT_STANDALONE_SHORT_MONTHS: syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); break; case UDAT_STANDALONE_NARROW_MONTHS: syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW); break; case UDAT_STANDALONE_WEEKDAYS: syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); break; case UDAT_STANDALONE_SHORT_WEEKDAYS: syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); break; case UDAT_STANDALONE_SHORTER_WEEKDAYS: syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::SHORT); break; case UDAT_STANDALONE_NARROW_WEEKDAYS: syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW); break; case UDAT_QUARTERS: syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); break; case UDAT_SHORT_QUARTERS: syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); break; case UDAT_STANDALONE_QUARTERS: syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); break; case UDAT_STANDALONE_SHORT_QUARTERS: syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); break; } return count; } U_NAMESPACE_BEGIN /* * This DateFormatSymbolsSingleSetter class is a friend of DateFormatSymbols * solely for the purpose of avoiding to clone the array of strings * just to modify one of them and then setting all of them back. * For example, the old code looked like this: * case UDAT_MONTHS: * res = syms->getMonths(count); * array = new UnicodeString[count]; * if(array == 0) { * *status = U_MEMORY_ALLOCATION_ERROR; * return; * } * uprv_arrayCopy(res, array, count); * if(index < count) * array[index] = val; * syms->setMonths(array, count); * break; * * Even worse, the old code actually cloned the entire DateFormatSymbols object, * cloned one value array, changed one value, and then made the SimpleDateFormat * replace its DateFormatSymbols object with the new one. * * markus 2002-oct-14 */ class DateFormatSymbolsSingleSetter /* not : public UObject because all methods are static */ { public: static void setSymbol(UnicodeString *array, int32_t count, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { if(array!=NULL) { if(index>=count) { errorCode=U_INDEX_OUTOFBOUNDS_ERROR; } else if(value==NULL) { errorCode=U_ILLEGAL_ARGUMENT_ERROR; } else { array[index].setTo(value, valueLength); } } } static void setEra(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fEras, syms->fErasCount, index, value, valueLength, errorCode); } static void setEraName(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fEraNames, syms->fEraNamesCount, index, value, valueLength, errorCode); } static void setMonth(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fMonths, syms->fMonthsCount, index, value, valueLength, errorCode); } static void setShortMonth(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fShortMonths, syms->fShortMonthsCount, index, value, valueLength, errorCode); } static void setNarrowMonth(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fNarrowMonths, syms->fNarrowMonthsCount, index, value, valueLength, errorCode); } static void setStandaloneMonth(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fStandaloneMonths, syms->fStandaloneMonthsCount, index, value, valueLength, errorCode); } static void setStandaloneShortMonth(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fStandaloneShortMonths, syms->fStandaloneShortMonthsCount, index, value, valueLength, errorCode); } static void setStandaloneNarrowMonth(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fStandaloneNarrowMonths, syms->fStandaloneNarrowMonthsCount, index, value, valueLength, errorCode); } static void setWeekday(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fWeekdays, syms->fWeekdaysCount, index, value, valueLength, errorCode); } static void setShortWeekday(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fShortWeekdays, syms->fShortWeekdaysCount, index, value, valueLength, errorCode); } static void setShorterWeekday(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fShorterWeekdays, syms->fShorterWeekdaysCount, index, value, valueLength, errorCode); } static void setNarrowWeekday(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fNarrowWeekdays, syms->fNarrowWeekdaysCount, index, value, valueLength, errorCode); } static void setStandaloneWeekday(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fStandaloneWeekdays, syms->fStandaloneWeekdaysCount, index, value, valueLength, errorCode); } static void setStandaloneShortWeekday(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fStandaloneShortWeekdays, syms->fStandaloneShortWeekdaysCount, index, value, valueLength, errorCode); } static void setStandaloneShorterWeekday(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fStandaloneShorterWeekdays, syms->fStandaloneShorterWeekdaysCount, index, value, valueLength, errorCode); } static void setStandaloneNarrowWeekday(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fStandaloneNarrowWeekdays, syms->fStandaloneNarrowWeekdaysCount, index, value, valueLength, errorCode); } static void setQuarter(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fQuarters, syms->fQuartersCount, index, value, valueLength, errorCode); } static void setShortQuarter(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fShortQuarters, syms->fShortQuartersCount, index, value, valueLength, errorCode); } static void setStandaloneQuarter(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fStandaloneQuarters, syms->fStandaloneQuartersCount, index, value, valueLength, errorCode); } static void setStandaloneShortQuarter(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fStandaloneShortQuarters, syms->fStandaloneShortQuartersCount, index, value, valueLength, errorCode); } static void setAmPm(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(syms->fAmPms, syms->fAmPmsCount, index, value, valueLength, errorCode); } static void setLocalPatternChars(DateFormatSymbols *syms, const UChar *value, int32_t valueLength, UErrorCode &errorCode) { setSymbol(&syms->fLocalPatternChars, 1, 0, value, valueLength, errorCode); } }; U_NAMESPACE_END U_CAPI void U_EXPORT2 udat_setSymbols( UDateFormat *format, UDateFormatSymbolType type, int32_t index, UChar *value, int32_t valueLength, UErrorCode *status) { verifyIsSimpleDateFormat(format, status); if(U_FAILURE(*status)) return; DateFormatSymbols *syms = (DateFormatSymbols *)((SimpleDateFormat *)format)->getDateFormatSymbols(); switch(type) { case UDAT_ERAS: DateFormatSymbolsSingleSetter::setEra(syms, index, value, valueLength, *status); break; case UDAT_ERA_NAMES: DateFormatSymbolsSingleSetter::setEraName(syms, index, value, valueLength, *status); break; case UDAT_MONTHS: DateFormatSymbolsSingleSetter::setMonth(syms, index, value, valueLength, *status); break; case UDAT_SHORT_MONTHS: DateFormatSymbolsSingleSetter::setShortMonth(syms, index, value, valueLength, *status); break; case UDAT_NARROW_MONTHS: DateFormatSymbolsSingleSetter::setNarrowMonth(syms, index, value, valueLength, *status); break; case UDAT_STANDALONE_MONTHS: DateFormatSymbolsSingleSetter::setStandaloneMonth(syms, index, value, valueLength, *status); break; case UDAT_STANDALONE_SHORT_MONTHS: DateFormatSymbolsSingleSetter::setStandaloneShortMonth(syms, index, value, valueLength, *status); break; case UDAT_STANDALONE_NARROW_MONTHS: DateFormatSymbolsSingleSetter::setStandaloneNarrowMonth(syms, index, value, valueLength, *status); break; case UDAT_WEEKDAYS: DateFormatSymbolsSingleSetter::setWeekday(syms, index, value, valueLength, *status); break; case UDAT_SHORT_WEEKDAYS: DateFormatSymbolsSingleSetter::setShortWeekday(syms, index, value, valueLength, *status); break; case UDAT_SHORTER_WEEKDAYS: DateFormatSymbolsSingleSetter::setShorterWeekday(syms, index, value, valueLength, *status); break; case UDAT_NARROW_WEEKDAYS: DateFormatSymbolsSingleSetter::setNarrowWeekday(syms, index, value, valueLength, *status); break; case UDAT_STANDALONE_WEEKDAYS: DateFormatSymbolsSingleSetter::setStandaloneWeekday(syms, index, value, valueLength, *status); break; case UDAT_STANDALONE_SHORT_WEEKDAYS: DateFormatSymbolsSingleSetter::setStandaloneShortWeekday(syms, index, value, valueLength, *status); break; case UDAT_STANDALONE_SHORTER_WEEKDAYS: DateFormatSymbolsSingleSetter::setStandaloneShorterWeekday(syms, index, value, valueLength, *status); break; case UDAT_STANDALONE_NARROW_WEEKDAYS: DateFormatSymbolsSingleSetter::setStandaloneNarrowWeekday(syms, index, value, valueLength, *status); break; case UDAT_QUARTERS: DateFormatSymbolsSingleSetter::setQuarter(syms, index, value, valueLength, *status); break; case UDAT_SHORT_QUARTERS: DateFormatSymbolsSingleSetter::setShortQuarter(syms, index, value, valueLength, *status); break; case UDAT_STANDALONE_QUARTERS: DateFormatSymbolsSingleSetter::setStandaloneQuarter(syms, index, value, valueLength, *status); break; case UDAT_STANDALONE_SHORT_QUARTERS: DateFormatSymbolsSingleSetter::setStandaloneShortQuarter(syms, index, value, valueLength, *status); break; case UDAT_AM_PMS: DateFormatSymbolsSingleSetter::setAmPm(syms, index, value, valueLength, *status); break; case UDAT_LOCALIZED_CHARS: DateFormatSymbolsSingleSetter::setLocalPatternChars(syms, value, valueLength, *status); break; default: *status = U_UNSUPPORTED_ERROR; break; } } U_CAPI const char* U_EXPORT2 udat_getLocaleByType(const UDateFormat *fmt, ULocDataLocaleType type, UErrorCode* status) { if (fmt == NULL) { if (U_SUCCESS(*status)) { *status = U_ILLEGAL_ARGUMENT_ERROR; } return NULL; } return ((Format*)fmt)->getLocaleID(type, *status); } U_CAPI void U_EXPORT2 udat_setContext(UDateFormat* fmt, UDisplayContext value, UErrorCode* status) { verifyIsSimpleDateFormat(fmt, status); if (U_FAILURE(*status)) { return; } ((SimpleDateFormat*)fmt)->setContext(value, *status); } U_CAPI UDisplayContext U_EXPORT2 udat_getContext(UDateFormat* fmt, UDisplayContextType type, UErrorCode* status) { verifyIsSimpleDateFormat(fmt, status); if (U_FAILURE(*status)) { return (UDisplayContext)0; } return ((SimpleDateFormat*)fmt)->getContext(type, *status); } /** * Verify that fmt is a RelativeDateFormat. Invalid error if not. * @param fmt the UDateFormat, definitely a DateFormat, maybe something else * @param status error code, will be set to failure if there is a familure or the fmt is NULL. */ static void verifyIsRelativeDateFormat(const UDateFormat* fmt, UErrorCode *status) { if(U_SUCCESS(*status) && dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))==NULL) { *status = U_ILLEGAL_ARGUMENT_ERROR; } } U_CAPI int32_t U_EXPORT2 udat_toPatternRelativeDate(const UDateFormat *fmt, UChar *result, int32_t resultLength, UErrorCode *status) { verifyIsRelativeDateFormat(fmt, status); if(U_FAILURE(*status)) return -1; UnicodeString datePattern; if(!(result==NULL && resultLength==0)) { // NULL destination for pure preflighting: empty dummy string // otherwise, alias the destination buffer datePattern.setTo(result, 0, resultLength); } ((RelativeDateFormat*)fmt)->toPatternDate(datePattern, *status); return datePattern.extract(result, resultLength, *status); } U_CAPI int32_t U_EXPORT2 udat_toPatternRelativeTime(const UDateFormat *fmt, UChar *result, int32_t resultLength, UErrorCode *status) { verifyIsRelativeDateFormat(fmt, status); if(U_FAILURE(*status)) return -1; UnicodeString timePattern; if(!(result==NULL && resultLength==0)) { // NULL destination for pure preflighting: empty dummy string // otherwise, alias the destination buffer timePattern.setTo(result, 0, resultLength); } ((RelativeDateFormat*)fmt)->toPatternTime(timePattern, *status); return timePattern.extract(result, resultLength, *status); } U_CAPI void U_EXPORT2 udat_applyPatternRelative(UDateFormat *format, const UChar *datePattern, int32_t datePatternLength, const UChar *timePattern, int32_t timePatternLength, UErrorCode *status) { verifyIsRelativeDateFormat(format, status); if(U_FAILURE(*status)) return; const UnicodeString datePat((UBool)(datePatternLength == -1), datePattern, datePatternLength); const UnicodeString timePat((UBool)(timePatternLength == -1), timePattern, timePatternLength); ((RelativeDateFormat*)format)->applyPatterns(datePat, timePat, *status); } #endif /* #if !UCONFIG_NO_FORMATTING */