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

Unexpected timezone returned after parsing a date

    Details

    • Subcomponent:
    • Resolved In Build:
      b96
    • CPU:
      generic
    • OS:
      generic
    • Verification:
      Verified

      Backports

        Description

        FULL PRODUCT VERSION :
        java version "1.7.0_76"
        Java(TM) SE Runtime Environment (build 1.7.0_76-b13)
        Java HotSpot(TM) 64-Bit Server VM (build 24.76-b04, mixed mode)

        ADDITIONAL OS VERSION INFORMATION :
        Linux adnlt043 2.6.32-504.8.1.el6.x86_64 #1 SMP Fri Dec 19 12:09:25 EST 2014 x86_64 x86_64 x86_64 GNU/Linux

        A DESCRIPTION OF THE PROBLEM :
        When parsing the virtual timezone "UTC" with java.text.SimpleDateFormat, the timezone is set to the first timezone that matches an actual timezone in the UTC group, which is Antarctica/Troll. When comparing this timezone with the result of TimeZone.getTimeZone("UTC"), we fail.

        ADDITIONAL REGRESSION INFORMATION:
        The comparison worked in JDK 1.7.0_21 and older versions of JDK.

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Compile and execute:

        public class TimeZoneTest {

        public static void main(String[] args) throws Exception {
        String dateString = "UTC";
        String formatString = "z";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(formatString);
        Date date = simpleDateFormat.parse(dateString);

        TimeZone timeZone = TimeZone.getTimeZone("UTC");

        long now = System.currentTimeMillis();

        Calendar cal = new GregorianCalendar(simpleDateFormat.getTimeZone());
        cal.setTime(date);

        if (timeZone.getOffset(now) == cal.getTimeZone().getOffset(now)) {
        System.out.println("Works as expected");
        } else {
        System.err.println("The timezone parsed with the simple date format has an offset '" +
        cal.getTimeZone().getOffset(now) + "', but the timezone offset of TimeZone.getTimeZone('UTC') is '" + timeZone.getOffset(now) + "'");
        }
        System.out.println("TimeZone.getTimeZone('UTC') : " + TimeZone.getTimeZone("UTC"));
        System.out.println("cal.getTimeZone() : " + cal.getTimeZone());
        }
        }


        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Works as expected
        TimeZone.getTimeZone('UTC') : sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
        cal.getTimeZone() : sun.util.calendar.ZoneInfo[id="Etc/UCT",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
        ACTUAL -
        The timezone parsed with the simple date format has an offset '7200000', but the timezone offset of TimeZone.getTimeZone('UTC') is '0'
        TimeZone.getTimeZone('UTC') : sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
        cal.getTimeZone() : sun.util.calendar.ZoneInfo[id="Antarctica/Troll",offset=0,dstSavings=7200000,useDaylight=true,transitions=67,lastRule=java.util.SimpleTimeZone[id=Antarctica/Troll,offset=0,dstSavings=7200000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]]


        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        public class TimeZoneTest {

        public static void main(String[] args) throws Exception {
        String dateString = "UTC";
        String formatString = "z";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(formatString);
        Date date = simpleDateFormat.parse(dateString);

        TimeZone timeZone = TimeZone.getTimeZone("UTC");

        long now = System.currentTimeMillis();

        Calendar cal = new GregorianCalendar(simpleDateFormat.getTimeZone());
        cal.setTime(date);

        if (timeZone.getOffset(now) == cal.getTimeZone().getOffset(now)) {
        System.out.println("Works as expected");
        } else {
        System.err.println("The timezone parsed with the simple date format has an offset '" +
        cal.getTimeZone().getOffset(now) + "', but the timezone offset of TimeZone.getTimeZone('UTC') is '" + timeZone.getOffset(now) + "'");
        }
        System.out.println("TimeZone.getTimeZone('UTC') : " + TimeZone.getTimeZone("UTC"));
        System.out.println("cal.getTimeZone() : " + cal.getTimeZone());
        }
        }

        ---------- END SOURCE ----------

          Issue Links

            Activity

            Hide
            psonal Pallavi Sonal added a comment -
            Attached is the test case.
            JDK 7 -Pass
            JDK 7u40 -Pass
            JDK 7u60 -Pass
            Below is the 'as expected' output on these versions:
            -----------------------------------------------------------------------------------
            Works as expected
            TimeZone.getTimeZone('UTC') : sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
            cal.getTimeZone() : sun.util.calendar.ZoneInfo[id="Etc/UCT",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
            -------------------------------------------------------------------------------------
            JDK 7u80 - Fail
            JDK 8 - Fail
            JDK 8u72 - Fail
            Below is the output on these version:
            --------------------------------------------------
            Works as expected
            TimeZone.getTimeZone('UTC') : sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
            cal.getTimeZone() : sun.util.calendar.ZoneInfo[id="Antarctica/Troll",offset=0,dstSavings=7200000,useDaylight=true,transitions=67,lastRule=java.util.SimpleTimeZone[id=Antarctica/Troll,offset=0,dstSavings=7200000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]]
            -------------------------------------------------------------------------------

            JDK 9ea b85 -Pass
            Below is the output:
            Works as expected
            TimeZone.getTimeZone('UTC') : sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
            cal.getTimeZone() : sun.util.calendar.ZoneInfo[id="Universal",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]

            ----------------------------------------------------------

            Moving across to dev-team for evaluation.
            Show
            psonal Pallavi Sonal added a comment - Attached is the test case. JDK 7 -Pass JDK 7u40 -Pass JDK 7u60 -Pass Below is the 'as expected' output on these versions: ----------------------------------------------------------------------------------- Works as expected TimeZone.getTimeZone('UTC') : sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null] cal.getTimeZone() : sun.util.calendar.ZoneInfo[id="Etc/UCT",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null] ------------------------------------------------------------------------------------- JDK 7u80 - Fail JDK 8 - Fail JDK 8u72 - Fail Below is the output on these version: -------------------------------------------------- Works as expected TimeZone.getTimeZone('UTC') : sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null] cal.getTimeZone() : sun.util.calendar.ZoneInfo[id="Antarctica/Troll",offset=0,dstSavings=7200000,useDaylight=true,transitions=67,lastRule=java.util.SimpleTimeZone[id=Antarctica/Troll,offset=0,dstSavings=7200000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]] ------------------------------------------------------------------------------- JDK 9ea b85 -Pass Below is the output: Works as expected TimeZone.getTimeZone('UTC') : sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null] cal.getTimeZone() : sun.util.calendar.ZoneInfo[id="Universal",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null] ---------------------------------------------------------- Moving across to dev-team for evaluation.
            Hide
            rpatil Ramanand Patil added a comment - - edited
            This issue happens only while parsing any abbreviated virtual timezone which is also present in the main timezone groups.(Like "UTC"), where it is part of "Antarctica/Troll" main group which includes:-
            Coordinated Universal Time, UTC, Central European Summer Time, CEST, Troll Time, ATT.
            And "UTC" is also in the main timezone group - UTC which includes:-
            Coordinated Universal Time, UTC, Coordinated Universal Time, UTC, Coordinated Universal Time, UTC.
            Hence to fix this issue what i have done is:- SimpleDateFormat's subParseZoneString(String text, int start, CalendarBuilder calb) method is altered to check and consider for the virtual zonenames which are also part of the main timezones(like UTC,IST,PST,MST,CST,etc...).

            Please note that, if you pass the other abbreviated virtual timezones which are not part of the main timezone groups(like AKST, ACST, AEST, WAT, etc...) you will find the previous behavior of setting the timezone to the main timezone in that group.
            Show
            rpatil Ramanand Patil added a comment - - edited This issue happens only while parsing any abbreviated virtual timezone which is also present in the main timezone groups.(Like "UTC"), where it is part of "Antarctica/Troll" main group which includes:- Coordinated Universal Time, UTC, Central European Summer Time, CEST, Troll Time, ATT. And "UTC" is also in the main timezone group - UTC which includes:- Coordinated Universal Time, UTC, Coordinated Universal Time, UTC, Coordinated Universal Time, UTC. Hence to fix this issue what i have done is:- SimpleDateFormat's subParseZoneString(String text, int start, CalendarBuilder calb) method is altered to check and consider for the virtual zonenames which are also part of the main timezones(like UTC,IST,PST,MST,CST,etc...). Please note that, if you pass the other abbreviated virtual timezones which are not part of the main timezone groups(like AKST, ACST, AEST, WAT, etc...) you will find the previous behavior of setting the timezone to the main timezone in that group.
            Hide
            okutsu Masayoshi Okutsu added a comment -
            The symptom is reproducible in JDK 9 with -Djava.locale.providers=COMPAT (a.k.a. JRE). Removed 9-na.
            Show
            okutsu Masayoshi Okutsu added a comment - The symptom is reproducible in JDK 9 with -Djava.locale.providers=COMPAT (a.k.a. JRE). Removed 9-na.
            Hide
            okutsu Masayoshi Okutsu added a comment -
            SimpleDateFormat.parse scans time zone names in resource bundles from the top and picks up whatever matched. The symptom is not reproducible with CLDR locale data because the display names for Antarctica/Troll doesn't follow the Olson tzdata. It's defined in tzdata as follows.

            # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
            #Rule Troll 2005 max - Mar 1 1:00u 1:00 CET
            Rule Troll 2005 max - Mar lastSun 1:00u 2:00 CEST
            #Rule Troll 2005 max - Oct lastSun 1:00u 1:00 CET
            #Rule Troll 2004 max - Nov 7 1:00u 0:00 UTC
            # Remove the following line when uncommenting the above '#Rule' lines.
            Rule Troll 2004 max - Oct lastSun 1:00u 0:00 UTC
            # Zone NAME GMTOFF RULES FORMAT [UNTIL]
            Zone Antarctica/Troll 0 - zzz 2005 Feb 12
            0:00 Troll %s

            But CLDR defines its names as "Greenwich Mean Time" and "GMT". Abbreviation "UTC" is used only for UTC.
            Show
            okutsu Masayoshi Okutsu added a comment - SimpleDateFormat.parse scans time zone names in resource bundles from the top and picks up whatever matched. The symptom is not reproducible with CLDR locale data because the display names for Antarctica/Troll doesn't follow the Olson tzdata. It's defined in tzdata as follows. # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S #Rule Troll 2005 max - Mar 1 1:00u 1:00 CET Rule Troll 2005 max - Mar lastSun 1:00u 2:00 CEST #Rule Troll 2005 max - Oct lastSun 1:00u 1:00 CET #Rule Troll 2004 max - Nov 7 1:00u 0:00 UTC # Remove the following line when uncommenting the above '#Rule' lines. Rule Troll 2004 max - Oct lastSun 1:00u 0:00 UTC # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Antarctica/Troll 0 - zzz 2005 Feb 12 0:00 Troll %s But CLDR defines its names as "Greenwich Mean Time" and "GMT". Abbreviation "UTC" is used only for UTC.
            Hide
            hgupdate HG Updates added a comment -
            URL: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/a1aa2671f281
            User: okutsu
            Date: 2015-12-03 06:34:50 +0000
            Show
            hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/a1aa2671f281 User: okutsu Date: 2015-12-03 06:34:50 +0000
            Hide
            hgupdate HG Updates added a comment -
            URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/a1aa2671f281
            User: lana
            Date: 2015-12-10 00:27:01 +0000
            Show
            hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/a1aa2671f281 User: lana Date: 2015-12-10 00:27:01 +0000

              People

              • Assignee:
                okutsu Masayoshi Okutsu
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                7 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: