Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8286102

TimeZone.getTimeZone(ZoneOffset) does not work for all ZoneOffsets and returns GMT unexpected

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 19
    • core-libs
    • None
    • behavioral
    • low
    • This is to additionally parse the seconds in Custom IDs, and the existing parsing for hours/minutes won't change, applications that only deal with hours/minutes won't see a change.
    • Java API
    • SE

      Summary

      Support Custom ID with seconds granularity resolution in java.util.TimeZone class.

      Problem

      In JDK, there are two classes to represent time zones. One is java.util.TimeZone, and the other is java.time.ZoneId. There are conversion methods between two classes in TimeZone class, i.e., TimeZone.getTimeZone(ZoneId) and TimeZone.toZoneId(). If the conversion from a ZoneId to a TimeZone fails in TimeZone.getTimeZone(ZoneId), it defaults to GMT zone. For a fixed offset zone, it should not fall back to GMT because it only relies on a fixed offset value from GMT. However, due to the offset granularity difference (TimeZone's Custom ID has minute-level resolution and ZoneOffset (a subclass of ZoneId which represents a fixed offset zone) has second-level resolution), ZoneOffset to TimeZone falls back to GMT when the offset involves non-zero seconds.

      Solution

      Extend the definition of TimeZone's Custom ID with seconds granularity and accept the notation such as GMT+00:00:01. For compatibility, the seconds part is optional, and normalized custom IDs will not include the seconds part if it is zero.

      Specification

      Modify the Custom ID description in the class description of TimeZone class as:

         * <blockquote><pre>
         * <a id="CustomID"><i>CustomID:</i></a>
      +  *         {@code GMT} <i>Sign</i> <i>Hours</i> {@code :} <i>Minutes</i> {@code :} <i>Seconds</i>
         *         {@code GMT} <i>Sign</i> <i>Hours</i> {@code :} <i>Minutes</i>
         *         {@code GMT} <i>Sign</i> <i>Hours</i> <i>Minutes</i>
         *         {@code GMT} <i>Sign</i> <i>Hours</i>
         * <i>Sign:</i> one of
         *         {@code + -}
         * <i>Hours:</i>
         *         <i>Digit</i>
         *         <i>Digit</i> <i>Digit</i>
         * <i>Minutes:</i>
         *         <i>Digit</i> <i>Digit</i>
      +  * <i>Seconds:</i>
      +  *         <i>Digit</i> <i>Digit</i>
         * <i>Digit:</i> one of
         *         {@code 0 1 2 3 4 5 6 7 8 9}
         * </pre></blockquote>
         *
      -  * <i>Hours</i> must be between 0 to 23 and <i>Minutes</i> must be
      +  * <i>Hours</i> must be between 0 to 23 and <i>Minutes</i>/<i>Seconds</i> must be
         * between 00 to 59.  For example, "GMT+10" and "GMT+0010" mean ten
         * hours and ten minutes ahead of GMT, respectively.

      Also modify the normalized Custom ID description as:

         * <blockquote><pre>
         * <a id="NormalizedCustomID"><i>NormalizedCustomID:</i></a>
      -  *         {@code GMT} <i>Sign</i> <i>TwoDigitHours</i> {@code :} <i>Minutes</i>
      +  *         {@code GMT} <i>Sign</i> <i>TwoDigitHours</i> {@code :} <i>Minutes</i> [<i>ColonSeconds</i>]
         * <i>Sign:</i> one of
         *         {@code + -}
         * <i>TwoDigitHours:</i>
         *         <i>Digit</i> <i>Digit</i>
         * <i>Minutes:</i>
         *         <i>Digit</i> <i>Digit</i>
      +  * <i>ColonSeconds:</i>
      +  *         {@code :} <i>Digit</i> <i>Digit</i>
         * <i>Digit:</i> one of
         *         {@code 0 1 2 3 4 5 6 7 8 9}
         * </pre></blockquote>
         * For example, TimeZone.getTimeZone("GMT-8").getID() returns "GMT-08:00".
      +  * <i>ColonSeconds</i> part only appears if the value is non-zero.

            naoto Naoto Sato
            uschindler Uwe Schindler
            Joe Wang
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: