]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/udat.cpp
ICU-66108.tar.gz
[apple/icu.git] / icuSources / i18n / udat.cpp
index 47bfe96c97d2864a5e371503ccc153f6bfdd0659..f6a04b053debbfd614e47fe945dc6b70d018e7ab 100644 (file)
@@ -1,6 +1,8 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
 /*
 *******************************************************************************
 /*
 *******************************************************************************
-*   Copyright (C) 1996-2014, International Business Machines
+*   Copyright (C) 1996-2015, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *******************************************************************************
 */
 *   Corporation and others.  All Rights Reserved.
 *******************************************************************************
 */
@@ -22,6 +24,8 @@
 #include "unicode/dtfmtsym.h"
 #include "unicode/ustring.h"
 #include "unicode/udisplaycontext.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"
 #include "cpputils.h"
 #include "reldtfmt.h"
 #include "umutex.h"
@@ -79,13 +83,24 @@ static UCalendarDateFields gDateFieldMapping[] = {
     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_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_FIELD_COUNT = 35
+    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) {
     // UCAL_IS_LEAP_MONTH is not the target of a mapping
 };
 
 U_CAPI UCalendarDateFields U_EXPORT2
 udat_toCalendarDateField(UDateFormatField field) {
-  return gDateFieldMapping[field];
+  return (field >= UDAT_ERA_FIELD && field < UDAT_FIELD_COUNT)? gDateFieldMapping[field]: UCAL_FIELD_COUNT;
+}
+
+// for Apple <rdar://problem/62136559>
+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. */
 }
 
 /* For now- one opener. */
@@ -164,9 +179,13 @@ udat_open(UDateFormatStyle  timeStyle,
         }
     }
 
         }
     }
 
