You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@myfaces.apache.org by Yee-wah Lee <ye...@oracle.com> on 2009/07/10 01:15:04 UTC
[Trinidad] DateTimeConverter and SimpleDateFormat changes in JDK
6 lead to issue with daylight savings
Hi everyone,
The Trinidad DateTimeConverter has a problem when using JDK 6, because
of changes in SimpleDateFormat. I have written a test case to replicate
the converter's behavior.
Test case:
DateFormat df = DateFormat.getDateTimeInstance (DateFormat.SHORT,
DateFormat.LONG);
Date d = new Date();
// getFormattingTimeZone copied from
trinidad-impl\DateTimeConverter.java, it clones the converter's timezone
and gives it a
// customID (GMT +/- offset)./ This affects the display name, e.g.
instead of 'PST' it will display 'GMT-08:00'
TimeZone tz = getFormattingTimeZone (df.getTimeZone());
df.setTimeZone (tz);
System.out.println ("The date is " + d + ", DateFormat.format()
returns " + df.format (d));
On JDK 1.5 this prints:
The date is Wed Jul 08 10:55:25 PDT 2009, DateFormat.format() returns
7/8/09 10:55:25 AM GMT-07:00
On JDK 6:
The date is Wed Jul 08 10:56:39 PDT 2009, DateFormat.format() returns
7/8/09 10:56:39 AM GMT-08:00
Notice that the offset in the second case is 8h. This is incorrect, the
date (Jul 8 09) is in Pacific Daylight time (GMT-7), and if posted
back, it would change the underlying data by +1h.
I can understand why getFormattingTimeZone was originally used: timezone
is thus always displayed in GMT +/- x, which helps when calculating
offsets on the client side. I would like to discuss the possible fixes
for the JDK 6 case (details to follow in second email), any input is
welcome.
I've filed a JIRA tracking this:
https://issues.apache.org/jira/browse/TRINIDAD-1512
Thanks,
Yee-Wah
Re: [Trinidad] DateTimeConverter and SimpleDateFormat changes in
JDK 6 lead to issue with daylight savings: code snippets
Posted by Yee-wah Lee <ye...@oracle.com>.
Here is the code relevant to the discussion:
1) DateTimeConverter.java#getFormattingTimeZone(TimeZone tZone)
This effectively creates a custom timezone.
TimeZone zone = (TimeZone) tZone.clone();
// set the id as "GMT Sign Hours : Minutes"
StringBuilder zoneId = new StringBuilder(9);
int rawOffset = zone.getRawOffset();
.. code to calculate and append GMT +/- hours:mins
zone.setID(zoneId.toString());
return zone;
2) JDK 1.5: SimpleDateFormat#subFormat()
The 1.5 format code would look up a zone info file using the date's
offset and daylight savings.
case 17: // 'z' - ZONE_OFFSET
int zoneIndex =
formatData.getZoneIndex(calendar.getTimeZone().getID());
if (zoneIndex == -1) {
value = calendar.get(Calendar.ZONE_OFFSET) +
calendar.get(Calendar.DST_OFFSET);
buffer.append(ZoneInfoFile.toCustomID(value));
<---------Uses this code path
}....
3) JDK 6: SimpleDateFormat#subFormat()
The 1.6 code now checks the DateFormatSymbols.locale and
isZoneStringsSet(). By default, the locale would be null and
zoneStringsSet = false unless user overrides either.
It then calls TimeZone.getDisplayName() instead of checking the
zoneInfoFile.
case 17: // 'z' - ZONE_OFFSET
if (formatData.locale == null || formatData.isZoneStringsSet) {
..
// same as 1.5, looks up zone info file
String[][] zoneStrings = formatData.getZoneStringsWrapper();
buffer.append(zoneStrings[zoneIndex][index]);
} else {
TimeZone tz = calendar.getTimeZone();
boolean daylight = (calendar.get(Calendar.DST_OFFSET) != 0);
int tzstyle = (count < 4 ? TimeZone.SHORT : TimeZone.LONG);
buffer.append(tz.getDisplayName(daylight, tzstyle,
formatData.locale)); <------------ Uses this code path
}...
4) JDK 1.5/6: TimeZone.getDisplayName()
This method is the same in both JDKs, but only called in JDK 6 case. If
the ID is customized (GMT +/-x), it simply returns that.
String id = getID();
String[] names = getDisplayNames(id, locale);
if (names == null) {
if (id.startsWith("GMT")) {
char sign = id.charAt(3);
if (sign == '+' || sign == '-') {
return id;
Therefore, the display name for the Converter's timezone in JDK 6 is
fixed as its ID (GMT+/-rawOffset).
Notes:
1) Although this used to work in JDK 1.5, I'm not convinced this is a
JDK issue. Since we are creating a custom timezone in
getFormattingTimeZone(), and the JDK documentation states: "No daylight
saving time transition schedule can be specified with a custom time zone
ID."
http://java.sun.com/javase/6/docs/api/java/util/TimeZone.html#setID%28java.lang.String
Arguably, the DateTimeConverter should get the formattingTimeZone() with
the value to be formatted included, so it instead does:
StringBuilder zoneId = new StringBuilder(9);
int offset = zone.getOffset((Date) value);
2) On the other hand, I don't understand the check in #subformat() for
formatData.locale or formatData.isZoneStringsSet.
It seems like a change for the default behavior in SimpleDateFormat
since most users will not plug-in their own DateFormatSymbols, and the
defaults for those fields is false.
Yee-Wah
Yee-wah Lee wrote:
> Hi everyone,
>
> The Trinidad DateTimeConverter has a problem when using JDK 6, because
> of changes in SimpleDateFormat. I have written a test case to
> replicate the converter's behavior.
>
> Test case:
> DateFormat df = DateFormat.getDateTimeInstance (DateFormat.SHORT,
> DateFormat.LONG);
> Date d = new Date();
> // getFormattingTimeZone copied from
> trinidad-impl\DateTimeConverter.java, it clones the converter's
> timezone and gives it a
> // customID (GMT +/- offset)./ This affects the display name,
> e.g. instead of 'PST' it will display 'GMT-08:00'
> TimeZone tz = getFormattingTimeZone (df.getTimeZone());
> df.setTimeZone (tz);
> System.out.println ("The date is " + d + ", DateFormat.format()
> returns " + df.format (d));
>
> On JDK 1.5 this prints:
> The date is Wed Jul 08 10:55:25 PDT 2009, DateFormat.format() returns
> 7/8/09 10:55:25 AM GMT-07:00
>
> On JDK 6:
> The date is Wed Jul 08 10:56:39 PDT 2009, DateFormat.format() returns
> 7/8/09 10:56:39 AM GMT-08:00
>
> Notice that the offset in the second case is 8h. This is incorrect,
> the date (Jul 8 09) is in Pacific Daylight time (GMT-7), and if
> posted back, it would change the underlying data by +1h.
>
> I can understand why getFormattingTimeZone was originally used:
> timezone is thus always displayed in GMT +/- x, which helps when
> calculating offsets on the client side. I would like to discuss the
> possible fixes for the JDK 6 case (details to follow in second email),
> any input is welcome.
>
> I've filed a JIRA tracking this:
> https://issues.apache.org/jira/browse/TRINIDAD-1512
>
> Thanks,
> Yee-Wah