Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
99cad872
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
99cad872
编写于
9月 09, 2010
作者:
O
okutsu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
4919632: RFE: SimpleDateFormat should fully support ISO8601 standard for timezone
Reviewed-by: peytoia
上级
e417482c
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
387 addition
and
5 deletion
+387
-5
src/share/classes/java/text/DateFormatSymbols.java
src/share/classes/java/text/DateFormatSymbols.java
+2
-1
src/share/classes/java/text/SimpleDateFormat.java
src/share/classes/java/text/SimpleDateFormat.java
+168
-4
test/java/text/Format/DateFormat/ISO8601ZoneTest.java
test/java/text/Format/DateFormat/ISO8601ZoneTest.java
+217
-0
未找到文件。
src/share/classes/java/text/DateFormatSymbols.java
浏览文件 @
99cad872
...
...
@@ -226,7 +226,7 @@ public class DateFormatSymbols implements Serializable, Cloneable {
* Unlocalized date-time pattern characters. For example: 'y', 'd', etc.
* All locales use the same these unlocalized pattern characters.
*/
static
final
String
patternChars
=
"GyMdkHmsSEDFwWahKzZYu"
;
static
final
String
patternChars
=
"GyMdkHmsSEDFwWahKzZYu
X
"
;
static
final
int
PATTERN_ERA
=
0
;
// G
static
final
int
PATTERN_YEAR
=
1
;
// y
...
...
@@ -249,6 +249,7 @@ public class DateFormatSymbols implements Serializable, Cloneable {
static
final
int
PATTERN_ZONE_VALUE
=
18
;
// Z
static
final
int
PATTERN_WEEK_YEAR
=
19
;
// Y
static
final
int
PATTERN_ISO_DAY_OF_WEEK
=
20
;
// u
static
final
int
PATTERN_ISO_ZONE
=
21
;
// X
/**
* Localized date-time pattern characters. For example, a locale may
...
...
src/share/classes/java/text/SimpleDateFormat.java
浏览文件 @
99cad872
...
...
@@ -204,6 +204,11 @@ import static java.text.DateFormatSymbols.*;
* <td>Time zone
* <td><a href="#rfc822timezone">RFC 822 time zone</a>
* <td><code>-0800</code>
* <tr bgcolor="#eeeeff">
* <td><code>X</code>
* <td>Time zone
* <td><a href="#iso8601timezone">ISO 8601 time zone</a>
* <td><code>-08</code>; <code>-0800</code>; <code>-08:00</code>
* </table>
* </blockquote>
* Pattern letters are usually repeated, as their number determines the
...
...
@@ -288,6 +293,7 @@ import static java.text.DateFormatSymbols.*;
* accepted.<br><br></li>
* <li><strong><a name="rfc822timezone">RFC 822 time zone:</a></strong>
* For formatting, the RFC 822 4-digit time zone format is used:
*
* <pre>
* <i>RFC822TimeZone:</i>
* <i>Sign</i> <i>TwoDigitHours</i> <i>Minutes</i>
...
...
@@ -295,8 +301,41 @@ import static java.text.DateFormatSymbols.*;
* <i>Digit Digit</i></pre>
* <i>TwoDigitHours</i> must be between 00 and 23. Other definitions
* are as for <a href="#timezone">general time zones</a>.
*
* <p>For parsing, <a href="#timezone">general time zones</a> are also
* accepted.
* <li><strong><a name="iso8601timezone">ISO 8601 Time zone:</a></strong>
* The number of pattern letters designates the format for both formatting
* and parsing as follows:
* <pre>
* <i>ISO8601TimeZone:</i>
* <i>OneLetterISO8601TimeZone</i>
* <i>TwoLetterISO8601TimeZone</i>
* <i>ThreeLetterISO8601TimeZone</i>
* <i>OneLetterISO8601TimeZone:</i>
* <i>Sign</i> <i>TwoDigitHours</i>
* {@code Z}
* <i>TwoLetterISO8601TimeZone:</i>
* <i>Sign</i> <i>TwoDigitHours</i> <i>Minutes</i>
* {@code Z}
* <i>ThreeLetterISO8601TimeZone:</i>
* <i>Sign</i> <i>TwoDigitHours</i> {@code :} <i>Minutes</i>
* {@code Z}</pre>
* Other definitions are as for <a href="#timezone">general time zones</a> or
* <a href="#rfc822timezone">RFC 822 time zones</a>.
*
* <p>For formatting, if the offset value from GMT is 0, {@code "Z"} is
* produced. If the number of pattern letters is 1, any fraction of an hour
* is ignored. For example, if the pattern is {@code "X"} and the time zone is
* {@code "GMT+05:30"}, {@code "+05"} is produced.
*
* <p>For parsing, {@code "Z"} is parsed as the UTC time zone designator.
* <a href="#timezone">General time zones</a> are <em>not</em> accepted.
*
* <p>If the number of pattern letters is 4 or more, {@link
* IllegalArgumentException} is thrown when constructing a {@code
* SimpleDateFormat} or {@linkplain #applyPattern(String) applying a
* pattern}.
* </ul>
* <code>SimpleDateFormat</code> also supports <em>localized date and time
* pattern</em> strings. In these strings, the pattern letters described above
...
...
@@ -343,6 +382,9 @@ import static java.text.DateFormatSymbols.*;
* <td><code>"yyyy-MM-dd'T'HH:mm:ss.SSSZ"</code>
* <td><code>2001-07-04T12:08:56.235-0700</code>
* <tr bgcolor="#eeeeff">
* <td><code>"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"</code>
* <td><code>2001-07-04T12:08:56.235-07:00</code>
* <tr>
* <td><code>"YYYY-'W'ww-u"</code>
* <td><code>2001-W27-3</code>
* </table>
...
...
@@ -839,6 +881,9 @@ public class SimpleDateFormat extends DateFormat {
* Encodes the given tag and length and puts encoded char(s) into buffer.
*/
private
static
final
void
encode
(
int
tag
,
int
length
,
StringBuilder
buffer
)
{
if
(
tag
==
PATTERN_ISO_ZONE
&&
length
>=
4
)
{
throw
new
IllegalArgumentException
(
"invalid ISO 8601 format: length="
+
length
);
}
if
(
length
<
255
)
{
buffer
.
append
((
char
)(
tag
<<
8
|
length
));
}
else
{
...
...
@@ -995,7 +1040,8 @@ public class SimpleDateFormat extends DateFormat {
Calendar
.
ZONE_OFFSET
,
// Pseudo Calendar fields
CalendarBuilder
.
WEEK_YEAR
,
CalendarBuilder
.
ISO_DAY_OF_WEEK
CalendarBuilder
.
ISO_DAY_OF_WEEK
,
Calendar
.
ZONE_OFFSET
};
// Map index into pattern character string to DateFormat field number
...
...
@@ -1009,7 +1055,8 @@ public class SimpleDateFormat extends DateFormat {
DateFormat
.
WEEK_OF_MONTH_FIELD
,
DateFormat
.
AM_PM_FIELD
,
DateFormat
.
HOUR1_FIELD
,
DateFormat
.
HOUR0_FIELD
,
DateFormat
.
TIMEZONE_FIELD
,
DateFormat
.
TIMEZONE_FIELD
,
DateFormat
.
YEAR_FIELD
,
DateFormat
.
DAY_OF_WEEK_FIELD
DateFormat
.
YEAR_FIELD
,
DateFormat
.
DAY_OF_WEEK_FIELD
,
DateFormat
.
TIMEZONE_FIELD
};
// Maps from DecimalFormatSymbols index to Field constant
...
...
@@ -1021,7 +1068,8 @@ public class SimpleDateFormat extends DateFormat {
Field
.
WEEK_OF_YEAR
,
Field
.
WEEK_OF_MONTH
,
Field
.
AM_PM
,
Field
.
HOUR1
,
Field
.
HOUR0
,
Field
.
TIME_ZONE
,
Field
.
TIME_ZONE
,
Field
.
YEAR
,
Field
.
DAY_OF_WEEK
Field
.
YEAR
,
Field
.
DAY_OF_WEEK
,
Field
.
TIME_ZONE
};
/**
...
...
@@ -1189,6 +1237,34 @@ public class SimpleDateFormat extends DateFormat {
CalendarUtils
.
sprintf0d
(
buffer
,
num
,
width
);
break
;
case
PATTERN_ISO_ZONE:
// 'X'
value
=
calendar
.
get
(
Calendar
.
ZONE_OFFSET
)
+
calendar
.
get
(
Calendar
.
DST_OFFSET
);
if
(
value
==
0
)
{
buffer
.
append
(
'Z'
);
break
;
}
value
/=
60000
;
if
(
value
>=
0
)
{
buffer
.
append
(
'+'
);
}
else
{
buffer
.
append
(
'-'
);
value
=
-
value
;
}
CalendarUtils
.
sprintf0d
(
buffer
,
value
/
60
,
2
);
if
(
count
==
1
)
{
break
;
}
if
(
count
==
3
)
{
buffer
.
append
(
':'
);
}
CalendarUtils
.
sprintf0d
(
buffer
,
value
%
60
,
2
);
break
;
default
:
// case PATTERN_DAY_OF_MONTH: // 'd'
// case PATTERN_HOUR_OF_DAY0: // 'H' 0-based. eg, 23:59 + 1 hour =>> 00:59
...
...
@@ -1973,6 +2049,94 @@ public class SimpleDateFormat extends DateFormat {
}
break
parsing
;
case
PATTERN_ISO_ZONE:
// 'X'
{
int
sign
=
0
;
int
offset
=
0
;
iso8601:
{
try
{
char
c
=
text
.
charAt
(
pos
.
index
);
if
(
c
==
'Z'
)
{
calb
.
set
(
Calendar
.
ZONE_OFFSET
,
0
).
set
(
Calendar
.
DST_OFFSET
,
0
);
return
++
pos
.
index
;
}
// parse text as "+/-hh[[:]mm]" based on count
if
(
c
==
'+'
)
{
sign
=
1
;
}
else
if
(
c
==
'-'
)
{
sign
=
-
1
;
}
// Look for hh.
int
hours
=
0
;
c
=
text
.
charAt
(++
pos
.
index
);
if
(
c
<
'0'
||
c
>
'9'
)
{
/* must be from '0' to '9'. */
break
parsing
;
}
hours
=
c
-
'0'
;
c
=
text
.
charAt
(++
pos
.
index
);
if
(
c
<
'0'
||
c
>
'9'
)
{
/* must be from '0' to '9'. */
break
parsing
;
}
hours
*=
10
;
hours
+=
c
-
'0'
;
if
(
hours
>
23
)
{
break
parsing
;
}
if
(
count
==
1
)
{
// "X"
offset
=
hours
*
60
;
break
iso8601
;
}
c
=
text
.
charAt
(++
pos
.
index
);
// Skip ':' if "XXX"
if
(
c
==
':'
)
{
if
(
count
==
2
)
{
break
parsing
;
}
c
=
text
.
charAt
(++
pos
.
index
);
}
else
{
if
(
count
==
3
)
{
// missing ':'
break
parsing
;
}
}
// Look for mm.
int
minutes
=
0
;
if
(
c
<
'0'
||
c
>
'9'
)
{
/* must be from '0' to '9'. */
break
parsing
;
}
minutes
=
c
-
'0'
;
c
=
text
.
charAt
(++
pos
.
index
);
if
(
c
<
'0'
||
c
>
'9'
)
{
/* must be from '0' to '9'. */
break
parsing
;
}
minutes
*=
10
;
minutes
+=
c
-
'0'
;
if
(
minutes
>
59
)
{
break
parsing
;
}
offset
=
hours
*
60
+
minutes
;
}
catch
(
StringIndexOutOfBoundsException
e
)
{
break
parsing
;
}
}
// Do the final processing for both of the above cases. We only
// arrive here if the form GMT+/-... or an RFC 822 form was seen.
if
(
sign
!=
0
)
{
offset
*=
MILLIS_PER_MINUTE
*
sign
;
calb
.
set
(
Calendar
.
ZONE_OFFSET
,
offset
).
set
(
Calendar
.
DST_OFFSET
,
0
);
return
++
pos
.
index
;
}
}
break
parsing
;
default
:
// case PATTERN_DAY_OF_MONTH: // 'd'
// case PATTERN_HOUR_OF_DAY0: // 'H' 0-based. eg, 23:59 + 1 hour =>> 00:59
...
...
@@ -2102,7 +2266,7 @@ public class SimpleDateFormat extends DateFormat {
* @exception NullPointerException if the given pattern is null
* @exception IllegalArgumentException if the given pattern is invalid
*/
public
void
applyPattern
(
String
pattern
)
public
void
applyPattern
(
String
pattern
)
{
compiledPattern
=
compile
(
pattern
);
this
.
pattern
=
pattern
;
...
...
test/java/text/Format/DateFormat/ISO8601ZoneTest.java
0 → 100644
浏览文件 @
99cad872
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 4919632
* @summary Unit test for ISO8601 time zone format support
*/
import
java.text.*
;
import
java.util.*
;
public
class
ISO8601ZoneTest
{
static
final
Date
TIMESTAMP
=
new
Date
(
1283758039020L
);
static
final
String
[][]
formatData
=
{
// time zone name, expected output at TIMESTAMP
{
"America/Los_Angeles"
,
"2010-09-06T00:27:19.020-07"
,
},
{
"America/Los_Angeles"
,
"2010-09-06T00:27:19.020-0700"
,
},
{
"America/Los_Angeles"
,
"2010-09-06T00:27:19.020-07:00"
,
},
{
"Australia/Sydney"
,
"2010-09-06T17:27:19.020+10"
,
},
{
"Australia/Sydney"
,
"2010-09-06T17:27:19.020+1000"
,
},
{
"Australia/Sydney"
,
"2010-09-06T17:27:19.020+10:00"
,
},
{
"GMT-07:00"
,
"2010-09-06T00:27:19.020-07"
,
},
{
"GMT-07:00"
,
"2010-09-06T00:27:19.020-0700"
,
},
{
"GMT-07:00"
,
"2010-09-06T00:27:19.020-07:00"
,
},
{
"UTC"
,
"2010-09-06T07:27:19.020Z"
,
},
{
"UTC"
,
"2010-09-06T07:27:19.020Z"
,
},
{
"UTC"
,
"2010-09-06T07:27:19.020Z"
,
},
};
static
final
String
[]
zones
=
{
"America/Los_Angeles"
,
"Australia/Sydney"
,
"GMT-07:00"
,
"UTC"
,
"GMT+05:30"
,
"GMT-01:23"
,
};
static
final
String
[]
isoZoneFormats
=
{
"yyyy-MM-dd'T'HH:mm:ss.SSSX"
,
"yyyy-MM-dd'T'HH:mm:ss.SSSXX"
,
"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"
,
};
static
final
String
[][]
badData
=
{
{
"X"
,
"1"
},
{
"X"
,
"+1"
},
{
"X"
,
"-2"
},
{
"X"
,
"-24"
},
{
"X"
,
"+24"
},
{
"XX"
,
"9"
},
{
"XX"
,
"23"
},
{
"XX"
,
"234"
},
{
"XX"
,
"3456"
},
{
"XX"
,
"23456"
},
{
"XX"
,
"+1"
},
{
"XX"
,
"-12"
},
{
"XX"
,
"+123"
},
{
"XX"
,
"-12:34"
},
{
"XX"
,
"+12:34"
},
{
"XX"
,
"-2423"
},
{
"XX"
,
"+2423"
},
{
"XX"
,
"-1260"
},
{
"XX"
,
"+1260"
},
{
"XXX"
,
"9"
},
{
"XXX"
,
"23"
},
{
"XXX"
,
"234"
},
{
"XXX"
,
"3456"
},
{
"XXX"
,
"23456"
},
{
"XXX"
,
"2:34"
},
{
"XXX"
,
"12:4"
},
{
"XXX"
,
"12:34"
},
{
"XXX"
,
"-1"
},
{
"XXX"
,
"+1"
},
{
"XXX"
,
"-12"
},
{
"XXX"
,
"+12"
},
{
"XXX"
,
"-123"
},
{
"XXX"
,
"+123"
},
{
"XXX"
,
"-1234"
},
{
"XXX"
,
"+1234"
},
{
"XXX"
,
"+24:23"
},
{
"XXX"
,
"+12:60"
},
{
"XXX"
,
"+1:23"
},
{
"XXX"
,
"+12:3"
},
};
static
String
[]
badFormats
=
{
"XXXX"
,
"XXXXX"
,
"XXXXXX"
,
};
public
static
void
main
(
String
[]
args
)
throws
Exception
{
TimeZone
tz
=
TimeZone
.
getDefault
();
try
{
for
(
int
i
=
0
;
i
<
formatData
.
length
;
i
++)
{
TimeZone
.
setDefault
(
TimeZone
.
getTimeZone
(
formatData
[
i
][
0
]));
formatTest
(
isoZoneFormats
[
i
%
isoZoneFormats
.
length
],
formatData
[
i
][
1
]);
}
for
(
String
zone
:
zones
)
{
TimeZone
.
setDefault
(
TimeZone
.
getTimeZone
(
zone
));
for
(
String
fmt
:
isoZoneFormats
)
{
roundtripTest
(
fmt
);
SimpleDateFormat
f
=
new
SimpleDateFormat
(
fmt
);
}
}
for
(
String
[]
d
:
badData
)
{
badDataParsing
(
d
[
0
],
d
[
1
]);
}
for
(
String
fmt
:
badFormats
)
{
badFormat
(
fmt
);
}
}
finally
{
TimeZone
.
setDefault
(
tz
);
}
}
static
void
formatTest
(
String
fmt
,
String
expected
)
throws
Exception
{
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
fmt
);
String
s
=
sdf
.
format
(
TIMESTAMP
);
if
(!
expected
.
equals
(
s
))
{
throw
new
RuntimeException
(
"formatTest: got "
+
s
+
", expected "
+
expected
);
}
Date
d
=
sdf
.
parse
(
s
);
if
(
d
.
getTime
()
!=
TIMESTAMP
.
getTime
())
{
throw
new
RuntimeException
(
"formatTest: parse("
+
s
+
"), got "
+
d
.
getTime
()
+
", expected "
+
TIMESTAMP
.
getTime
());
}
ParsePosition
pos
=
new
ParsePosition
(
0
);
d
=
sdf
.
parse
(
s
+
"123"
,
pos
);
if
(
d
.
getTime
()
!=
TIMESTAMP
.
getTime
())
{
throw
new
RuntimeException
(
"formatTest: parse("
+
s
+
"), got "
+
d
.
getTime
()
+
", expected "
+
TIMESTAMP
.
getTime
());
}
if
(
pos
.
getIndex
()
!=
s
.
length
())
{
throw
new
RuntimeException
(
"formatTest: wrong resulting parse position: "
+
pos
.
getIndex
()
+
", expected "
+
s
.
length
());
}
}
static
void
roundtripTest
(
String
fmt
)
throws
Exception
{
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
fmt
);
Date
date
=
new
Date
();
int
fractionalHour
=
sdf
.
getTimeZone
().
getOffset
(
date
.
getTime
());
fractionalHour
%=
3600000
;
// fraction of hour
String
s
=
sdf
.
format
(
date
);
Date
pd
=
sdf
.
parse
(
s
);
long
diffsInMillis
=
pd
.
getTime
()
-
date
.
getTime
();
if
(
diffsInMillis
!=
0
)
{
if
(
diffsInMillis
!=
fractionalHour
)
{
throw
new
RuntimeException
(
"fmt= "
+
fmt
+
", diff="
+
diffsInMillis
+
", fraction="
+
fractionalHour
);
}
}
}
static
void
badDataParsing
(
String
fmt
,
String
text
)
{
try
{
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
fmt
);
sdf
.
parse
(
text
);
throw
new
RuntimeException
(
"didn't throw an exception: fmt="
+
fmt
+
", text="
+
text
);
}
catch
(
ParseException
e
)
{
// OK
}
}
static
void
badFormat
(
String
fmt
)
{
try
{
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
fmt
);
throw
new
RuntimeException
(
"Constructor didn't throw an exception: fmt="
+
fmt
);
}
catch
(
IllegalArgumentException
e
)
{
// OK
}
try
{
SimpleDateFormat
sdf
=
new
SimpleDateFormat
();
sdf
.
applyPattern
(
fmt
);
throw
new
RuntimeException
(
"applyPattern didn't throw an exception: fmt="
+
fmt
);
}
catch
(
IllegalArgumentException
e
)
{
// OK
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录