mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-07 06:25:30 +00:00
DateFormat parses 2-digit years other than "00" through "99". Fix restricts parsing to those 2-digit year strings.
X-Trac-URL: https://ssl.icu-project.org/trac/ticket/28 git-svn-id: http://source.icu-project.org/repos/icu/icu/trunk@64 0a8b766c-62c9-45f9-954d-7f2943c9ead0
This commit is contained in:
parent
5ab20cb303
commit
45456dcd7d
4 changed files with 79 additions and 3 deletions
|
@ -24,6 +24,8 @@
|
|||
* Removed subParseLong
|
||||
* Removed chk
|
||||
* 02/22/99 stephen Removed character literals for EBCDIC safety
|
||||
* 10/14/99 aliu Updated 2-digit year parsing so that only "00" thru
|
||||
* "99" are recognized. {j28 4182066}
|
||||
********************************************************************************
|
||||
*/
|
||||
|
||||
|
@ -1117,12 +1119,15 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
|||
case kEraField:
|
||||
return matchString(text, start, Calendar::ERA, fSymbols->fEras, fSymbols->fErasCount);
|
||||
case kYearField:
|
||||
// If there are 4 or more YEAR pattern characters, this indicates
|
||||
// If there are 3 or more YEAR pattern characters, this indicates
|
||||
// that the year value is to be treated literally, without any
|
||||
// two-digit year adjustments (e.g., from "01" to 2001). Otherwise
|
||||
// we made adjustments to place the 2-digit year in the proper
|
||||
// century -- unless the given year itself is more than two characters.
|
||||
if (count <= 2 && (pos.getIndex() - start) <= 2)
|
||||
// century, for parsed strings from "00" to "99". Any other string
|
||||
// is treated literally: "2250", "-1", "1", "002".
|
||||
if (count <= 2 && (pos.getIndex() - start) == 2
|
||||
&& Unicode::isDigit(text.charAt(start))
|
||||
&& Unicode::isDigit(text.charAt(start+1)))
|
||||
{
|
||||
// Assume for example that the defaultCenturyStart is 6/18/1903.
|
||||
// This means that two-digit years will be forced into the range
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
* Removed subParseLong
|
||||
* Removed getZoneIndex (added in DateFormatSymbols)
|
||||
* 06/14/99 stephen Removed fgTimeZoneDataSuffix
|
||||
* 10/14/99 aliu Updated class doc to describe 2-digit year parsing
|
||||
* {j28 4182066}.
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
|
@ -135,6 +137,28 @@ class DateFormatSymbols;
|
|||
* marker 'a' is left out from the format pattern while the "hour in am/pm"
|
||||
* pattern symbol is used. This information loss can happen when formatting the
|
||||
* time in PM.
|
||||
*
|
||||
* <p>
|
||||
* When parsing a date string using the abbreviated year pattern ("y" or "yy"),
|
||||
* SimpleDateFormat must interpret the abbreviated year
|
||||
* relative to some century. It does this by adjusting dates to be
|
||||
* within 80 years before and 20 years after the time the SimpleDateFormat
|
||||
* instance is created. For example, using a pattern of "MM/dd/yy" and a
|
||||
* SimpleDateFormat instance created on Jan 1, 1997, the string
|
||||
* "01/11/12" would be interpreted as Jan 11, 2012 while the string "05/04/64"
|
||||
* would be interpreted as May 4, 1964.
|
||||
* During parsing, only strings consisting of exactly two digits, as defined by
|
||||
* <code>Unicode::isDigit()</code>, will be parsed into the default century.
|
||||
* Any other numeric string, such as a one digit string, a three or more digit
|
||||
* string, or a two digit string that isn't all digits (for example, "-1"), is
|
||||
* interpreted literally. So "01/02/3" or "01/02/003" are parsed, using the
|
||||
* same pattern, as Jan 2, 3 AD. Likewise, "01/02/-3" is parsed as Jan 2, 4 BC.
|
||||
*
|
||||
* <p>
|
||||
* If the year pattern has more than two 'y' characters, the year is
|
||||
* interpreted literally, regardless of the number of digits. So using the
|
||||
* pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D.
|
||||
*
|
||||
* <P>
|
||||
* For time zones that have no names, SimpleDateFormat uses strings GMT+hours:minutes or
|
||||
* GMT-hours:minutes.
|
||||
|
|
|
@ -70,6 +70,7 @@ CalendarRegressionTest::runIndexedTest( int32_t index, bool_t exec, char* &name,
|
|||
CASE(32,Test4165343)
|
||||
CASE(33,Test4166109)
|
||||
CASE(34,Test4167060)
|
||||
CASE(35,Test4197699)
|
||||
|
||||
default: name = ""; break;
|
||||
}
|
||||
|
@ -1580,8 +1581,53 @@ CalendarRegressionTest::Test4167060()
|
|||
delete calendars[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Week of year is wrong at the start and end of the year.
|
||||
*/
|
||||
void CalendarRegressionTest::Test4197699() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
GregorianCalendar cal(status);
|
||||
cal.setFirstDayOfWeek(Calendar::MONDAY);
|
||||
cal.setMinimalDaysInFirstWeek(4);
|
||||
SimpleDateFormat fmt("E dd MMM yyyy 'DOY='D 'WOY='w",
|
||||
Locale::US, status);
|
||||
fmt.setCalendar(cal);
|
||||
if (FAILURE(status)) {
|
||||
errln("Couldn't initialize test");
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t DATA[] = {
|
||||
2000, Calendar::JANUARY, 1, 52,
|
||||
2001, Calendar::DECEMBER, 31, 1,
|
||||
};
|
||||
int32_t DATA_length = sizeof(DATA) / sizeof(DATA[0]);
|
||||
|
||||
UnicodeString str;
|
||||
DateFormat& dfmt = *(DateFormat*)&fmt;
|
||||
for (int32_t i=0; i<DATA_length; ) {
|
||||
cal.clear();
|
||||
cal.set(DATA[i], DATA[i+1], DATA[i+2]);
|
||||
i += 3;
|
||||
int32_t expWOY = DATA[i++];
|
||||
int32_t actWOY = cal.get(Calendar::WEEK_OF_YEAR, status);
|
||||
if (expWOY == actWOY) {
|
||||
logln(UnicodeString("Ok: ") + dfmt.format(cal.getTime(status), str.remove()));
|
||||
} else {
|
||||
errln(UnicodeString("FAIL: ") + dfmt.format(cal.getTime(status), str.remove())
|
||||
+ ", expected WOY=" + expWOY);
|
||||
cal.add(Calendar::DATE, -8, status);
|
||||
for (int j=0; j<14; ++j) {
|
||||
cal.add(Calendar::DATE, 1, status);
|
||||
logln(dfmt.format(cal.getTime(status), str.remove()));
|
||||
}
|
||||
}
|
||||
if (FAILURE(status)) {
|
||||
errln("FAIL: Unexpected error from Calendar");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UDate
|
||||
CalendarRegressionTest::makeDate(int32_t y, int32_t m, int32_t d,
|
||||
|
|
|
@ -65,6 +65,7 @@ public:
|
|||
void Test4165343(void) ;
|
||||
void Test4166109(void) ;
|
||||
void Test4167060(void) ;
|
||||
void Test4197699();
|
||||
|
||||
void printdate(GregorianCalendar *cal, char *string);
|
||||
void dowTest(bool_t lenient) ;
|
||||
|
|
Loading…
Add table
Reference in a new issue