| Index: source/i18n/smpdtfmt.cpp
|
| diff --git a/source/i18n/smpdtfmt.cpp b/source/i18n/smpdtfmt.cpp
|
| index 28fd78f982d5607ffcda0c1c46c0663065ac8a6f..901664115cc773d2b57651e90f2de01a8c12871c 100644
|
| --- a/source/i18n/smpdtfmt.cpp
|
| +++ b/source/i18n/smpdtfmt.cpp
|
| @@ -1,6 +1,6 @@
|
| /*
|
| *******************************************************************************
|
| -* Copyright (C) 1997-2013, International Business Machines Corporation and *
|
| +* Copyright (C) 1997-2014, International Business Machines Corporation and *
|
| * others. All Rights Reserved. *
|
| *******************************************************************************
|
| *
|
| @@ -29,7 +29,6 @@
|
| #include "unicode/utypes.h"
|
|
|
| #if !UCONFIG_NO_FORMATTING
|
| -
|
| #include "unicode/smpdtfmt.h"
|
| #include "unicode/dtfmtsym.h"
|
| #include "unicode/ures.h"
|
| @@ -49,6 +48,7 @@
|
| #include "unicode/utf16.h"
|
| #include "unicode/vtzone.h"
|
| #include "unicode/udisplaycontext.h"
|
| +#include "unicode/brkiter.h"
|
| #include "olsontz.h"
|
| #include "patternprops.h"
|
| #include "fphdlimp.h"
|
| @@ -125,8 +125,9 @@ static const UDateFormatField kDateFields[] = {
|
| UDAT_STANDALONE_MONTH_FIELD,
|
| UDAT_QUARTER_FIELD,
|
| UDAT_STANDALONE_QUARTER_FIELD,
|
| - UDAT_YEAR_NAME_FIELD };
|
| -static const int8_t kDateFieldsCount = 15;
|
| + UDAT_YEAR_NAME_FIELD,
|
| + UDAT_RELATED_YEAR_FIELD };
|
| +static const int8_t kDateFieldsCount = 16;
|
|
|
| static const UDateFormatField kTimeFields[] = {
|
| UDAT_HOUR_OF_DAY1_FIELD,
|
| @@ -202,11 +203,12 @@ static const int32_t gFieldRangeBias[] = {
|
| 1, // 'L' - UDAT_STANDALONE_MONTH_FIELD
|
| -1, // 'Q' - UDAT_QUARTER_FIELD (1-4?)
|
| -1, // 'q' - UDAT_STANDALONE_QUARTER_FIELD
|
| - -1 // 'V' - UDAT_TIMEZONE_SPECIAL_FIELD
|
| + -1, // 'V' - UDAT_TIMEZONE_SPECIAL_FIELD
|
| -1, // 'U' - UDAT_YEAR_NAME_FIELD
|
| -1, // 'O' - UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD
|
| -1, // 'X' - UDAT_TIMEZONE_ISO_FIELD
|
| -1, // 'x' - UDAT_TIMEZONE_ISO_LOCAL_FIELD
|
| + -1, // 'r' - UDAT_RELATED_YEAR_FIELD
|
| };
|
|
|
| // When calendar uses hebr numbering (i.e. he@calendar=hebrew),
|
| @@ -236,6 +238,10 @@ SimpleDateFormat::~SimpleDateFormat()
|
| delete cur->nf;
|
| uprv_free(cur);
|
| }
|
| +
|
| +#if !UCONFIG_NO_BREAK_ITERATION
|
| + delete fCapitalizationBrkIter;
|
| +#endif
|
| }
|
|
|
| //----------------------------------------------------------------------
|
| @@ -246,9 +252,9 @@ SimpleDateFormat::SimpleDateFormat(UErrorCode& status)
|
| fTimeZoneFormat(NULL),
|
| fNumberFormatters(NULL),
|
| fOverrideList(NULL),
|
| - fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
|
| + fCapitalizationBrkIter(NULL)
|
| {
|
| - setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
|
| + initializeBooleanAttributes();
|
| construct(kShort, (EStyle) (kShort + kDateOffset), fLocale, status);
|
| initializeDefaultCentury();
|
| }
|
| @@ -263,11 +269,11 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
| fTimeZoneFormat(NULL),
|
| fNumberFormatters(NULL),
|
| fOverrideList(NULL),
|
| - fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
|
| + fCapitalizationBrkIter(NULL)
|
| {
|
| fDateOverride.setToBogus();
|
| fTimeOverride.setToBogus();
|
| - setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
|
| + initializeBooleanAttributes();
|
| initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
|
| initialize(fLocale, status);
|
| initializeDefaultCentury();
|
| @@ -284,11 +290,11 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
| fTimeZoneFormat(NULL),
|
| fNumberFormatters(NULL),
|
| fOverrideList(NULL),
|
| - fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
|
| + fCapitalizationBrkIter(NULL)
|
| {
|
| fDateOverride.setTo(override);
|
| fTimeOverride.setToBogus();
|
| - setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
|
| + initializeBooleanAttributes();
|
| initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
|
| initialize(fLocale, status);
|
| initializeDefaultCentury();
|
| @@ -307,12 +313,12 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
| fTimeZoneFormat(NULL),
|
| fNumberFormatters(NULL),
|
| fOverrideList(NULL),
|
| - fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
|
| + fCapitalizationBrkIter(NULL)
|
| {
|
|
|
| fDateOverride.setToBogus();
|
| fTimeOverride.setToBogus();
|
| - setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
|
| + initializeBooleanAttributes();
|
|
|
| initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
|
| initialize(fLocale, status);
|
| @@ -330,12 +336,12 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
| fTimeZoneFormat(NULL),
|
| fNumberFormatters(NULL),
|
| fOverrideList(NULL),
|
| - fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
|
| + fCapitalizationBrkIter(NULL)
|
| {
|
|
|
| fDateOverride.setTo(override);
|
| fTimeOverride.setToBogus();
|
| - setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
|
| + initializeBooleanAttributes();
|
|
|
| initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
|
| initialize(fLocale, status);
|
| @@ -356,12 +362,12 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
| fTimeZoneFormat(NULL),
|
| fNumberFormatters(NULL),
|
| fOverrideList(NULL),
|
| - fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
|
| + fCapitalizationBrkIter(NULL)
|
| {
|
|
|
| fDateOverride.setToBogus();
|
| fTimeOverride.setToBogus();
|
| - setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
|
| + initializeBooleanAttributes();
|
|
|
| initializeCalendar(NULL,fLocale,status);
|
| initialize(fLocale, status);
|
| @@ -379,12 +385,12 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
| fTimeZoneFormat(NULL),
|
| fNumberFormatters(NULL),
|
| fOverrideList(NULL),
|
| - fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
|
| + fCapitalizationBrkIter(NULL)
|
| {
|
|
|
| fDateOverride.setToBogus();
|
| fTimeOverride.setToBogus();
|
| - setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
|
| + initializeBooleanAttributes();
|
|
|
| initializeCalendar(NULL, fLocale, status);
|
| initialize(fLocale, status);
|
| @@ -403,9 +409,9 @@ SimpleDateFormat::SimpleDateFormat(EStyle timeStyle,
|
| fTimeZoneFormat(NULL),
|
| fNumberFormatters(NULL),
|
| fOverrideList(NULL),
|
| - fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
|
| + fCapitalizationBrkIter(NULL)
|
| {
|
| - setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
|
| + initializeBooleanAttributes();
|
| construct(timeStyle, dateStyle, fLocale, status);
|
| if(U_SUCCESS(status)) {
|
| initializeDefaultCentury();
|
| @@ -427,9 +433,10 @@ SimpleDateFormat::SimpleDateFormat(const Locale& locale,
|
| fTimeZoneFormat(NULL),
|
| fNumberFormatters(NULL),
|
| fOverrideList(NULL),
|
| - fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
|
| + fCapitalizationBrkIter(NULL)
|
| {
|
| if (U_FAILURE(status)) return;
|
| + initializeBooleanAttributes();
|
| initializeSymbols(fLocale, initializeCalendar(NULL, fLocale, status),status);
|
| if (U_FAILURE(status))
|
| {
|
| @@ -446,7 +453,6 @@ SimpleDateFormat::SimpleDateFormat(const Locale& locale,
|
|
|
| fDateOverride.setToBogus();
|
| fTimeOverride.setToBogus();
|
| - setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
|
|
|
| initialize(fLocale, status);
|
| if(U_SUCCESS(status)) {
|
| @@ -463,10 +469,9 @@ SimpleDateFormat::SimpleDateFormat(const SimpleDateFormat& other)
|
| fTimeZoneFormat(NULL),
|
| fNumberFormatters(NULL),
|
| fOverrideList(NULL),
|
| - fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
|
| + fCapitalizationBrkIter(NULL)
|
| {
|
| - UErrorCode status = U_ZERO_ERROR;
|
| - setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
|
| + initializeBooleanAttributes();
|
| *this = other;
|
| }
|
|
|
| @@ -498,7 +503,11 @@ SimpleDateFormat& SimpleDateFormat::operator=(const SimpleDateFormat& other)
|
| fLocale = other.fLocale;
|
| }
|
|
|
| - fCapitalizationContext = other.fCapitalizationContext;
|
| +#if !UCONFIG_NO_BREAK_ITERATION
|
| + if (other.fCapitalizationBrkIter != NULL) {
|
| + fCapitalizationBrkIter = (other.fCapitalizationBrkIter)->clone();
|
| + }
|
| +#endif
|
|
|
| return *this;
|
| }
|
| @@ -517,6 +526,8 @@ UBool
|
| SimpleDateFormat::operator==(const Format& other) const
|
| {
|
| if (DateFormat::operator==(other)) {
|
| + // The DateFormat::operator== check for fCapitalizationContext equality above
|
| + // is sufficient to check equality of all derived context-related data.
|
| // DateFormat::operator== guarantees following cast is safe
|
| SimpleDateFormat* that = (SimpleDateFormat*)&other;
|
| return (fPattern == that->fPattern &&
|
| @@ -524,8 +535,7 @@ SimpleDateFormat::operator==(const Format& other) const
|
| that->fSymbols != NULL && // Check for pathological object
|
| *fSymbols == *that->fSymbols &&
|
| fHaveDefaultCentury == that->fHaveDefaultCentury &&
|
| - fDefaultCenturyStart == that->fDefaultCenturyStart &&
|
| - fCapitalizationContext == that->fCapitalizationContext);
|
| + fDefaultCenturyStart == that->fDefaultCenturyStart);
|
| }
|
| return FALSE;
|
| }
|
| @@ -804,6 +814,19 @@ void SimpleDateFormat::initializeDefaultCentury()
|
| }
|
| }
|
|
|
| +/*
|
| + * Initialize the boolean attributes. Separate so we can call it from all constructors.
|
| + */
|
| +void SimpleDateFormat::initializeBooleanAttributes()
|
| +{
|
| + UErrorCode status = U_ZERO_ERROR;
|
| +
|
| + setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status);
|
| + setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
|
| + setBooleanAttribute(UDAT_PARSE_PARTIAL_MATCH, true, status);
|
| + setBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, true, status);
|
| +}
|
| +
|
| /* Define one-century window into which to disambiguate dates using
|
| * two-digit years. Make public in JDK 1.2.
|
| */
|
| @@ -876,6 +899,7 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo,
|
| UChar prevCh = 0;
|
| int32_t count = 0;
|
| int32_t fieldNum = 0;
|
| + UDisplayContext capitalizationContext = getContext(UDISPCTX_TYPE_CAPITALIZATION, status);
|
|
|
| // loop through the pattern string character by character
|
| for (int32_t i = 0; i < fPattern.length() && U_SUCCESS(status); ++i) {
|
| @@ -884,7 +908,7 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo,
|
| // Use subFormat() to format a repeated pattern character
|
| // when a different pattern or non-pattern character is seen
|
| if (ch != prevCh && count > 0) {
|
| - subFormat(appendTo, prevCh, count, fCapitalizationContext, fieldNum++, handler, *workCal, status);
|
| + subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, status);
|
| count = 0;
|
| }
|
| if (ch == QUOTE) {
|
| @@ -912,7 +936,7 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo,
|
|
|
| // Format the last item in the pattern, if any
|
| if (count > 0) {
|
| - subFormat(appendTo, prevCh, count, fCapitalizationContext, fieldNum++, handler, *workCal, status);
|
| + subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, status);
|
| }
|
|
|
| if (calClone != NULL) {
|
| @@ -937,10 +961,10 @@ SimpleDateFormat::fgCalendarFieldToLevel[] =
|
| /*wW*/ 20, 30,
|
| /*dDEF*/ 30, 20, 30, 30,
|
| /*ahHm*/ 40, 50, 50, 60,
|
| - /*sS..*/ 70, 80,
|
| + /*sS*/ 70, 80,
|
| /*z?Y*/ 0, 0, 10,
|
| /*eug*/ 30, 10, 0,
|
| - /*A*/ 40
|
| + /*A?.*/ 40, 0, 0
|
| };
|
|
|
|
|
| @@ -957,7 +981,7 @@ SimpleDateFormat::fgPatternCharToLevel[] = {
|
| // a b c d e f g h i j k l m n o
|
| -1, 40, -1, 30, 30, 30, -1, 0, 50, -1, -1, 50, -1, 60, -1, -1,
|
| // p q r s t u v w x y z
|
| - -1, 20, -1, 70, -1, 10, 0, 20, 0, 10, 0, -1, -1, -1, -1, -1
|
| + -1, 20, 10, 70, -1, 10, 0, 20, 0, 10, 0, -1, -1, -1, -1, -1
|
| };
|
|
|
|
|
| @@ -982,6 +1006,7 @@ SimpleDateFormat::fgPatternIndexToCalendarField[] =
|
| /*U*/ UCAL_YEAR,
|
| /*O*/ UCAL_ZONE_OFFSET,
|
| /*Xx*/ UCAL_ZONE_OFFSET, UCAL_ZONE_OFFSET,
|
| + /*r*/ UCAL_EXTENDED_YEAR,
|
| };
|
|
|
| // Map index into pattern character string to DateFormat field number
|
| @@ -1004,6 +1029,7 @@ SimpleDateFormat::fgPatternIndexToDateFormatField[] = {
|
| /*U*/ UDAT_YEAR_NAME_FIELD,
|
| /*O*/ UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD,
|
| /*Xx*/ UDAT_TIMEZONE_ISO_FIELD, UDAT_TIMEZONE_ISO_LOCAL_FIELD,
|
| + /*r*/ UDAT_RELATED_YEAR_FIELD,
|
| };
|
|
|
| //----------------------------------------------------------------------
|
| @@ -1059,16 +1085,22 @@ SimpleDateFormat::initNumberFormatters(const Locale &locale,UErrorCode &status)
|
| }
|
| umtx_unlock(&LOCK);
|
|
|
| + if (U_FAILURE(status)) {
|
| + return;
|
| + }
|
| +
|
| processOverrideString(locale,fDateOverride,kOvrStrDate,status);
|
| processOverrideString(locale,fTimeOverride,kOvrStrTime,status);
|
| -
|
| }
|
|
|
| void
|
| SimpleDateFormat::processOverrideString(const Locale &locale, const UnicodeString &str, int8_t type, UErrorCode &status) {
|
| - if (str.isBogus()) {
|
| + if (str.isBogus() || U_FAILURE(status)) {
|
| return;
|
| }
|
| +
|
| + U_ASSERT(fNumberFormatters != NULL);
|
| +
|
| int32_t start = 0;
|
| int32_t len;
|
| UnicodeString nsName;
|
| @@ -1150,7 +1182,6 @@ SimpleDateFormat::processOverrideString(const Locale &locale, const UnicodeStrin
|
|
|
| // Now that we have an appropriate number formatter, fill in the appropriate spaces in the
|
| // number formatters table.
|
| -
|
| if (ovrField.isBogus()) {
|
| switch (type) {
|
| case kOvrStrDate:
|
| @@ -1223,7 +1254,7 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
|
| }
|
|
|
| UCalendarDateFields field = fgPatternIndexToCalendarField[patternCharIndex];
|
| - int32_t value = cal.get(field, status);
|
| + int32_t value = (patternCharIndex != UDAT_RELATED_YEAR_FIELD)? cal.get(field, status): cal.getRelatedYear(status);
|
| if (U_FAILURE(status)) {
|
| return;
|
| }
|
| @@ -1592,8 +1623,8 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
|
| break;
|
| }
|
| #if !UCONFIG_NO_BREAK_ITERATION
|
| - if (fieldNum == 0) {
|
| - // first field, check to see whether we need to titlecase it
|
| + // if first field, check to see whether we need to and are able to titlecase it
|
| + if (fieldNum == 0 && u_islower(appendTo.char32At(beginOffset)) && fCapitalizationBrkIter != NULL) {
|
| UBool titlecase = FALSE;
|
| switch (capitalizationContext) {
|
| case UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE:
|
| @@ -1611,7 +1642,7 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
|
| }
|
| if (titlecase) {
|
| UnicodeString firstField(appendTo, beginOffset);
|
| - firstField.toTitle(NULL, fLocale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
|
| + firstField.toTitle(fCapitalizationBrkIter, fLocale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
|
| appendTo.replaceBetween(beginOffset, appendTo.length(), firstField);
|
| }
|
| }
|
| @@ -1622,6 +1653,104 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
|
|
|
| //----------------------------------------------------------------------
|
|
|
| +void SimpleDateFormat::adoptNumberFormat(NumberFormat *formatToAdopt) {
|
| + formatToAdopt->setParseIntegerOnly(TRUE);
|
| + if (fNumberFormat && fNumberFormat != formatToAdopt){
|
| + delete fNumberFormat;
|
| + }
|
| + fNumberFormat = formatToAdopt;
|
| +
|
| + if (fNumberFormatters) {
|
| + for (int32_t i = 0; i < UDAT_FIELD_COUNT; i++) {
|
| + if (fNumberFormatters[i] == formatToAdopt) {
|
| + fNumberFormatters[i] = NULL;
|
| + }
|
| + }
|
| + uprv_free(fNumberFormatters);
|
| + fNumberFormatters = NULL;
|
| + }
|
| +
|
| + while (fOverrideList) {
|
| + NSOverride *cur = fOverrideList;
|
| + fOverrideList = cur->next;
|
| + if (cur->nf != formatToAdopt) { // only delete those not duplicate
|
| + delete cur->nf;
|
| + uprv_free(cur);
|
| + } else {
|
| + cur->nf = NULL;
|
| + uprv_free(cur);
|
| + }
|
| + }
|
| +}
|
| +
|
| +void SimpleDateFormat::adoptNumberFormat(const UnicodeString& fields, NumberFormat *formatToAdopt, UErrorCode &status){
|
| + // if it has not been initialized yet, initialize
|
| + if (fNumberFormatters == NULL) {
|
| + fNumberFormatters = (NumberFormat**)uprv_malloc(UDAT_FIELD_COUNT * sizeof(NumberFormat*));
|
| + if (fNumberFormatters) {
|
| + for (int32_t i = 0; i < UDAT_FIELD_COUNT; i++) {
|
| + fNumberFormatters[i] = fNumberFormat;
|
| + }
|
| + } else {
|
| + status = U_MEMORY_ALLOCATION_ERROR;
|
| + return;
|
| + }
|
| + }
|
| +
|
| + // See if the numbering format is in the override list, if not, then add it.
|
| + NSOverride *cur = fOverrideList;
|
| + UBool found = FALSE;
|
| + while (cur && !found) {
|
| + if ( cur->nf == formatToAdopt ) {
|
| + found = TRUE;
|
| + }
|
| + cur = cur->next;
|
| + }
|
| +
|
| + if (!found) {
|
| + cur = (NSOverride *)uprv_malloc(sizeof(NSOverride));
|
| + if (cur) {
|
| + // no matter what the locale's default number format looked like, we want
|
| + // to modify it so that it doesn't use thousands separators, doesn't always
|
| + // show the decimal point, and recognizes integers only when parsing
|
| + formatToAdopt->setGroupingUsed(FALSE);
|
| + DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(formatToAdopt);
|
| + if (decfmt != NULL) {
|
| + decfmt->setDecimalSeparatorAlwaysShown(FALSE);
|
| + }
|
| + formatToAdopt->setParseIntegerOnly(TRUE);
|
| + formatToAdopt->setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
|
| +
|
| + cur->nf = formatToAdopt;
|
| + cur->hash = -1; // set duplicate here (before we set it with NumberSystem Hash, here we cannot get nor use it)
|
| + cur->next = fOverrideList;
|
| + fOverrideList = cur;
|
| + } else {
|
| + status = U_MEMORY_ALLOCATION_ERROR;
|
| + return;
|
| + }
|
| + }
|
| +
|
| + for (int i=0; i<fields.length(); i++) {
|
| + UChar field = fields.charAt(i);
|
| + // if the pattern character is unrecognized, signal an error and bail out
|
| + UDateFormatField patternCharIndex = DateFormatSymbols::getPatternCharIndex(field);
|
| + if (patternCharIndex == UDAT_FIELD_COUNT) {
|
| + status = U_INVALID_FORMAT_ERROR;
|
| + return;
|
| + }
|
| +
|
| + // Set the number formatter in the table
|
| + fNumberFormatters[patternCharIndex] = formatToAdopt;
|
| + }
|
| +}
|
| +
|
| +const NumberFormat *
|
| +SimpleDateFormat::getNumberFormatForField(UChar field) const {
|
| + UDateFormatField index = DateFormatSymbols::getPatternCharIndex(field);
|
| + return getNumberFormatByIndex(index);
|
| +}
|
| +
|
| NumberFormat *
|
| SimpleDateFormat::getNumberFormatByIndex(UDateFormatField index) const {
|
| if (fNumberFormatters != NULL) {
|
| @@ -1694,14 +1823,17 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
| {
|
| UErrorCode status = U_ZERO_ERROR;
|
| int32_t pos = parsePos.getIndex();
|
| + if(parsePos.getIndex() < 0) {
|
| + parsePos.setErrorIndex(0);
|
| + return;
|
| + }
|
| int32_t start = pos;
|
|
|
| +
|
| UBool ambiguousYear[] = { FALSE };
|
| int32_t saveHebrewMonth = -1;
|
| int32_t count = 0;
|
| -
|
| - // hack, reset tztype, cast away const
|
| - ((SimpleDateFormat*)this)->tztype = UTZFMT_TIME_TYPE_UNKNOWN;
|
| + UTimeZoneFormatTimeType tzTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
|
|
|
| // For parsing abutting numeric fields. 'abutPat' is the
|
| // offset into 'pattern' of the first of 2 or more abutting
|
| @@ -1795,7 +1927,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
| }
|
|
|
| pos = subParse(text, pos, ch, count,
|
| - TRUE, FALSE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter);
|
| + TRUE, FALSE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter, &tzTimeType);
|
|
|
| // If the parse fails anywhere in the run, back up to the
|
| // start of the run and retry.
|
| @@ -1810,7 +1942,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
| // fields.
|
| else if (ch != 0x6C) { // pattern char 'l' (SMALL LETTER L) just gets ignored
|
| int32_t s = subParse(text, pos, ch, count,
|
| - FALSE, TRUE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter);
|
| + FALSE, TRUE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter, &tzTimeType);
|
|
|
| if (s == -pos-1) {
|
| // era not present, in special cases allow this to continue
|
| @@ -1847,7 +1979,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
|
|
| abutPat = -1; // End of any abutting fields
|
|
|
| - if (! matchLiterals(fPattern, i, text, pos, getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status))) {
|
| + if (! matchLiterals(fPattern, i, text, pos, getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status), getBooleanAttribute(UDAT_PARSE_PARTIAL_MATCH, status), isLenient())) {
|
| status = U_PARSE_ERROR;
|
| goto ExitParse;
|
| }
|
| @@ -1890,7 +2022,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
| // when the two-digit year is equal to the start year, and thus might fall at the
|
| // front or the back of the default century. This only works because we adjust
|
| // the year correctly to start with in other cases -- see subParse().
|
| - if (ambiguousYear[0] || tztype != UTZFMT_TIME_TYPE_UNKNOWN) // If this is true then the two-digit year == the default start year
|
| + if (ambiguousYear[0] || tzTimeType != UTZFMT_TIME_TYPE_UNKNOWN) // If this is true then the two-digit year == the default start year
|
| {
|
| // We need a copy of the fields, and we need to avoid triggering a call to
|
| // complete(), which will recalculate the fields. Since we can't access
|
| @@ -1913,7 +2045,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
| delete copy;
|
| }
|
|
|
| - if (tztype != UTZFMT_TIME_TYPE_UNKNOWN) {
|
| + if (tzTimeType != UTZFMT_TIME_TYPE_UNKNOWN) {
|
| copy = cal.clone();
|
| // Check for failed cloning.
|
| if (copy == NULL) {
|
| @@ -1939,7 +2071,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
| // matches the rule used by the parsed time zone.
|
| int32_t raw, dst;
|
| if (btz != NULL) {
|
| - if (tztype == UTZFMT_TIME_TYPE_STANDARD) {
|
| + if (tzTimeType == UTZFMT_TIME_TYPE_STANDARD) {
|
| btz->getOffsetFromLocal(localMillis,
|
| BasicTimeZone::kStandard, BasicTimeZone::kStandard, raw, dst, status);
|
| } else {
|
| @@ -1954,7 +2086,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
|
|
| // Now, compare the results with parsed type, either standard or daylight saving time
|
| int32_t resolvedSavings = dst;
|
| - if (tztype == UTZFMT_TIME_TYPE_STANDARD) {
|
| + if (tzTimeType == UTZFMT_TIME_TYPE_STANDARD) {
|
| if (dst != 0) {
|
| // Override DST_OFFSET = 0 in the result calendar
|
| resolvedSavings = 0;
|
| @@ -2129,12 +2261,14 @@ UBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern,
|
| int32_t &patternOffset,
|
| const UnicodeString &text,
|
| int32_t &textOffset,
|
| - UBool lenient)
|
| + UBool whitespaceLenient,
|
| + UBool partialMatchLenient,
|
| + UBool oldLeniency)
|
| {
|
| UBool inQuote = FALSE;
|
| - UnicodeString literal;
|
| + UnicodeString literal;
|
| int32_t i = patternOffset;
|
| -
|
| +
|
| // scan pattern looking for contiguous literal characters
|
| for ( ; i < pattern.length(); i += 1) {
|
| UChar ch = pattern.charAt(i);
|
| @@ -2161,7 +2295,7 @@ UBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern,
|
| int32_t p;
|
| int32_t t = textOffset;
|
|
|
| - if (lenient) {
|
| + if (whitespaceLenient) {
|
| // trim leading, trailing whitespace from
|
| // the literal text
|
| literal.trim();
|
| @@ -2196,7 +2330,7 @@ UBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern,
|
| // TODO: should we require internal spaces
|
| // in lenient mode? (There won't be any
|
| // leading or trailing spaces)
|
| - if (!lenient && t == tStart) {
|
| + if (!whitespaceLenient && t == tStart) {
|
| // didn't find matching whitespace:
|
| // an error in strict mode
|
| return FALSE;
|
| @@ -2208,11 +2342,10 @@ UBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern,
|
| break;
|
| }
|
| }
|
| -
|
| if (t >= text.length() || literal.charAt(p) != text.charAt(t)) {
|
| // Ran out of text, or found a non-matching character:
|
| // OK in lenient mode, an error in strict mode.
|
| - if (lenient) {
|
| + if (whitespaceLenient) {
|
| if (t == textOffset && text.charAt(t) == 0x2e &&
|
| isAfterNonNumericField(pattern, patternOffset)) {
|
| // Lenient mode and the literal input text begins with a "." and
|
| @@ -2220,6 +2353,17 @@ UBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern,
|
| ++t;
|
| continue; // Do not update p.
|
| }
|
| + // if it is actual whitespace and we're whitespace lenient it's OK
|
| +
|
| + UChar wsc = text.charAt(t);
|
| + if(PatternProps::isWhiteSpace(wsc)) {
|
| + // Lenient mode and it's just whitespace we skip it
|
| + ++t;
|
| + continue; // Do not update p.
|
| + }
|
| + }
|
| + // hack around oldleniency being a bit of a catch-all bucket and we're just adding support specifically for paritial matches
|
| + if(partialMatchLenient && oldLeniency) {
|
| break;
|
| }
|
|
|
| @@ -2401,16 +2545,10 @@ SimpleDateFormat::set2DigitYearStart(UDate d, UErrorCode& status)
|
| /**
|
| * Private member function that converts the parsed date strings into
|
| * timeFields. Returns -start (for ParsePosition) if failed.
|
| - * @param text the time text to be parsed.
|
| - * @param start where to start parsing.
|
| - * @param ch the pattern character for the date field text to be parsed.
|
| - * @param count the count of a pattern character.
|
| - * @return the new start position if matching succeeded; a negative number
|
| - * indicating matching failure, otherwise.
|
| */
|
| int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UChar ch, int32_t count,
|
| UBool obeyCount, UBool allowNegative, UBool ambiguousYear[], int32_t& saveHebrewMonth, Calendar& cal,
|
| - int32_t patLoc, MessageFormat * numericLeapMonthFormatter) const
|
| + int32_t patLoc, MessageFormat * numericLeapMonthFormatter, UTimeZoneFormatTimeType *tzTimeType) const
|
| {
|
| Formattable number;
|
| int32_t value = 0;
|
| @@ -2606,22 +2744,22 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
| && u_isdigit(text.charAt(start))
|
| && u_isdigit(text.charAt(start+1)))
|
| {
|
| - // only adjust year for patterns less than 3.
|
| - if(count < 3) {
|
| - // Assume for example that the defaultCenturyStart is 6/18/1903.
|
| - // This means that two-digit years will be forced into the range
|
| - // 6/18/1903 to 6/17/2003. As a result, years 00, 01, and 02
|
| - // correspond to 2000, 2001, and 2002. Years 04, 05, etc. correspond
|
| - // to 1904, 1905, etc. If the year is 03, then it is 2003 if the
|
| - // other fields specify a date before 6/18, or 1903 if they specify a
|
| - // date afterwards. As a result, 03 is an ambiguous year. All other
|
| - // two-digit years are unambiguous.
|
| - if(fHaveDefaultCentury) { // check if this formatter even has a pivot year
|
| - int32_t ambiguousTwoDigitYear = fDefaultCenturyStartYear % 100;
|
| - ambiguousYear[0] = (value == ambiguousTwoDigitYear);
|
| - value += (fDefaultCenturyStartYear/100)*100 +
|
| - (value < ambiguousTwoDigitYear ? 100 : 0);
|
| - }
|
| + // only adjust year for patterns less than 3.
|
| + if(count < 3) {
|
| + // Assume for example that the defaultCenturyStart is 6/18/1903.
|
| + // This means that two-digit years will be forced into the range
|
| + // 6/18/1903 to 6/17/2003. As a result, years 00, 01, and 02
|
| + // correspond to 2000, 2001, and 2002. Years 04, 05, etc. correspond
|
| + // to 1904, 1905, etc. If the year is 03, then it is 2003 if the
|
| + // other fields specify a date before 6/18, or 1903 if they specify a
|
| + // date afterwards. As a result, 03 is an ambiguous year. All other
|
| + // two-digit years are unambiguous.
|
| + if(fHaveDefaultCentury) { // check if this formatter even has a pivot year
|
| + int32_t ambiguousTwoDigitYear = fDefaultCenturyStartYear % 100;
|
| + ambiguousYear[0] = (value == ambiguousTwoDigitYear);
|
| + value += (fDefaultCenturyStartYear/100)*100 +
|
| + (value < ambiguousTwoDigitYear ? 100 : 0);
|
| + }
|
| }
|
| }
|
| cal.set(UCAL_YEAR, value);
|
| @@ -2711,17 +2849,25 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
| }
|
| int32_t newStart = 0;
|
| if (patternCharIndex==UDAT_MONTH_FIELD) {
|
| - newStart = matchString(text, start, UCAL_MONTH, fSymbols->fMonths, fSymbols->fMonthsCount, wideMonthPat, cal); // try MMMM
|
| - if (newStart > 0) {
|
| - return newStart;
|
| + if(getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 4) {
|
| + newStart = matchString(text, start, UCAL_MONTH, fSymbols->fMonths, fSymbols->fMonthsCount, wideMonthPat, cal); // try MMMM
|
| + if (newStart > 0) {
|
| + return newStart;
|
| + }
|
| + }
|
| + if(getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 3) {
|
| + newStart = matchString(text, start, UCAL_MONTH, fSymbols->fShortMonths, fSymbols->fShortMonthsCount, shortMonthPat, cal); // try MMM
|
| }
|
| - newStart = matchString(text, start, UCAL_MONTH, fSymbols->fShortMonths, fSymbols->fShortMonthsCount, shortMonthPat, cal); // try MMM
|
| } else {
|
| - newStart = matchString(text, start, UCAL_MONTH, fSymbols->fStandaloneMonths, fSymbols->fStandaloneMonthsCount, wideMonthPat, cal); // try LLLL
|
| - if (newStart > 0) {
|
| - return newStart;
|
| + if(getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 4) {
|
| + newStart = matchString(text, start, UCAL_MONTH, fSymbols->fStandaloneMonths, fSymbols->fStandaloneMonthsCount, wideMonthPat, cal); // try LLLL
|
| + if (newStart > 0) {
|
| + return newStart;
|
| + }
|
| + }
|
| + if(getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 3) {
|
| + newStart = matchString(text, start, UCAL_MONTH, fSymbols->fStandaloneShortMonths, fSymbols->fStandaloneShortMonthsCount, shortMonthPat, cal); // try LLL
|
| }
|
| - newStart = matchString(text, start, UCAL_MONTH, fSymbols->fStandaloneShortMonths, fSymbols->fStandaloneShortMonthsCount, shortMonthPat, cal); // try LLL
|
| }
|
| if (newStart > 0 || !getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status)) // currently we do not try to parse MMMMM/LLLLL: #8860
|
| return newStart;
|
| @@ -2773,22 +2919,30 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
| // Want to be able to parse both short and long forms.
|
| // Try count == 4 (EEEE) wide first:
|
| int32_t newStart = 0;
|
| - if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
|
| - fSymbols->fWeekdays, fSymbols->fWeekdaysCount, NULL, cal)) > 0)
|
| - return newStart;
|
| + if(getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 4) {
|
| + if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
|
| + fSymbols->fWeekdays, fSymbols->fWeekdaysCount, NULL, cal)) > 0)
|
| + return newStart;
|
| + }
|
| // EEEE wide failed, now try EEE abbreviated
|
| - else if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
|
| - fSymbols->fShortWeekdays, fSymbols->fShortWeekdaysCount, NULL, cal)) > 0)
|
| - return newStart;
|
| + if(getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 3) {
|
| + if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
|
| + fSymbols->fShortWeekdays, fSymbols->fShortWeekdaysCount, NULL, cal)) > 0)
|
| + return newStart;
|
| + }
|
| // EEE abbreviated failed, now try EEEEEE short
|
| - else if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
|
| - fSymbols->fShorterWeekdays, fSymbols->fShorterWeekdaysCount, NULL, cal)) > 0)
|
| - return newStart;
|
| + if(getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 6) {
|
| + if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
|
| + fSymbols->fShorterWeekdays, fSymbols->fShorterWeekdaysCount, NULL, cal)) > 0)
|
| + return newStart;
|
| + }
|
| // EEEEEE short failed, now try EEEEE narrow
|
| - else if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
|
| - fSymbols->fNarrowWeekdays, fSymbols->fNarrowWeekdaysCount, NULL, cal)) > 0)
|
| - return newStart;
|
| - else if (!getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status) || patternCharIndex == UDAT_DAY_OF_WEEK_FIELD)
|
| + if(getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 5) {
|
| + if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
|
| + fSymbols->fNarrowWeekdays, fSymbols->fNarrowWeekdaysCount, NULL, cal)) > 0)
|
| + return newStart;
|
| + }
|
| + if (!getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status) || patternCharIndex == UDAT_DAY_OF_WEEK_FIELD)
|
| return newStart;
|
| // else we allowing parsing as number, below
|
| }
|
| @@ -2805,16 +2959,22 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
| // Want to be able to parse both short and long forms.
|
| // Try count == 4 (cccc) first:
|
| int32_t newStart = 0;
|
| - if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
|
| + if(getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 4) {
|
| + if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
|
| fSymbols->fStandaloneWeekdays, fSymbols->fStandaloneWeekdaysCount, NULL, cal)) > 0)
|
| - return newStart;
|
| - else if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
|
| + return newStart;
|
| + }
|
| + if(getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 3) {
|
| + if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
|
| fSymbols->fStandaloneShortWeekdays, fSymbols->fStandaloneShortWeekdaysCount, NULL, cal)) > 0)
|
| - return newStart;
|
| - else if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
|
| + return newStart;
|
| + }
|
| + if(getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 6) {
|
| + if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
|
| fSymbols->fStandaloneShorterWeekdays, fSymbols->fStandaloneShorterWeekdaysCount, NULL, cal)) > 0)
|
| - return newStart;
|
| - else if (!getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status))
|
| + return newStart;
|
| + }
|
| + if (!getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status))
|
| return newStart;
|
| // else we allowing parsing as number, below
|
| }
|
| @@ -2848,15 +3008,21 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
| // Try count == 4 first:
|
| int32_t newStart = 0;
|
|
|
| - if ((newStart = matchQuarterString(text, start, UCAL_MONTH,
|
| + if(getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 4) {
|
| + if ((newStart = matchQuarterString(text, start, UCAL_MONTH,
|
| fSymbols->fQuarters, fSymbols->fQuartersCount, cal)) > 0)
|
| - return newStart;
|
| - else if ((newStart = matchQuarterString(text, start, UCAL_MONTH,
|
| + return newStart;
|
| + }
|
| + if(getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 3) {
|
| + if ((newStart = matchQuarterString(text, start, UCAL_MONTH,
|
| fSymbols->fShortQuarters, fSymbols->fShortQuartersCount, cal)) > 0)
|
| - return newStart;
|
| - else if (!getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status))
|
| + return newStart;
|
| + }
|
| + if (!getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status))
|
| return newStart;
|
| // else we allowing parsing as number, below
|
| + if(!getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status))
|
| + return -start;
|
| }
|
| break;
|
|
|
| @@ -2874,25 +3040,29 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
| // Try count == 4 first:
|
| int32_t newStart = 0;
|
|
|
| - if ((newStart = matchQuarterString(text, start, UCAL_MONTH,
|
| + if(getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 4) {
|
| + if ((newStart = matchQuarterString(text, start, UCAL_MONTH,
|
| fSymbols->fStandaloneQuarters, fSymbols->fStandaloneQuartersCount, cal)) > 0)
|
| - return newStart;
|
| - else if ((newStart = matchQuarterString(text, start, UCAL_MONTH,
|
| + return newStart;
|
| + }
|
| + if(getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 3) {
|
| + if ((newStart = matchQuarterString(text, start, UCAL_MONTH,
|
| fSymbols->fStandaloneShortQuarters, fSymbols->fStandaloneShortQuartersCount, cal)) > 0)
|
| - return newStart;
|
| - else if (!getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status))
|
| + return newStart;
|
| + }
|
| + if (!getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status))
|
| return newStart;
|
| // else we allowing parsing as number, below
|
| + if(!getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status))
|
| + return -start;
|
| }
|
| break;
|
|
|
| case UDAT_TIMEZONE_FIELD: // 'z'
|
| {
|
| - UTimeZoneFormatTimeType tzTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
|
| UTimeZoneFormatStyle style = (count < 4) ? UTZFMT_STYLE_SPECIFIC_SHORT : UTZFMT_STYLE_SPECIFIC_LONG;
|
| - TimeZone *tz = tzFormat()->parse(style, text, pos, &tzTimeType);
|
| + TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType);
|
| if (tz != NULL) {
|
| - ((SimpleDateFormat*)this)->tztype = tzTimeType;
|
| cal.adoptTimeZone(tz);
|
| return pos.getIndex();
|
| }
|
| @@ -2900,12 +3070,10 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
| break;
|
| case UDAT_TIMEZONE_RFC_FIELD: // 'Z'
|
| {
|
| - UTimeZoneFormatTimeType tzTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
|
| UTimeZoneFormatStyle style = (count < 4) ?
|
| UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL : ((count == 5) ? UTZFMT_STYLE_ISO_EXTENDED_FULL: UTZFMT_STYLE_LOCALIZED_GMT);
|
| - TimeZone *tz = tzFormat()->parse(style, text, pos, &tzTimeType);
|
| + TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType);
|
| if (tz != NULL) {
|
| - ((SimpleDateFormat*)this)->tztype = tzTimeType;
|
| cal.adoptTimeZone(tz);
|
| return pos.getIndex();
|
| }
|
| @@ -2913,11 +3081,9 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
| }
|
| case UDAT_TIMEZONE_GENERIC_FIELD: // 'v'
|
| {
|
| - UTimeZoneFormatTimeType tzTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
|
| UTimeZoneFormatStyle style = (count < 4) ? UTZFMT_STYLE_GENERIC_SHORT : UTZFMT_STYLE_GENERIC_LONG;
|
| - TimeZone *tz = tzFormat()->parse(style, text, pos, &tzTimeType);
|
| + TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType);
|
| if (tz != NULL) {
|
| - ((SimpleDateFormat*)this)->tztype = tzTimeType;
|
| cal.adoptTimeZone(tz);
|
| return pos.getIndex();
|
| }
|
| @@ -2925,7 +3091,6 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
| }
|
| case UDAT_TIMEZONE_SPECIAL_FIELD: // 'V'
|
| {
|
| - UTimeZoneFormatTimeType tzTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
|
| UTimeZoneFormatStyle style;
|
| switch (count) {
|
| case 1:
|
| @@ -2941,9 +3106,8 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
| style = UTZFMT_STYLE_GENERIC_LOCATION;
|
| break;
|
| }
|
| - TimeZone *tz = tzFormat()->parse(style, text, pos, &tzTimeType);
|
| + TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType);
|
| if (tz != NULL) {
|
| - ((SimpleDateFormat*)this)->tztype = tzTimeType;
|
| cal.adoptTimeZone(tz);
|
| return pos.getIndex();
|
| }
|
| @@ -2951,11 +3115,9 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
| }
|
| case UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD: // 'O'
|
| {
|
| - UTimeZoneFormatTimeType tzTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
|
| UTimeZoneFormatStyle style = (count < 4) ? UTZFMT_STYLE_LOCALIZED_GMT_SHORT : UTZFMT_STYLE_LOCALIZED_GMT;
|
| - TimeZone *tz = tzFormat()->parse(style, text, pos, &tzTimeType);
|
| + TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType);
|
| if (tz != NULL) {
|
| - ((SimpleDateFormat*)this)->tztype = tzTimeType;
|
| cal.adoptTimeZone(tz);
|
| return pos.getIndex();
|
| }
|
| @@ -2963,7 +3125,6 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
| }
|
| case UDAT_TIMEZONE_ISO_FIELD: // 'X'
|
| {
|
| - UTimeZoneFormatTimeType tzTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
|
| UTimeZoneFormatStyle style;
|
| switch (count) {
|
| case 1:
|
| @@ -2982,9 +3143,8 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
| style = UTZFMT_STYLE_ISO_EXTENDED_FULL;
|
| break;
|
| }
|
| - TimeZone *tz = tzFormat()->parse(style, text, pos, &tzTimeType);
|
| + TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType);
|
| if (tz != NULL) {
|
| - ((SimpleDateFormat*)this)->tztype = tzTimeType;
|
| cal.adoptTimeZone(tz);
|
| return pos.getIndex();
|
| }
|
| @@ -2992,7 +3152,6 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
| }
|
| case UDAT_TIMEZONE_ISO_LOCAL_FIELD: // 'x'
|
| {
|
| - UTimeZoneFormatTimeType tzTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
|
| UTimeZoneFormatStyle style;
|
| switch (count) {
|
| case 1:
|
| @@ -3011,9 +3170,8 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
| style = UTZFMT_STYLE_ISO_EXTENDED_LOCAL_FULL;
|
| break;
|
| }
|
| - TimeZone *tz = tzFormat()->parse(style, text, pos, &tzTimeType);
|
| + TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType);
|
| if (tz != NULL) {
|
| - ((SimpleDateFormat*)this)->tztype = tzTimeType;
|
| cal.adoptTimeZone(tz);
|
| return pos.getIndex();
|
| }
|
| @@ -3088,6 +3246,9 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
| case UDAT_STANDALONE_QUARTER_FIELD:
|
| cal.set(UCAL_MONTH, (value - 1) * 3);
|
| break;
|
| + case UDAT_RELATED_YEAR_FIELD:
|
| + cal.setRelatedYear(value);
|
| + break;
|
| default:
|
| cal.set(field, value);
|
| break;
|
| @@ -3297,30 +3458,25 @@ void SimpleDateFormat::adoptCalendar(Calendar* calendarToAdopt)
|
| //----------------------------------------------------------------------
|
|
|
|
|
| -void SimpleDateFormat::setContext(UDisplayContext value, UErrorCode& status)
|
| -{
|
| - if (U_FAILURE(status))
|
| - return;
|
| - if ( (UDisplayContextType)((uint32_t)value >> 8) == UDISPCTX_TYPE_CAPITALIZATION ) {
|
| - fCapitalizationContext = value;
|
| - } else {
|
| - status = U_ILLEGAL_ARGUMENT_ERROR;
|
| - }
|
| -}
|
| -
|
| -
|
| -//----------------------------------------------------------------------
|
| -
|
| -
|
| -UDisplayContext SimpleDateFormat::getContext(UDisplayContextType type, UErrorCode& status) const
|
| +// override the DateFormat implementation in order to
|
| +// lazily initialize fCapitalizationBrkIter
|
| +void
|
| +SimpleDateFormat::setContext(UDisplayContext value, UErrorCode& status)
|
| {
|
| - if (U_FAILURE(status))
|
| - return (UDisplayContext)0;
|
| - if (type != UDISPCTX_TYPE_CAPITALIZATION) {
|
| - status = U_ILLEGAL_ARGUMENT_ERROR;
|
| - return (UDisplayContext)0;
|
| + DateFormat::setContext(value, status);
|
| +#if !UCONFIG_NO_BREAK_ITERATION
|
| + if (U_SUCCESS(status)) {
|
| + if ( fCapitalizationBrkIter == NULL && (value==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
|
| + value==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU || value==UDISPCTX_CAPITALIZATION_FOR_STANDALONE) ) {
|
| + UErrorCode status = U_ZERO_ERROR;
|
| + fCapitalizationBrkIter = BreakIterator::createSentenceInstance(fLocale, status);
|
| + if (U_FAILURE(status)) {
|
| + delete fCapitalizationBrkIter;
|
| + fCapitalizationBrkIter = NULL;
|
| + }
|
| + }
|
| }
|
| - return fCapitalizationContext;
|
| +#endif
|
| }
|
|
|
|
|
|
|