2

I am using the Calendar class in java and am having trouble. I have this code

Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("NZST"));
System.out.println("Calendar.HOUR_OF_DAY = " + calendar.get(Calendar.HOUR_OF_DAY));
System.out.println("Calendar.HOUR = " + calendar.get(Calendar.HOUR));
System.out.println("calendar.getTime() = " + calendar.getTime());

and I would expect it to output

Calendar.HOUR_OF_DAY = 17
Calendar.HOUR = 5
calendar.getTime() = Sat Aug 08 17:45:53 NZST 2020

but instead it outputs

Calendar.HOUR_OF_DAY = 5
Calendar.HOUR = 5
calendar.getTime() = Sat Aug 08 17:45:53 NZST 2020

So why does the HOUR_OF_DAY and HOUR return the same thing however, calendar.getTime() shows the correct HOUR_OF_DAY. They are both using NZST.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • I recommend you don’t use `Calendar` and `TimeZone`. Those classes are poorly designed and long outdated. Instead use `ZonedDateTime` and `ZoneId`, both from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). See [the answer by Basil Bourque](https://stackoverflow.com/a/63312411/5772882). – Ole V.V. Aug 08 '20 at 19:20

2 Answers2

3

They are both using NZST.

No, they're not, although I can see why you think they are.

The first is actually using UTC, because "NZST" is not a valid time zone ID. It's a shame that TimeZone.getTimeZone doesn't throw an exception when you present it with an invalid ID, but that can't be changed now :(

calendar.getTime() is returning a Date reference, and Date doesn't have a time zone so it's printing in your system local time zone - which happens to be New Zealand.

If you change your first line of code to use a real time zone ID, it behaves as you expect it to:

Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Pacific/Auckland"));

A few abbreviations (like NZST) are recognized as time zone IDs in Java, but it's always better to use the full IANA time zone ID, like "Pacific/Auckland".

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
1

tl;dr

ZonedDateTime
.now( 
    ZoneId.of( "Pacific/Auckland" ) 
) 
.getHour()

Details

The Answer by Jon Skeet is correct. In addition, you are using terrible classes that were supplanted years ago by the java.time classes defined in JSR 310.

The ZoneId class in java.time replaces the legacy class TimeZone. This class ZoneId fulfills the wish in Jon Skeet’s Answer: If you feed it a false zone ID like NZST, it throws an exception.

java.time

ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;  // Specify a time zone. A history of past, present, and future changes to the offset-from-UTC used by the people of a particular region. 
ZonedDateTime zdt = ZonedDateTime.now( z ) ;  // Capture the current time as seen in a particular time zone.
int hour = zdt.getHour() ;                    // Extract the hour of he day.
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154