-    if(fmt == 0) {
+    if(fmt == nullptr) {
         *status = U_MEMORY_ALLOCATION_ERROR;
         *status = U_MEMORY_ALLOCATION_ERROR;
-        return 0;
+        return nullptr;
+    }
+    if (U_FAILURE(*status)) {
+        delete fmt;
+        return nullptr;
     }
 
     if(tzID != 0) {
     }
 
     if(tzID != 0) {
@@ -213,10 +232,16 @@ udat_format(    const    UDateFormat*    format,
         UFieldPosition* position,
         UErrorCode*     status)
 {
         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;
 
     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);
         // NULL destination for pure preflighting: empty dummy string
         // otherwise, alias the destination buffer
         res.setTo(result, 0, resultLength);
@@ -237,6 +262,100 @@ udat_format(    const    UDateFormat*    format,
     return res.extract(result, resultLength, *status);
 }
 
     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,
 U_CAPI UDate U_EXPORT2
 udat_parse(    const    UDateFormat*        format,
         const    UChar*          text,
@@ -281,19 +400,21 @@ udat_parseCalendar(const    UDateFormat*    format,
 
     const UnicodeString src((UBool)(textLength == -1), text, textLength);
     ParsePosition pp;
 
     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);
 
 
     ((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;
     }
 }
 
     }
 }
 
@@ -343,12 +464,36 @@ udat_setCalendar(UDateFormat*    fmt,
     ((DateFormat*)fmt)->setCalendar(*((Calendar*)calendarToSet));
 }
 
     ((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_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)
 U_CAPI void U_EXPORT2
 udat_setNumberFormat(UDateFormat*    fmt,
                      const   UNumberFormat*  numberFormatToSet)
@@ -356,6 +501,13 @@ udat_setNumberFormat(UDateFormat*    fmt,
     ((DateFormat*)fmt)->setNumberFormat(*((NumberFormat*)numberFormatToSet));
 }
 
     ((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)
 {
 U_CAPI const char* U_EXPORT2
 udat_getAvailable(int32_t index)
 {
@@ -394,10 +546,16 @@ udat_toPattern(    const   UDateFormat     *fmt,
         int32_t         resultLength,
         UErrorCode      *status)
 {
         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;
 
     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);
         // NULL destination for pure preflighting: empty dummy string
         // otherwise, alias the destination buffer
         res.setTo(result, 0, resultLength);
@@ -443,6 +601,51 @@ udat_applyPattern(  UDateFormat     *format,
         ((SimpleDateFormat*)format)->applyPattern(pat);
 }
 
         ((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,
 U_CAPI int32_t U_EXPORT2
 udat_getSymbols(const   UDateFormat     *fmt,
                 UDateFormatSymbolType   type,
@@ -454,14 +657,17 @@ udat_getSymbols(const   UDateFormat     *fmt,
     const DateFormatSymbols *syms;
     const SimpleDateFormat* sdtfmt;
     const RelativeDateFormat* rdtfmt;
     const DateFormatSymbols *syms;
     const SimpleDateFormat* sdtfmt;
     const RelativeDateFormat* rdtfmt;
+    BreakIterator* capitalizationBrkIter;
     if ((sdtfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
         syms = sdtfmt->getDateFormatSymbols();
     if ((sdtfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
         syms = sdtfmt->getDateFormatSymbols();
+        capitalizationBrkIter = sdtfmt->getCapitalizationBrkIter();
     } else if ((rdtfmt = dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
         syms = rdtfmt->getDateFormatSymbols();
     } else if ((rdtfmt = dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
         syms = rdtfmt->getDateFormatSymbols();
+        capitalizationBrkIter = rdtfmt->getCapitalizationBrkIter();
     } else {
         return -1;
     }
     } else {
         return -1;
     }
-    int32_t count;
+    int32_t count = 0;
     const UnicodeString *res = NULL;
 
     switch(type) {
     const UnicodeString *res = NULL;
 
     switch(type) {
@@ -561,14 +767,72 @@ udat_getSymbols(const   UDateFormat     *fmt,
         res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
         break;
 
         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:
     case UADAT_CYCLIC_ZODIAC_NAMES:
-        res = syms->getZodiacNames(count);
+        res = syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
         index = (index > 0)? (index - 1) % 12: 0;
         break;
 
     }
 
     if(index < count) {
         index = (index > 0)? (index - 1) % 12: 0;
         break;
 
     }
 
     if(index < count) {
+#if !UCONFIG_NO_BREAK_ITERATION
+        // Apple addition for <rdar://problem/27335144>
+        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;
         return res[index].extract(result, resultLength, *status);
     }
     return 0;
@@ -680,10 +944,35 @@ udat_countSymbols(    const    UDateFormat                *fmt,
         syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
         break;
 
         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:
      case UADAT_CYCLIC_ZODIAC_NAMES:
-        syms->getZodiacNames(count);
+        syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
         break;
         break;
-   }
+
+    }
 
     return count;
 }
 
     return count;
 }
@@ -871,6 +1160,20 @@ public:
         setSymbol(syms->fStandaloneShortQuarters, syms->fStandaloneShortQuartersCount, index, value, valueLength, 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)
     static void
         setAmPm(DateFormatSymbols *syms, int32_t index,
         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
@@ -982,6 +1285,14 @@ udat_setSymbols(    UDateFormat             *format,
         DateFormatSymbolsSingleSetter::setStandaloneShortQuarter(syms, index, value, valueLength, *status);
         break;
 
         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;
     case UDAT_AM_PMS:
         DateFormatSymbolsSingleSetter::setAmPm(syms, index, value, valueLength, *status);
         break;
@@ -1051,10 +1362,16 @@ udat_toPatternRelativeDate(const UDateFormat *fmt,
                            UErrorCode        *status)
 {
     verifyIsRelativeDateFormat(fmt, status);
                            UErrorCode        *status)
 {
     verifyIsRelativeDateFormat(fmt, 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 datePattern;
 
     UnicodeString datePattern;
-    if(!(result==NULL && resultLength==0)) {
+    if (result != NULL) {
         // NULL destination for pure preflighting: empty dummy string
         // otherwise, alias the destination buffer
         datePattern.setTo(result, 0, resultLength);
         // NULL destination for pure preflighting: empty dummy string
         // otherwise, alias the destination buffer
         datePattern.setTo(result, 0, resultLength);
@@ -1070,10 +1387,16 @@ udat_toPatternRelativeTime(const UDateFormat *fmt,
                            UErrorCode        *status)
 {
     verifyIsRelativeDateFormat(fmt, status);
                            UErrorCode        *status)
 {
     verifyIsRelativeDateFormat(fmt, 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 timePattern;
 
     UnicodeString timePattern;
-    if(!(result==NULL && resultLength==0)) {
+    if (result != NULL) {
         // NULL destination for pure preflighting: empty dummy string
         // otherwise, alias the destination buffer
         timePattern.setTo(result, 0, resultLength);
         // NULL destination for pure preflighting: empty dummy string
         // otherwise, alias the destination buffer
         timePattern.setTo(result, 0, resultLength);