Reputation: 9935
Why does the program printout the same output/time with different TimeZone
?
Calendar cal = GregorianCalendar.getInstance();
TimeZone timeZone_1 = TimeZone.getTimeZone("Asia/Rangoon");
cal.setTimeZone(timeZone_1);
System.out.println(cal.getTime());
TimeZone timeZone_2 = TimeZone.getTimeZone("Asia/Tokyo");
cal.setTimeZone(timeZone_2);
System.out.println(cal.getTime());
Example Output :
Thu Nov 22 09:00:33 MMT 2012
Thu Nov 22 09:00:33 MMT 2012
My Expected Output is:
Thu Nov 22 09:00:33 MMT 2012
Thu Nov 22 11:30:33 MMT 2012
Upvotes: 2
Views: 90
Reputation: 338181
Instant // Represent a moment as seen in UTC, that is, with an offset from UTC of zero hours-minutes-seconds.
.now() // Capture the current moment in UTC.
.atZone( ZoneId.of( "Asia/Rangoon" ) ) // Adjust from UTC to a particular time zone. Same moment, different wall-clock/calendar.
.atZoneSameInstant( ZoneId.of( "Asia/Tokyo" ) ) // Adjust from one time zone to another. Same moment, different wall-clock/calendar.
.toString() // Generate text in ISO 8601 format wisely extended to append the name of time zone in square brackets.
java.util.Date#toString
tells a lieThe Answer by Tomasz Nurkiewicz is correct. Your call to cal.getTime()
returns a java.util.Date
object whose toString
method lies to you. That Date#toString
method has the anti-feature of dynamically applying a current default time zone to its value which is actually stored as a moment seen in UTC (an offset-from-UTC of zero hours-minutes-seconds).
This anti-feature is one of many reasons to avoid Date
& Calendar
classes.
You are using terribly flawed date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310.
ZonedDateTime
To represent the current moment, use Instant
.
You can adjust that moment to be seen through a particular time zone. Apply a ZoneId
to produce a [ZonedDateTime][2]
object.
ZoneId zRangoon = ZoneId.of( "Asia/Rangoon" );
ZoneId zTokyo = ZoneId.of( "Asia/Tokyo" ) ;
Instant instant = Instant.now() ; // Always in UTC (offset of zero).
// Adjust that moment into particular time zones.
ZonedDateTime zdtRangoon = instant.atZone( zRangoon ) ;
ZonedDateTime zdtTokyo = instant.atZone( zTokyo ) ;
The objects referenced by variables instant
, zdtRangoon
, and zdtTokyo
all represent the very same moment, the same point on the timeline — three views, one moment.
Call ZonedDateTime#toString
to generate text in standard ISO 8601 format wisely extended to append the name of time zone in square brackets.
String outputRangoon = zdtRangoon.toString() ;
String outputTokyo = zdtTokyo.toString() ;
See this code run at Ideone.com. Notice the difference in date as well as time-of-day.
instant.toString() = 2023-12-31T20:36:15.449185Z
outputRangoon = 2024-01-01T03:06:15.449185+06:30[Asia/Rangoon]
outputTokyo = 2024-01-01T05:36:15.449185+09:00[Asia/Tokyo]
To get localized output, use DateTimeFormatter.ofLocalizedDateTime
. Search Stack Overflow to find more info.
Upvotes: 0
Reputation: 340708
Your code is fine, it's only the debug output that's wrong (misleading). cal.getTime()
returns Date
object, which is independent from time zone. But Date.toString()
always prints this date with systems' time zone. Date.toString()
is so counterintuitive (it displays calendar time with system time zone while it barely stores number of millliseconds) that it should have been banned/deprecated.
To have accurate logging use SimpleDateFormat
or call various Calendar.get*()
methods instead:
System.out.println(cal.get(Calendar.HOUR_OF_DAY));
System.out.println(cal.get(Calendar.MINUTE));
And as always with any questions regarding Java date/time handling, consider jodatime...
Upvotes: 4