X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/374ca955a76ecab1204ca8bfa63ff9238d998416..340931cb2e044a2141d11567dd0f782524e32994:/icuSources/i18n/udat.cpp diff --git a/icuSources/i18n/udat.cpp b/icuSources/i18n/udat.cpp index eb6966f7..f6a04b05 100644 --- a/icuSources/i18n/udat.cpp +++ b/icuSources/i18n/udat.cpp @@ -1,6 +1,8 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html /* ******************************************************************************* -* Copyright (C) 1996-2004, International Business Machines +* Copyright (C) 1996-2015, International Business Machines * Corporation and others. All Rights Reserved. ******************************************************************************* */ @@ -21,10 +23,120 @@ #include "unicode/numfmt.h" #include "unicode/dtfmtsym.h" #include "unicode/ustring.h" +#include "unicode/udisplaycontext.h" +#include "unicode/ufieldpositer.h" +#include "unicode/ucasemap.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(reinterpret_cast(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 (also UCAL_DST_OFFSET) + UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_GENERIC_FIELD = 24 (also UCAL_DST_OFFSET) + 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 (also UCAL_DST_OFFSET) + UCAL_YEAR, // UDAT_YEAR_NAME_FIELD = 30 + UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD = 31 (also UCAL_DST_OFFSET) + UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_ISO_FIELD = 32 (also UCAL_DST_OFFSET) + UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_ISO_LOCAL_FIELD = 33 (also UCAL_DST_OFFSET) + UCAL_EXTENDED_YEAR, // UDAT_RELATED_YEAR_FIELD = 34 (not an exact match) + UCAL_FIELD_COUNT, // UDAT_AM_PM_MIDNIGHT_NOON_FIELD=35 (no match) + UCAL_FIELD_COUNT, // UDAT_FLEXIBLE_DAY_PERIOD_FIELD=36 (no match) + UCAL_FIELD_COUNT, // UDAT_TIME_SEPARATOR_FIELD = 37 (no match) + // UDAT_FIELD_COUNT = 38 as of ICU 66 + // UCAL_IS_LEAP_MONTH is not the target of a mapping +}; + +U_CAPI UCalendarDateFields U_EXPORT2 +udat_toCalendarDateField(UDateFormatField field) { + return (field >= UDAT_ERA_FIELD && field < UDAT_FIELD_COUNT)? gDateFieldMapping[field]: UCAL_FIELD_COUNT; +} + +// for Apple +U_CAPI UDateFormatField U_EXPORT2 +udat_patternCharToDateFormatField(UChar patternChar) { + const UChar* patternUChars = (UChar*)DateFormatSymbols::getPatternUChars(); + UChar* patternOffset = u_strchr(patternUChars, patternChar); + return (patternOffset)? (UDateFormatField)(patternOffset-patternUChars): UDAT_FIELD_COUNT; +} + +/* 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, @@ -35,54 +147,58 @@ udat_open(UDateFormatStyle timeStyle, int32_t patternLength, UErrorCode *status) { - if(U_FAILURE(*status)) - { + DateFormat *fmt; + if(U_FAILURE(*status)) { return 0; } - if(timeStyle != UDAT_IGNORE) - { - DateFormat *fmt; - if(locale == 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 + } + else { fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle, (DateFormat::EStyle)timeStyle, Locale(locale)); - - if(fmt == 0) { - *status = U_MEMORY_ALLOCATION_ERROR; - return 0; } + } + else { + UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength); - 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); + if(locale == 0) { + fmt = new SimpleDateFormat(pat, *status); + } + else { + fmt = new SimpleDateFormat(pat, Locale(locale), *status); } - - return (UDateFormat*)fmt; } - else - { - const UnicodeString pat = UnicodeString((UBool)(patternLength == -1), pattern, patternLength); - UDateFormat *retVal = 0; - if(locale == 0) - retVal = (UDateFormat*)new SimpleDateFormat(pat, *status); - else - retVal = (UDateFormat*)new SimpleDateFormat(pat, Locale(locale), *status); + if(fmt == nullptr) { + *status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } + if (U_FAILURE(*status)) { + delete fmt; + return nullptr; + } - if(retVal == 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; } - return retVal; + fmt->adoptTimeZone(zone); } + + return (UDateFormat*)fmt; } @@ -98,7 +214,7 @@ udat_clone(const UDateFormat *fmt, { if(U_FAILURE(*status)) return 0; - Format *res = ((SimpleDateFormat*)fmt)->clone(); + Format *res = ((DateFormat*)fmt)->clone(); if(res == 0) { *status = U_MEMORY_ALLOCATION_ERROR; @@ -116,10 +232,16 @@ udat_format( const UDateFormat* format, UFieldPosition* position, UErrorCode* status) { - if(U_FAILURE(*status)) return -1; + if(U_FAILURE(*status)) { + return -1; + } + if (result == NULL ? resultLength != 0 : resultLength < 0) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return -1; + } UnicodeString res; - if(!(result==NULL && resultLength==0)) { + if (result != NULL) { // NULL destination for pure preflighting: empty dummy string // otherwise, alias the destination buffer res.setTo(result, 0, resultLength); @@ -140,6 +262,100 @@ udat_format( const UDateFormat* format, return res.extract(result, resultLength, *status); } +U_CAPI int32_t U_EXPORT2 +udat_formatCalendar(const UDateFormat* format, + UCalendar* calendar, + UChar* result, + int32_t resultLength, + UFieldPosition* position, + UErrorCode* status) +{ + if(U_FAILURE(*status)) { + return -1; + } + if (result == NULL ? resultLength != 0 : resultLength < 0) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return -1; + } + + UnicodeString res; + if (result != NULL) { + // 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(*(Calendar*)calendar, res, fp); + + if(position != 0) { + position->beginIndex = fp.getBeginIndex(); + position->endIndex = fp.getEndIndex(); + } + + return res.extract(result, resultLength, *status); +} + +U_CAPI int32_t U_EXPORT2 +udat_formatForFields( const UDateFormat* format, + UDate dateToFormat, + UChar* result, + int32_t resultLength, + UFieldPositionIterator* fpositer, + UErrorCode* status) +{ + if(U_FAILURE(*status)) { + return -1; + } + if (result == NULL ? resultLength != 0 : resultLength < 0) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return -1; + } + + UnicodeString res; + if (result != NULL) { + // NULL destination for pure preflighting: empty dummy string + // otherwise, alias the destination buffer + res.setTo(result, 0, resultLength); + } + + ((DateFormat*)format)->format(dateToFormat, res, (FieldPositionIterator*)fpositer, *status); + + return res.extract(result, resultLength, *status); +} + +U_CAPI int32_t U_EXPORT2 +udat_formatCalendarForFields(const UDateFormat* format, + UCalendar* calendar, + UChar* result, + int32_t resultLength, + UFieldPositionIterator* fpositer, + UErrorCode* status) +{ + if(U_FAILURE(*status)) { + return -1; + } + if (result == NULL ? resultLength != 0 : resultLength < 0) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return -1; + } + + UnicodeString res; + if (result != NULL) { + // NULL destination for pure preflighting: empty dummy string + // otherwise, alias the destination buffer + res.setTo(result, 0, resultLength); + } + + ((DateFormat*)format)->format(*(Calendar*)calendar, res, (FieldPositionIterator*)fpositer, *status); + + return res.extract(result, resultLength, *status); +} + U_CAPI UDate U_EXPORT2 udat_parse( const UDateFormat* format, const UChar* text, @@ -184,19 +400,21 @@ udat_parseCalendar(const UDateFormat* format, const UnicodeString src((UBool)(textLength == -1), text, textLength); ParsePosition pp; + int32_t stackParsePos = 0; - if(parsePos != 0) - pp.setIndex(*parsePos); + if(parsePos == NULL) { + parsePos = &stackParsePos; + } + + 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; - } + if(pp.getErrorIndex() == -1) + *parsePos = pp.getIndex(); + else { + *parsePos = pp.getErrorIndex(); + *status = U_PARSE_ERROR; } } @@ -213,6 +431,26 @@ udat_setLenient( UDateFormat* fmt, ((DateFormat*)fmt)->setLenient(isLenient); } +U_DRAFT UBool U_EXPORT2 +udat_getBooleanAttribute(const UDateFormat* fmt, + UDateFormatBooleanAttribute attr, + UErrorCode* status) +{ + if(U_FAILURE(*status)) return FALSE; + return ((DateFormat*)fmt)->getBooleanAttribute(attr, *status); + //return FALSE; +} + +U_DRAFT void U_EXPORT2 +udat_setBooleanAttribute(UDateFormat *fmt, + UDateFormatBooleanAttribute attr, + UBool newValue, + UErrorCode* status) +{ + if(U_FAILURE(*status)) return; + ((DateFormat*)fmt)->setBooleanAttribute(attr, newValue, *status); +} + U_CAPI const UCalendar* U_EXPORT2 udat_getCalendar(const UDateFormat* fmt) { @@ -226,12 +464,36 @@ udat_setCalendar(UDateFormat* fmt, ((DateFormat*)fmt)->setCalendar(*((Calendar*)calendarToSet)); } +U_DRAFT const UNumberFormat* U_EXPORT2 +udat_getNumberFormatForField(const UDateFormat* fmt, UChar field) +{ + UErrorCode status = U_ZERO_ERROR; + verifyIsSimpleDateFormat(fmt, &status); + if (U_FAILURE(status)) return (const UNumberFormat*) ((DateFormat*)fmt)->getNumberFormat(); + return (const UNumberFormat*) ((SimpleDateFormat*)fmt)->getNumberFormatForField(field); +} + U_CAPI const UNumberFormat* U_EXPORT2 udat_getNumberFormat(const UDateFormat* fmt) { return (const UNumberFormat*) ((DateFormat*)fmt)->getNumberFormat(); } +U_DRAFT void U_EXPORT2 +udat_adoptNumberFormatForFields( UDateFormat* fmt, + const UChar* fields, + UNumberFormat* numberFormatToSet, + UErrorCode* status) +{ + verifyIsSimpleDateFormat(fmt, status); + if (U_FAILURE(*status)) return; + + if (fields!=NULL) { + UnicodeString overrideFields(fields); + ((SimpleDateFormat*)fmt)->adoptNumberFormat(overrideFields, (NumberFormat*)numberFormatToSet, *status); + } +} + U_CAPI void U_EXPORT2 udat_setNumberFormat(UDateFormat* fmt, const UNumberFormat* numberFormatToSet) @@ -239,6 +501,13 @@ udat_setNumberFormat(UDateFormat* fmt, ((DateFormat*)fmt)->setNumberFormat(*((NumberFormat*)numberFormatToSet)); } +U_DRAFT void U_EXPORT2 +udat_adoptNumberFormat( UDateFormat* fmt, + UNumberFormat* numberFormatToAdopt) +{ + ((DateFormat*)fmt)->adoptNumberFormat((NumberFormat*)numberFormatToAdopt); +} + U_CAPI const char* U_EXPORT2 udat_getAvailable(int32_t index) { @@ -255,6 +524,7 @@ 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); } @@ -264,6 +534,7 @@ udat_set2DigitYearStart( UDateFormat *fmt, UDate d, UErrorCode *status) { + verifyIsSimpleDateFormat(fmt, status); if(U_FAILURE(*status)) return; ((SimpleDateFormat*)fmt)->set2DigitYearStart(d, *status); } @@ -275,24 +546,41 @@ udat_toPattern( const UDateFormat *fmt, int32_t resultLength, UErrorCode *status) { - if(U_FAILURE(*status)) return -1; + if(U_FAILURE(*status)) { + return -1; + } + if (result == NULL ? resultLength != 0 : resultLength < 0) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return -1; + } UnicodeString res; - if(!(result==NULL && resultLength==0)) { + if (result != NULL) { // NULL destination for pure preflighting: empty dummy string // otherwise, alias the destination buffer res.setTo(result, 0, resultLength); } - if(localized) - ((SimpleDateFormat*)fmt)->toLocalizedPattern(res, *status); - else - ((SimpleDateFormat*)fmt)->toPattern(res); + const DateFormat *df=reinterpret_cast(fmt); + const SimpleDateFormat *sdtfmt=dynamic_cast(df); + const RelativeDateFormat *reldtfmt; + if (sdtfmt!=NULL) { + if(localized) + sdtfmt->toLocalizedPattern(res, *status); + else + sdtfmt->toPattern(res); + } else if (!localized && (reldtfmt=dynamic_cast(df))!=NULL) { + reldtfmt->toPattern(res, *status); + } else { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return -1; + } return res.extract(result, resultLength, *status); } -// TBD: should this take an UErrorCode? +// TODO: should this take an UErrorCode? +// A: Yes. Of course. U_CAPI void U_EXPORT2 udat_applyPattern( UDateFormat *format, UBool localized, @@ -302,12 +590,62 @@ udat_applyPattern( UDateFormat *format, 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); } +// Apple addition +static DateFormatSymbols::ECapitalizationContextUsageType capUsageFromSymbolType(UDateFormatSymbolType type) +{ + DateFormatSymbols::ECapitalizationContextUsageType capContextUsageType = DateFormatSymbols::kCapContextUsageOther; + switch (type) { + case UDAT_ERA_NAMES: + capContextUsageType = DateFormatSymbols::kCapContextUsageEraWide; + break; + case UDAT_ERAS: + capContextUsageType = DateFormatSymbols::kCapContextUsageEraAbbrev; + break; + case UDAT_MONTHS: + case UDAT_SHORT_MONTHS: + capContextUsageType = DateFormatSymbols::kCapContextUsageMonthFormat; + break; + case UDAT_STANDALONE_MONTHS: + case UDAT_STANDALONE_SHORT_MONTHS: + capContextUsageType = DateFormatSymbols::kCapContextUsageMonthStandalone; + break; + case UDAT_NARROW_MONTHS: + case UDAT_STANDALONE_NARROW_MONTHS: + capContextUsageType = DateFormatSymbols::kCapContextUsageMonthNarrow; + break; + case UDAT_WEEKDAYS: + case UDAT_SHORT_WEEKDAYS: + case UDAT_SHORTER_WEEKDAYS: + capContextUsageType = DateFormatSymbols::kCapContextUsageDayFormat; + break; + case UDAT_STANDALONE_WEEKDAYS: + case UDAT_STANDALONE_SHORT_WEEKDAYS: + case UDAT_STANDALONE_SHORTER_WEEKDAYS: + capContextUsageType = DateFormatSymbols::kCapContextUsageDayStandalone; + break; + case UDAT_STANDALONE_NARROW_WEEKDAYS: + case UDAT_NARROW_WEEKDAYS: + capContextUsageType = DateFormatSymbols::kCapContextUsageDayNarrow; + break; + default: + break; + } + return capContextUsageType; +} + + + U_CAPI int32_t U_EXPORT2 udat_getSymbols(const UDateFormat *fmt, UDateFormatSymbolType type, @@ -316,54 +654,49 @@ udat_getSymbols(const UDateFormat *fmt, int32_t resultLength, UErrorCode *status) { - if(U_FAILURE(*status)) return -1; - - const DateFormatSymbols *syms = - ((SimpleDateFormat*)fmt)->getDateFormatSymbols(); - int32_t count; - const UnicodeString *res; + const DateFormatSymbols *syms; + const SimpleDateFormat* sdtfmt; + const RelativeDateFormat* rdtfmt; + BreakIterator* capitalizationBrkIter; + if ((sdtfmt = dynamic_cast(reinterpret_cast(fmt))) != NULL) { + syms = sdtfmt->getDateFormatSymbols(); + capitalizationBrkIter = sdtfmt->getCapitalizationBrkIter(); + } else if ((rdtfmt = dynamic_cast(reinterpret_cast(fmt))) != NULL) { + syms = rdtfmt->getDateFormatSymbols(); + capitalizationBrkIter = rdtfmt->getCapitalizationBrkIter(); + } else { + return -1; + } + int32_t count = 0; + const UnicodeString *res = NULL; switch(type) { case UDAT_ERAS: res = syms->getEras(count); - if(index < count) { - return res[index].extract(result, resultLength, *status); - } + break; + + case UDAT_ERA_NAMES: + res = syms->getEraNames(count); break; case UDAT_MONTHS: res = syms->getMonths(count); - if(index < count) { - return res[index].extract(result, resultLength, *status); - } break; case UDAT_SHORT_MONTHS: res = syms->getShortMonths(count); - if(index < count) { - return res[index].extract(result, resultLength, *status); - } break; case UDAT_WEEKDAYS: res = syms->getWeekdays(count); - if(index < count) { - return res[index].extract(result, resultLength, *status); - } break; case UDAT_SHORT_WEEKDAYS: res = syms->getShortWeekdays(count); - if(index < count) { - return res[index].extract(result, resultLength, *status); - } break; case UDAT_AM_PMS: res = syms->getAmPmStrings(count); - if(index < count) { - return res[index].extract(result, resultLength, *status); - } break; case UDAT_LOCALIZED_CHARS: @@ -377,17 +710,149 @@ udat_getSymbols(const UDateFormat *fmt, 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; + + case UDAT_CYCLIC_YEARS_WIDE: + res = syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); + break; + + case UDAT_CYCLIC_YEARS_ABBREVIATED: + res = syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); + break; + + case UDAT_CYCLIC_YEARS_NARROW: + res = syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); + break; + + case UDAT_ZODIAC_NAMES_WIDE: + res = syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); + break; + + case UDAT_ZODIAC_NAMES_ABBREVIATED: + res = syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); + break; + + case UDAT_ZODIAC_NAMES_NARROW: + res = syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); + break; + + case UADAT_CYCLIC_ZODIAC_NAMES: + res = syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); + index = (index > 0)? (index - 1) % 12: 0; + break; + } + if(index < count) { +#if !UCONFIG_NO_BREAK_ITERATION + // Apple addition for + if (u_islower(res[index].char32At(0)) && capitalizationBrkIter != NULL) { + UDisplayContext capitalizationContext = ((const DateFormat*)fmt)->getContext(UDISPCTX_TYPE_CAPITALIZATION, *status); + UBool titlecase = FALSE; + switch (capitalizationContext) { + case UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE: + titlecase = TRUE; + break; + case UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU: + titlecase = syms->capitalizeForUsage(capUsageFromSymbolType(type), 0); + break; + case UDISPCTX_CAPITALIZATION_FOR_STANDALONE: + titlecase = syms->capitalizeForUsage(capUsageFromSymbolType(type), 1); + break; + default: + // titlecase = FALSE; + break; + } + if (titlecase) { + UnicodeString symbolToModify(res[index]); + BreakIterator* capBrkIterToUse = capitalizationBrkIter->clone(); + if (capBrkIterToUse != NULL) { + Locale locale = capBrkIterToUse->getLocale(ULOC_ACTUAL_LOCALE, *status); + if (U_SUCCESS(*status)) { + symbolToModify.toTitle(capBrkIterToUse, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT); + delete capBrkIterToUse; + return symbolToModify.extract(result, resultLength, *status); + } + delete capBrkIterToUse; + } + } + } +#endif + 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 = - ((SimpleDateFormat*)fmt)->getDateFormatSymbols(); + const DateFormatSymbols *syms; + const SimpleDateFormat* sdtfmt; + const RelativeDateFormat* rdtfmt; + if ((sdtfmt = dynamic_cast(reinterpret_cast(fmt))) != NULL) { + syms = sdtfmt->getDateFormatSymbols(); + } else if ((rdtfmt = dynamic_cast(reinterpret_cast(fmt))) != NULL) { + syms = rdtfmt->getDateFormatSymbols(); + } else { + return 0; + } int32_t count = 0; switch(type) { @@ -418,6 +883,95 @@ udat_countSymbols( const UDateFormat *fmt, 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; + + case UDAT_CYCLIC_YEARS_WIDE: + syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); + break; + + case UDAT_CYCLIC_YEARS_ABBREVIATED: + syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); + break; + + case UDAT_CYCLIC_YEARS_NARROW: + syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); + break; + + case UDAT_ZODIAC_NAMES_WIDE: + syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); + break; + + case UDAT_ZODIAC_NAMES_ABBREVIATED: + syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); + break; + + case UDAT_ZODIAC_NAMES_NARROW: + syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); + break; + + case UADAT_CYCLIC_ZODIAC_NAMES: + syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); + break; + } return count; @@ -473,6 +1027,13 @@ public: 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) @@ -487,6 +1048,34 @@ public: 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) @@ -501,6 +1090,90 @@ public: 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 + setShortYearNames(DateFormatSymbols *syms, int32_t index, + const UChar *value, int32_t valueLength, UErrorCode &errorCode) + { + setSymbol(syms->fShortYearNames, syms->fShortYearNamesCount, index, value, valueLength, errorCode); + } + + static void + setShortZodiacNames(DateFormatSymbols *syms, int32_t index, + const UChar *value, int32_t valueLength, UErrorCode &errorCode) + { + setSymbol(syms->fShortZodiacNames, syms->fShortZodiacNamesCount, index, value, valueLength, errorCode); + } + static void setAmPm(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) @@ -526,6 +1199,7 @@ udat_setSymbols( UDateFormat *format, int32_t valueLength, UErrorCode *status) { + verifyIsSimpleDateFormat(format, status); if(U_FAILURE(*status)) return; DateFormatSymbols *syms = (DateFormatSymbols *)((SimpleDateFormat *)format)->getDateFormatSymbols(); @@ -535,6 +1209,10 @@ udat_setSymbols( UDateFormat *format, 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; @@ -543,6 +1221,22 @@ udat_setSymbols( UDateFormat *format, 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; @@ -551,6 +1245,54 @@ udat_setSymbols( UDateFormat *format, 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_CYCLIC_YEARS_ABBREVIATED: + DateFormatSymbolsSingleSetter::setShortYearNames(syms, index, value, valueLength, *status); + break; + + case UDAT_ZODIAC_NAMES_ABBREVIATED: + DateFormatSymbolsSingleSetter::setShortZodiacNames(syms, index, value, valueLength, *status); + break; + case UDAT_AM_PMS: DateFormatSymbolsSingleSetter::setAmPm(syms, index, value, valueLength, *status); break; @@ -558,6 +1300,11 @@ udat_setSymbols( UDateFormat *format, case UDAT_LOCALIZED_CHARS: DateFormatSymbolsSingleSetter::setLocalPatternChars(syms, value, valueLength, *status); break; + + default: + *status = U_UNSUPPORTED_ERROR; + break; + } } @@ -574,4 +1321,103 @@ udat_getLocaleByType(const UDateFormat *fmt, } return ((Format*)fmt)->getLocaleID(type, *status); } + +U_CAPI void U_EXPORT2 +udat_setContext(UDateFormat* fmt, UDisplayContext value, UErrorCode* status) +{ + if (U_FAILURE(*status)) { + return; + } + ((DateFormat*)fmt)->setContext(value, *status); + return; +} + +U_CAPI UDisplayContext U_EXPORT2 +udat_getContext(const UDateFormat* fmt, UDisplayContextType type, UErrorCode* status) +{ + if (U_FAILURE(*status)) { + return (UDisplayContext)0; + } + return ((const DateFormat*)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(reinterpret_cast(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; + } + if (result == NULL ? resultLength != 0 : resultLength < 0) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return -1; + } + + UnicodeString datePattern; + if (result != NULL) { + // 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; + } + if (result == NULL ? resultLength != 0 : resultLength < 0) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return -1; + } + + UnicodeString timePattern; + if (result != NULL) { + // 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 */