Here is the code relevant to the discussion:
1) DateTimeConverter.java#getFormattingTimeZone(TimeZone tZone)
This effectively creates a timezone with customized id.
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