ICU-5559 Normalize time zone ID using RFC822 format in the result TimeZone when it is created by TimeZone#createTimeZone with custom ID.
X-SVN-Rev: 22129
This commit is contained in:
parent
283fa8f668
commit
fb68bb6add
@ -86,6 +86,8 @@ static char gStrBuf[256];
|
||||
#define kRULES "Rules"
|
||||
#define kNAMES "Names"
|
||||
#define kDEFAULT "Default"
|
||||
#define kMAX_CUSTOM_HOUR 23
|
||||
#define kMAX_CUSTOM_MIN 59
|
||||
|
||||
// Static data and constants
|
||||
|
||||
@ -93,10 +95,6 @@ static const UChar GMT_ID[] = {0x47, 0x4D, 0x54, 0x00}; /* "GMT" */
|
||||
static const UChar Z_STR[] = {0x7A, 0x00}; /* "z" */
|
||||
static const UChar ZZZZ_STR[] = {0x7A, 0x7A, 0x7A, 0x7A, 0x00}; /* "zzzz" */
|
||||
static const int32_t GMT_ID_LENGTH = 3;
|
||||
static const UChar CUSTOM_ID[] =
|
||||
{
|
||||
0x43, 0x75, 0x73, 0x74, 0x6F, 0x6D, 0x00 /* "Custom" */
|
||||
};
|
||||
|
||||
static UMTX LOCK;
|
||||
static U_NAMESPACE_QUALIFIER TimeZone* DEFAULT_ZONE = NULL;
|
||||
@ -1168,7 +1166,8 @@ TimeZone::createCustomTimeZone(const UnicodeString& id)
|
||||
{
|
||||
ParsePosition pos(GMT_ID_LENGTH);
|
||||
UBool negative = FALSE;
|
||||
int32_t offset;
|
||||
int32_t hour = 0;
|
||||
int32_t min = 0;
|
||||
|
||||
if (id[pos.getIndex()] == 0x002D /*'-'*/)
|
||||
negative = TRUE;
|
||||
@ -1194,13 +1193,12 @@ TimeZone::createCustomTimeZone(const UnicodeString& id)
|
||||
delete numberFormat;
|
||||
return 0;
|
||||
}
|
||||
offset = n.getLong();
|
||||
hour = n.getLong();
|
||||
|
||||
if (pos.getIndex() < id.length() &&
|
||||
id[pos.getIndex()] == 0x003A /*':'*/)
|
||||
{
|
||||
// hh:mm
|
||||
offset *= 60;
|
||||
pos.setIndex(pos.getIndex() + 1);
|
||||
int32_t oldPos = pos.getIndex();
|
||||
n.setLong(kParseFailed);
|
||||
@ -1209,27 +1207,57 @@ TimeZone::createCustomTimeZone(const UnicodeString& id)
|
||||
delete numberFormat;
|
||||
return 0;
|
||||
}
|
||||
offset += n.getLong();
|
||||
min = n.getLong();
|
||||
}
|
||||
else
|
||||
{
|
||||
// hhmm or hh
|
||||
|
||||
// Be strict about interpreting something as hh; it must be
|
||||
// an offset < 30, and it must be one or two digits. Thus
|
||||
// an offset < 23, and it must be one or two digits. Thus
|
||||
// 0010 is interpreted as 00:10, but 10 is interpreted as
|
||||
// 10:00.
|
||||
if (offset < 30 && (pos.getIndex() - start) <= 2)
|
||||
offset *= 60; // hh, from 00 to 29; 30 is 00:30
|
||||
else
|
||||
offset = offset % 100 + offset / 100 * 60; // hhmm
|
||||
if (hour > kMAX_CUSTOM_HOUR || (pos.getIndex() - start) > 2) {
|
||||
min = hour % 100;
|
||||
hour /= 100;
|
||||
}
|
||||
}
|
||||
|
||||
if(negative)
|
||||
offset = -offset;
|
||||
|
||||
delete numberFormat;
|
||||
return new SimpleTimeZone(offset * 60000, CUSTOM_ID);
|
||||
|
||||
if (hour > kMAX_CUSTOM_HOUR || min > kMAX_CUSTOM_MIN) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create time zone ID in RFC822 format - GMT[+|-]hhmm
|
||||
UnicodeString tzRFC(GMT_ID);
|
||||
if (hour|min) {
|
||||
if (negative) {
|
||||
tzRFC += (UChar)'-';
|
||||
} else {
|
||||
tzRFC += (UChar)'+';
|
||||
}
|
||||
|
||||
if (hour < 10) {
|
||||
tzRFC += (UChar)'0';
|
||||
} else {
|
||||
tzRFC += (UChar)('0' + hour/10);
|
||||
}
|
||||
tzRFC += (UChar)('0' + hour%10);
|
||||
|
||||
if (min < 10) {
|
||||
tzRFC += (UChar)'0';
|
||||
} else {
|
||||
tzRFC += (UChar)('0' + min/10);
|
||||
}
|
||||
tzRFC += (UChar)('0' + min%10);
|
||||
}
|
||||
|
||||
int32_t offset = (hour * 60 + min) * 60 * 1000;
|
||||
if(negative) {
|
||||
offset = -offset;
|
||||
}
|
||||
return new SimpleTimeZone(offset, tzRFC);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -764,7 +764,7 @@ void TimeZoneTest::TestShortZoneIDs()
|
||||
/**
|
||||
* Utility function for TestCustomParse
|
||||
*/
|
||||
UnicodeString& TimeZoneTest::formatMinutes(int32_t min, UnicodeString& rv)
|
||||
UnicodeString& TimeZoneTest::formatMinutes(int32_t min, UnicodeString& rv, UBool insertSep/*=TRUE*/)
|
||||
{
|
||||
rv.remove();
|
||||
|
||||
@ -774,13 +774,17 @@ UnicodeString& TimeZoneTest::formatMinutes(int32_t min, UnicodeString& rv)
|
||||
min = min%60;
|
||||
|
||||
rv += UChar(sign);
|
||||
if(h > 10)
|
||||
if(h >= 10)
|
||||
rv += UChar(0x0030 + (h/10));
|
||||
else
|
||||
rv += "0";
|
||||
|
||||
rv += UChar(0x0030 + (h%10));
|
||||
|
||||
rv += ":";
|
||||
if (insertSep)
|
||||
rv += ":";
|
||||
|
||||
if(min > 10)
|
||||
if(min >= 10)
|
||||
rv += UChar(0x0030 + (min/10));
|
||||
else
|
||||
rv += "0";
|
||||
@ -790,6 +794,19 @@ UnicodeString& TimeZoneTest::formatMinutes(int32_t min, UnicodeString& rv)
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function for TestCustomParse, generating RFC822 style
|
||||
* time zone string for the give offset in minutes
|
||||
*/
|
||||
UnicodeString& TimeZoneTest::formatRFC822TZ(int32_t min, UnicodeString& rv)
|
||||
{
|
||||
UnicodeString offsetStr;
|
||||
formatMinutes(min, offsetStr, FALSE);
|
||||
rv.remove();
|
||||
rv += "GMT";
|
||||
rv += offsetStr;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* As part of the VM fix (see CCC approved RFE 4028006, bug
|
||||
@ -803,7 +820,6 @@ void TimeZoneTest::TestCustomParse()
|
||||
{
|
||||
int32_t i;
|
||||
const int32_t kUnparseable = 604800; // the number of seconds in a week. More than any offset should be.
|
||||
const UnicodeString kExpectedCustomID = "Custom";
|
||||
|
||||
struct
|
||||
{
|
||||
@ -819,7 +835,7 @@ void TimeZoneTest::TestCustomParse()
|
||||
// {"GMT+0", (0)}, // ICU 2.8: An Olson zone ID
|
||||
{"GMT+1", (60)},
|
||||
{"GMT-0030", (-30)},
|
||||
{"GMT+15:99", (15*60+99)},
|
||||
{"GMT+15:99", kUnparseable},
|
||||
{"GMT+", kUnparseable},
|
||||
{"GMT-", kUnparseable},
|
||||
{"GMT+0:", kUnparseable},
|
||||
@ -880,8 +896,9 @@ void TimeZoneTest::TestCustomParse()
|
||||
{
|
||||
zone->getID(itsID);
|
||||
int32_t ioffset = zone->getRawOffset()/60000;
|
||||
UnicodeString offset;
|
||||
UnicodeString offset, expectedID;
|
||||
formatMinutes(ioffset, offset);
|
||||
formatRFC822TZ(ioffset, expectedID);
|
||||
logln(id + " -> " + itsID + " GMT" + offset);
|
||||
if (exp == kUnparseable)
|
||||
{
|
||||
@ -890,10 +907,11 @@ void TimeZoneTest::TestCustomParse()
|
||||
", id " + itsID);
|
||||
}
|
||||
else if (ioffset != exp ||
|
||||
(itsID.compare(kExpectedCustomID) != 0))
|
||||
(itsID.compare(expectedID) != 0))
|
||||
{
|
||||
errln("Expected offset of " + formatMinutes(exp,temp) +
|
||||
", id Custom, for " + id +
|
||||
", id " + expectedID +
|
||||
", for " + id +
|
||||
", got offset of " + offset +
|
||||
", id " + itsID);
|
||||
}
|
||||
|
@ -93,7 +93,8 @@ public:
|
||||
|
||||
private:
|
||||
// internal functions
|
||||
static UnicodeString& formatMinutes(int32_t min, UnicodeString& rv);
|
||||
static UnicodeString& formatMinutes(int32_t min, UnicodeString& rv, UBool insertSep = TRUE);
|
||||
static UnicodeString& formatRFC822TZ(int32_t min, UnicodeString& rv);
|
||||
};
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
Loading…
Reference in New Issue
Block a user