I am exploring the new java.time API of Java 8. I am particularly trying to retrieve the current time (my current time zone, of a different time zone, and of a different offset).
The code is:
public static void getCurrentLocalTime(){
LocalTime time = LocalTime.now();
System.out.println("Local Time Zone: "+ZoneId.systemDefault().toString());
System.out.println("Current local time : " + time);
}
public static void getCurrentTimeWithTimeZone(){
LocalDateTime localtDateAndTime = LocalDateTime.now();
ZoneId zoneId = ZoneId.of("America/Los_Angeles");
ZonedDateTime dateAndTimeInLA = ZonedDateTime.of(localtDateAndTime, zoneId);
String currentTimewithTimeZone =dateAndTimeInLA.getHour()+":"+dateAndTimeInLA.getMinute();
System.out.println("Current time in Los Angeles: " + currentTimewithTimeZone);
}
public static void getCurrentTimeWithZoneOffset(){
LocalTime localtTime = LocalTime.now();
ZoneOffset offset = ZoneOffset.of("-08:00");
OffsetTime offsetTime = OffsetTime.of(localtTime, offset);
String currentTimewithZoneOffset =offsetTime.getHour()+":"+offsetTime.getMinute();
System.out.println("Current time with offset -08:00: " + currentTimewithZoneOffset);
}
But, when I call the methods I get the same time-of-day (my system time), which is obviously not what I am expecting.
The output of the method calls:
Current time in Los Angeles: 19:59
Local Time Zone: Asia/Calcutta
Current local time : 19:59:20.477
Current time with offset -08:00: 19:59
Even after setting a different time zone and offset, why am I getting the same time?
LocalDateTime.now()
always returns the current date/time in your default timezone (say 13 October @ 11.20am in London). When you create a ZonedDateTime
or OffsetTime
from it with a specific ZoneId
or ZoneOffset
, you get the same date and time but in a different time zone (for example 13 october at 11.20am in Los Angeles), which represents a different instant in time.
You are probably looking for something like:
Instant now = Instant.now();
ZoneId zoneId = ZoneId.of("America/Los_Angeles");
ZonedDateTime dateAndTimeInLA = ZonedDateTime.ofInstant(now, zoneId);
This will calculate the current date and time in Los Angeles: 13 october, 3.20am.
Consider the following fixed methods:
public static void getCurrentLocalTime() {
LocalTime time = LocalTime.now();
System.out.println("Local Time Zone: " + ZoneId.systemDefault().toString());
System.out.println("Current local time : " + time);
}
public static void getCurrentTimeWithTimeZone() {
LocalDateTime localDateAndTime = LocalDateTime.now(ZoneId.of("America/Los_Angeles"));
System.out.println("Current time in Los Angeles: " + localDateAndTime.toLocalTime());
}
public static void getCurrentTimeWithZoneOffset() {
LocalTime localTime = LocalTime.now(ZoneOffset.of("-08:00"));
System.out.println("Current time with offset -08:00: " + localTime);
}
What changed is that instead of calling now()
, the call is made to now(zone)
. That is because now()
always return the current system time in your time-zone. The calls to atZone
, OffsetTime.of
or ZoneDateTime.of
do not change the date/time, it only tells Java Time that the date should be understood at a date/time in this timezone.
When calling these 3 methods, here's the output on my machine:
Local Time Zone: Europe/Paris
Current local time : 12:32:21.560
Current time in Los Angeles: 03:32:21.579
Current time with offset -08:00: 02:32:21.580
To make this very clear: you're in Europe and call LocalDateTime.now().atZone(ZoneId.of("America/Los_Angeles"))
- you are creating a date/time which represents the current-time in Europe as if you were located in Los Angeles, so you are creating a date/time which is actually in the future for Los Angeles residents (8 or 9 hours in the future, depending on DST).
There is also another way of displaying time in another zone by using withZoneSameInstant
:
// now, in current zone,
// 2016-04-13T14:24:57.618+02:00[Europe/Warsaw]
ZonedDateTime now = ZonedDateTime.now();
// 2016-04-13T05:24:57.618-07:00[America/Los_Angeles]
ZonedDateTime losAngelesDateTime = now.withZoneSameInstant(ZoneId.of("America/Los_Angeles"));