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 |
} |