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


Reply via email to