ICU-6420 Fixed calendar/date symbols mismatch problem for C.
X-SVN-Rev: 25309
This commit is contained in:
parent
c6efa90f2d
commit
f682a39582
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
* Copyright (C) 1997-2008, International Business Machines Corporation and *
|
* Copyright (C) 1997-2009, International Business Machines Corporation and *
|
||||||
* others. All Rights Reserved. *
|
* others. All Rights Reserved. *
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
*
|
*
|
||||||
@ -514,6 +514,19 @@ SimpleDateFormat::format(Calendar& cal, UnicodeString& appendTo, FieldPosition&
|
|||||||
pos.setBeginIndex(0);
|
pos.setBeginIndex(0);
|
||||||
pos.setEndIndex(0);
|
pos.setEndIndex(0);
|
||||||
|
|
||||||
|
Calendar *workCal = &cal;
|
||||||
|
TimeZone *backupTZ = NULL;
|
||||||
|
if (&cal != fCalendar && uprv_strcmp(cal.getType(), fCalendar->getType()) != 0) {
|
||||||
|
// Different calendar type
|
||||||
|
// We use the time and time zone from the input calendar, but
|
||||||
|
// do not use the input calendar for field calculation.
|
||||||
|
UDate t = cal.getTime(status);
|
||||||
|
fCalendar->setTime(t, status);
|
||||||
|
backupTZ = fCalendar->getTimeZone().clone();
|
||||||
|
fCalendar->setTimeZone(cal.getTimeZone());
|
||||||
|
workCal = fCalendar;
|
||||||
|
}
|
||||||
|
|
||||||
UBool inQuote = FALSE;
|
UBool inQuote = FALSE;
|
||||||
UChar prevCh = 0;
|
UChar prevCh = 0;
|
||||||
int32_t count = 0;
|
int32_t count = 0;
|
||||||
@ -525,7 +538,7 @@ SimpleDateFormat::format(Calendar& cal, UnicodeString& appendTo, FieldPosition&
|
|||||||
// Use subFormat() to format a repeated pattern character
|
// Use subFormat() to format a repeated pattern character
|
||||||
// when a different pattern or non-pattern character is seen
|
// when a different pattern or non-pattern character is seen
|
||||||
if (ch != prevCh && count > 0) {
|
if (ch != prevCh && count > 0) {
|
||||||
subFormat(appendTo, prevCh, count, pos, cal, status);
|
subFormat(appendTo, prevCh, count, pos, *workCal, status);
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
if (ch == QUOTE) {
|
if (ch == QUOTE) {
|
||||||
@ -553,7 +566,12 @@ SimpleDateFormat::format(Calendar& cal, UnicodeString& appendTo, FieldPosition&
|
|||||||
|
|
||||||
// Format the last item in the pattern, if any
|
// Format the last item in the pattern, if any
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
subFormat(appendTo, prevCh, count, pos, cal, status);
|
subFormat(appendTo, prevCh, count, pos, *workCal, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backupTZ != NULL) {
|
||||||
|
// Restore the original time zone
|
||||||
|
fCalendar->adoptTimeZone(backupTZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
// and if something failed (e.g., an invalid format character), reset our FieldPosition
|
// and if something failed (e.g., an invalid format character), reset our FieldPosition
|
||||||
@ -1337,8 +1355,10 @@ UBool SimpleDateFormat::isNumeric(UChar formatChar, int32_t count) {
|
|||||||
void
|
void
|
||||||
SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition& parsePos) const
|
SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition& parsePos) const
|
||||||
{
|
{
|
||||||
|
UErrorCode status = U_ZERO_ERROR;
|
||||||
int32_t pos = parsePos.getIndex();
|
int32_t pos = parsePos.getIndex();
|
||||||
int32_t start = pos;
|
int32_t start = pos;
|
||||||
|
|
||||||
UBool ambiguousYear[] = { FALSE };
|
UBool ambiguousYear[] = { FALSE };
|
||||||
int32_t count = 0;
|
int32_t count = 0;
|
||||||
|
|
||||||
@ -1357,6 +1377,21 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
|||||||
|
|
||||||
const UnicodeString numericFormatChars(NUMERIC_FORMAT_CHARS);
|
const UnicodeString numericFormatChars(NUMERIC_FORMAT_CHARS);
|
||||||
|
|
||||||
|
TimeZone *backupTZ = NULL;
|
||||||
|
Calendar *workCal = &cal;
|
||||||
|
if (&cal != fCalendar && uprv_strcmp(cal.getType(), fCalendar->getType()) != 0) {
|
||||||
|
// Different calendar type
|
||||||
|
// We use the time/zone from the input calendar, but
|
||||||
|
// do not use the input calendar for field calculation.
|
||||||
|
fCalendar->setTime(cal.getTime(status),status);
|
||||||
|
if (U_FAILURE(status)) {
|
||||||
|
goto ExitParse;
|
||||||
|
}
|
||||||
|
backupTZ = fCalendar->getTimeZone().clone();
|
||||||
|
fCalendar->setTimeZone(cal.getTimeZone());
|
||||||
|
workCal = fCalendar;
|
||||||
|
}
|
||||||
|
|
||||||
for (int32_t i=0; i<fPattern.length(); ++i) {
|
for (int32_t i=0; i<fPattern.length(); ++i) {
|
||||||
UChar ch = fPattern.charAt(i);
|
UChar ch = fPattern.charAt(i);
|
||||||
|
|
||||||
@ -1422,14 +1457,13 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
|||||||
if (fieldPat == abutPat) {
|
if (fieldPat == abutPat) {
|
||||||
count -= abutPass++;
|
count -= abutPass++;
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
parsePos.setIndex(start);
|
status = U_PARSE_ERROR;
|
||||||
parsePos.setErrorIndex(pos);
|
goto ExitParse;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = subParse(text, pos, ch, count,
|
pos = subParse(text, pos, ch, count,
|
||||||
TRUE, FALSE, ambiguousYear, cal);
|
TRUE, FALSE, ambiguousYear, *workCal);
|
||||||
|
|
||||||
// If the parse fails anywhere in the run, back up to the
|
// If the parse fails anywhere in the run, back up to the
|
||||||
// start of the run and retry.
|
// start of the run and retry.
|
||||||
@ -1443,15 +1477,14 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
|||||||
// Handle non-numeric fields and non-abutting numeric
|
// Handle non-numeric fields and non-abutting numeric
|
||||||
// fields.
|
// fields.
|
||||||
else {
|
else {
|
||||||
int32_t s = pos;
|
int32_t s = subParse(text, pos, ch, count,
|
||||||
pos = subParse(text, pos, ch, count,
|
FALSE, TRUE, ambiguousYear, *workCal);
|
||||||
FALSE, TRUE, ambiguousYear, cal);
|
|
||||||
|
|
||||||
if (pos < 0) {
|
if (s < 0) {
|
||||||
parsePos.setErrorIndex(s);
|
status = U_PARSE_ERROR;
|
||||||
parsePos.setIndex(start);
|
goto ExitParse;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
pos = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1504,9 +1537,8 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We fall through to this point if the match fails
|
// We fall through to this point if the match fails
|
||||||
parsePos.setIndex(start);
|
status = U_PARSE_ERROR;
|
||||||
parsePos.setErrorIndex(pos);
|
goto ExitParse;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1538,7 +1570,6 @@ 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
|
// 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
|
// 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().
|
// the year correctly to start with in other cases -- see subParse().
|
||||||
UErrorCode status = U_ZERO_ERROR;
|
|
||||||
if (ambiguousYear[0] || tztype != TZTYPE_UNK) // If this is true then the two-digit year == the default start year
|
if (ambiguousYear[0] || tztype != TZTYPE_UNK) // 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
|
// We need a copy of the fields, and we need to avoid triggering a call to
|
||||||
@ -1671,13 +1702,25 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
|||||||
delete copy;
|
delete copy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExitParse:
|
ExitParse:
|
||||||
|
// Set the parsed result if local calendar is used
|
||||||
|
// instead of the input calendar
|
||||||
|
if (U_SUCCESS(status) && workCal != &cal) {
|
||||||
|
cal.setTimeZone(workCal->getTimeZone());
|
||||||
|
cal.setTime(workCal->getTime(status), status);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore the original time zone if required
|
||||||
|
if (backupTZ != NULL) {
|
||||||
|
fCalendar->adoptTimeZone(backupTZ);
|
||||||
|
}
|
||||||
|
|
||||||
// If any Calendar calls failed, we pretend that we
|
// If any Calendar calls failed, we pretend that we
|
||||||
// couldn't parse the string, when in reality this isn't quite accurate--
|
// couldn't parse the string, when in reality this isn't quite accurate--
|
||||||
// we did parse it; the Calendar calls just failed.
|
// we did parse it; the Calendar calls just failed.
|
||||||
if (U_FAILURE(status)) {
|
if (U_FAILURE(status)) {
|
||||||
parsePos.setErrorIndex(pos);
|
parsePos.setErrorIndex(pos);
|
||||||
parsePos.setIndex(start);
|
parsePos.setIndex(start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
********************************************************************************
|
********************************************************************************
|
||||||
* Copyright (C) 1997-2008, International Business Machines
|
* Copyright (C) 1997-2009, International Business Machines
|
||||||
* Corporation and others. All Rights Reserved.
|
* Corporation and others. All Rights Reserved.
|
||||||
********************************************************************************
|
********************************************************************************
|
||||||
*
|
*
|
||||||
@ -245,7 +245,11 @@ public:
|
|||||||
* occurence of the timezone pattern character 'z'.
|
* occurence of the timezone pattern character 'z'.
|
||||||
*
|
*
|
||||||
* @param cal Calendar set to the date and time to be formatted
|
* @param cal Calendar set to the date and time to be formatted
|
||||||
* into a date/time string.
|
* into a date/time string. When the calendar type is
|
||||||
|
* different from the internal calendar held by this
|
||||||
|
* DateFormat instance, the date and the time zone will
|
||||||
|
* be inherited from the input calendar, but other calendar
|
||||||
|
* field values will be calculated by the internal calendar.
|
||||||
* @param appendTo Output parameter to receive result.
|
* @param appendTo Output parameter to receive result.
|
||||||
* Result is appended to existing contents.
|
* Result is appended to existing contents.
|
||||||
* @param fieldPosition On input: an alignment field, if desired (see examples above)
|
* @param fieldPosition On input: an alignment field, if desired (see examples above)
|
||||||
@ -342,7 +346,12 @@ public:
|
|||||||
*
|
*
|
||||||
* @param text The date/time string to be parsed
|
* @param text The date/time string to be parsed
|
||||||
* @param cal a Calendar set to the date and time to be formatted
|
* @param cal a Calendar set to the date and time to be formatted
|
||||||
* into a date/time string.
|
* into a date/time string. When the calendar type
|
||||||
|
* is different from the internal calendar held by this
|
||||||
|
* DateFormat instance, calendar field values will be
|
||||||
|
* parsed based on the internal calendar, then the result
|
||||||
|
* (time in milliseconds and time zone) will be set in
|
||||||
|
* this calendar.
|
||||||
* @param pos On input, the position at which to start parsing; on
|
* @param pos On input, the position at which to start parsing; on
|
||||||
* output, the position at which parsing terminated, or the
|
* output, the position at which parsing terminated, or the
|
||||||
* start position if the parse failed.
|
* start position if the parse failed.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/********************************************************************
|
/********************************************************************
|
||||||
* COPYRIGHT:
|
* COPYRIGHT:
|
||||||
* Copyright (c) 1997-2008, International Business Machines Corporation and
|
* Copyright (c) 1997-2009, International Business Machines Corporation and
|
||||||
* others. All Rights Reserved.
|
* others. All Rights Reserved.
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
@ -74,9 +74,10 @@ void DateFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &nam
|
|||||||
TESTCASE(34,TestRelativeClone);
|
TESTCASE(34,TestRelativeClone);
|
||||||
TESTCASE(35,TestHostClone);
|
TESTCASE(35,TestHostClone);
|
||||||
TESTCASE(36,TestTimeZoneDisplayName);
|
TESTCASE(36,TestTimeZoneDisplayName);
|
||||||
|
TESTCASE(37,TestRoundtripWithCalendar);
|
||||||
/*
|
/*
|
||||||
TESTCASE(37,TestRelativeError);
|
TESTCASE(38,TestRelativeError);
|
||||||
TESTCASE(38,TestRelativeOther);
|
TESTCASE(39,TestRelativeOther);
|
||||||
*/
|
*/
|
||||||
default: name = ""; break;
|
default: name = ""; break;
|
||||||
}
|
}
|
||||||
@ -2898,6 +2899,128 @@ void DateFormatTest::TestTimeZoneDisplayName()
|
|||||||
delete cal;
|
delete cal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DateFormatTest::TestRoundtripWithCalendar(void) {
|
||||||
|
UErrorCode status = U_ZERO_ERROR;
|
||||||
|
|
||||||
|
TimeZone *tz = TimeZone::createTimeZone("Europe/Paris");
|
||||||
|
TimeZone *gmt = TimeZone::createTimeZone("Etc/GMT");
|
||||||
|
|
||||||
|
Calendar *calendars[] = {
|
||||||
|
Calendar::createInstance(*tz, Locale("und@calendar=gregorian"), status),
|
||||||
|
Calendar::createInstance(*tz, Locale("und@calendar=buddhist"), status),
|
||||||
|
// Calendar::createInstance(*tz, Locale("und@calendar=hebrew"), status),
|
||||||
|
Calendar::createInstance(*tz, Locale("und@calendar=islamic"), status),
|
||||||
|
Calendar::createInstance(*tz, Locale("und@calendar=japanese"), status),
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
if (U_FAILURE(status)) {
|
||||||
|
errln("Failed to initialize calendars");
|
||||||
|
for (int i = 0; calendars[i] != NULL; i++) {
|
||||||
|
delete calendars[i];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME The formatters commented out below are currently failing because of
|
||||||
|
// the calendar calculation problem reported by #6691
|
||||||
|
|
||||||
|
// The order of test formatters must match the order of calendars above.
|
||||||
|
DateFormat *formatters[] = {
|
||||||
|
DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("en_US")), //calendar=gregorian
|
||||||
|
DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("th_TH")), //calendar=buddhist
|
||||||
|
// DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("he_IL@calendar=hebrew")),
|
||||||
|
DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("ar_EG@calendar=islamic")),
|
||||||
|
// DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("ja_JP@calendar=japanese")),
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
UDate d = Calendar::getNow();
|
||||||
|
UnicodeString buf;
|
||||||
|
FieldPosition fpos;
|
||||||
|
ParsePosition ppos;
|
||||||
|
|
||||||
|
for (int i = 0; formatters[i] != NULL; i++) {
|
||||||
|
buf.remove();
|
||||||
|
fpos.setBeginIndex(0);
|
||||||
|
fpos.setEndIndex(0);
|
||||||
|
calendars[i]->setTime(d, status);
|
||||||
|
|
||||||
|
// Normal case output - the given calendar matches the calendar
|
||||||
|
// used by the formatter
|
||||||
|
formatters[i]->format(*calendars[i], buf, fpos);
|
||||||
|
UnicodeString refStr(buf);
|
||||||
|
|
||||||
|
for (int j = 0; calendars[j] != NULL; j++) {
|
||||||
|
if (j == i) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
buf.remove();
|
||||||
|
fpos.setBeginIndex(0);
|
||||||
|
fpos.setEndIndex(0);
|
||||||
|
calendars[j]->setTime(d, status);
|
||||||
|
|
||||||
|
// Even the different calendar type is specified,
|
||||||
|
// we should get the same result.
|
||||||
|
formatters[i]->format(*calendars[j], buf, fpos);
|
||||||
|
if (refStr != buf) {
|
||||||
|
errln((UnicodeString)"FAIL: Different format result with a different calendar for the same time -"
|
||||||
|
+ "\n Reference calendar type=" + calendars[i]->getType()
|
||||||
|
+ "\n Another calendar type=" + calendars[j]->getType()
|
||||||
|
+ "\n Expected result=" + refStr
|
||||||
|
+ "\n Actual result=" + buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
calendars[i]->setTimeZone(*gmt);
|
||||||
|
calendars[i]->clear();
|
||||||
|
ppos.setErrorIndex(-1);
|
||||||
|
ppos.setIndex(0);
|
||||||
|
|
||||||
|
// Normal case parse result - the given calendar matches the calendar
|
||||||
|
// used by the formatter
|
||||||
|
formatters[i]->parse(refStr, *calendars[i], ppos);
|
||||||
|
|
||||||
|
for (int j = 0; calendars[j] != NULL; j++) {
|
||||||
|
if (j == i) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
calendars[j]->setTimeZone(*gmt);
|
||||||
|
calendars[j]->clear();
|
||||||
|
ppos.setErrorIndex(-1);
|
||||||
|
ppos.setIndex(0);
|
||||||
|
|
||||||
|
// Even the different calendar type is specified,
|
||||||
|
// we should get the same time and time zone.
|
||||||
|
formatters[i]->parse(refStr, *calendars[j], ppos);
|
||||||
|
if (calendars[i]->getTime(status) != calendars[j]->getTime(status)
|
||||||
|
|| calendars[i]->getTimeZone() != calendars[j]->getTimeZone()) {
|
||||||
|
UnicodeString tzid;
|
||||||
|
errln((UnicodeString)"FAIL: Different parse result with a different calendar for the same string -"
|
||||||
|
+ "\n Reference calendar type=" + calendars[i]->getType()
|
||||||
|
+ "\n Another calendar type=" + calendars[j]->getType()
|
||||||
|
+ "\n Date string=" + refStr
|
||||||
|
+ "\n Expected time=" + calendars[i]->getTime(status)
|
||||||
|
+ "\n Expected time zone=" + calendars[i]->getTimeZone().getID(tzid)
|
||||||
|
+ "\n Actual time=" + calendars[j]->getTime(status)
|
||||||
|
+ "\n Actual time zone=" + calendars[j]->getTimeZone().getID(tzid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (U_FAILURE(status)) {
|
||||||
|
errln((UnicodeString)"FAIL: " + u_errorName(status));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete tz;
|
||||||
|
delete gmt;
|
||||||
|
for (int i = 0; calendars[i] != NULL; i++) {
|
||||||
|
delete calendars[i];
|
||||||
|
}
|
||||||
|
for (int i = 0; formatters[i] != NULL; i++) {
|
||||||
|
delete formatters[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void DateFormatTest::TestRelativeError(void)
|
void DateFormatTest::TestRelativeError(void)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/********************************************************************
|
/********************************************************************
|
||||||
* COPYRIGHT:
|
* COPYRIGHT:
|
||||||
* Copyright (c) 1997-2007, International Business Machines Corporation and
|
* Copyright (c) 1997-2009, International Business Machines Corporation and
|
||||||
* others. All Rights Reserved.
|
* others. All Rights Reserved.
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
@ -185,12 +185,15 @@ public:
|
|||||||
|
|
||||||
void TestHostClone(void);
|
void TestHostClone(void);
|
||||||
|
|
||||||
|
void TestTimeZoneDisplayName(void);
|
||||||
|
|
||||||
|
void TestRoundtripWithCalendar(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/***
|
/***
|
||||||
* Test Relative Dates
|
* Test Relative Dates
|
||||||
*/
|
*/
|
||||||
void TestRelative(void);
|
void TestRelative(void);
|
||||||
void TestTimeZoneDisplayName(void);
|
|
||||||
/* void TestRelativeError(void);
|
/* void TestRelativeError(void);
|
||||||
void TestRelativeOther(void);
|
void TestRelativeOther(void);
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user