Calendar.getInstance().getTime() returning date in “GMT” instead of Default TimeZone

后端 未结 3 750
温柔的废话
温柔的废话 2021-01-19 13:16
Calendar c = Calendar.getInstance();
System.out.println(c.getTime());
c.set(2007, 0, 1);
System.out.println(c.getTime());

Output:

3条回答
  •  滥情空心
    2021-01-19 14:10

    The second output in your question is the correct and expected behaviour on a JVM running Irish time (Europe/Dublin). On September 12, 2017 Ireland is on summer time (DST). While it is not clearly documented, Date.toString() (which you invoke implicitly when printing the Date you get from c.getTime()) prints the date and time in the JVM’s time zone, which in September is rendered as IST for Irish Summer Time.

    When you set the date on the Calendar object also using Irish time, the hour of day is preserved; in your case you get Jan 01 2007 12:36:24 Irish standard time. Now imagine the confusion if both Irish Summer Time and Irish Standard Time were rendered as IST. You would not be able to distinguish. Instead, since Irish standard time coincides with GMT, this is what Date.toString() prints when the date is not in the summer time part of the year (which January isn’t).

    My guess is that your first output is from a JVM running India time. It too is rendered as IST, and since India doesn’t use summer time, the same abbreviation is given summer and winter.

    java.time

    Before understanding the explanation for the behaviour you observed, I posted a comment about the outdated and the modern Java date and time classes. I still don’t think the comment is way off, though. This is the modern equivalent of your code:

        ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Europe/Dublin"));
        System.out.println(zdt);
        zdt = zdt.with(LocalDate.of(2007, Month.JANUARY, 1));
        System.out.println(zdt);
    

    It prints

    2017-09-12T11:45:33.921+01:00[Europe/Dublin]
    2007-01-01T11:45:33.921Z[Europe/Dublin]
    

    If you want to use the JVM’s time zone setting, use ZoneId.systemDefault() instead of ZoneId.of("Europe/Dublin"). As the name states, contrary to Date, ZonedDateTime does include a time zone. It corresponds more to the old Calendar class. As you can see, its toString method prints the offset from UTC (Z meaning zero offset) and the time zone name in the unambiguous region/city format. I believe that this leaves a lot less room for confusion. If you want to print the date in a specific format, use a DateTimeFormatter.

    Appendix: sample output from your code

    For the sake of completeness, here are the outputs from your code when running different time zones that may be rendered as IST:

    • Europe/Dublin (agrees with your second output)

      Tue Sep 12 11:19:28 IST 2017
      Mon Jan 01 11:19:28 GMT 2007
      
    • Asia/Tel_Aviv

      Tue Sep 12 13:19:28 IDT 2017
      Mon Jan 01 13:19:28 IST 2007
      
    • Asia/Kolkata (agrees with your first output)

      Tue Sep 12 15:49:28 IST 2017
      Mon Jan 01 15:49:28 IST 2007
      

提交回复
热议问题