简体   繁体   中英

Convert time back from UTC to specified TimeZone

Being entirely confused of what's going in with java time and why there are thousands of posts related to this I somehow managed to store time in UTC using jodaTime:

Calendar cal = new GregorianCalendar();

cal.setTimeInMillis(DateTimeZone.getDefault().convertLocalToUTC(
                            cal.getTimeInMillis(), false));

Since I am using hibernate(and not willing to use adapters for JodaTime to work correctly with version 4) I only use this jodaTime method to convert jdk time to utc. This seems to produce expected result and the local time(current london GMT+1) gets converted to UTC via subtracting 1 from this local time.

So far so good. Then whenever I retrieve my time for specific timezone I get incorrect offset of -2 where it should be -3 including DST.

Calendar cal = new GregorianCalendar();

  System.out.println("Local London Hours: "+cal.get(Calendar.HOUR_OF_DAY)); System.out.println("Local London Milliseconds: "+cal.getTimeInMillis()); cal.setTimeInMillis(DateTimeZone.getDefault().convertLocalToUTC( cal.getTimeInMillis(), false)); System.out.println("UTC Hours: "+cal.get(Calendar.HOUR_OF_DAY)); System.out.println("UTC Milliseconds: "+cal.getTimeInMillis()); // Time for specific time zone cal.setTimeZone(TimeZone.getTimeZone("Europe/Vilnius")); System.out.println("Vilnius Hours: "+cal.get(Calendar.HOUR_OF_DAY)); System.out.println("Vilnius Milliseconds: "+cal.getTimeInMillis()); // is this time in DST? - Yes System.out.println("Vilnius time is in DST: "+TimeZone.getTimeZone("Europe/Vilnius").inDaylightTime(cal.getTime())); 

http://www.timeanddate.com/worldclock/city.html?n=660 Time zone details for specific timezone

Output:

Local London Hours: 21

Local London Milliseconds: 1381869901339

UTC Hours: 20

UTC Milliseconds: 1381866301339

Vilnius Hours: 22 // this should be 23 (according to link)

Vilnius Milliseconds: 1381866301339

Vilnius time is in DST: true // no, it is not since hours value is not 23

Use

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Europe/London");

to get London time.

You should be able to change it to UTC with:

cal.setTimeZone(TimeZone.getTimeZone("UTC"));

But, there is a funny thing about the Calendar class. Before you change the time zone and afterwards, it works best if you get some value from it. So add a line like,

cal.get(Calendar.HOUR_OF_DAY);

This causes the Calendar object to readjust all its internal fields.

The problem is that it stores the time in milliseconds and it stores the hour and day and minute and all that in other fields. If you set the hour, it doesn't update the millisecond time until you read some field. That's in case you are going to set the date and the hour and everything so it doesn't have to recalculate every time, just once you get them all changed.

Similarly, if you change the millisecond time or the timezone, it doesn't recalculate the hour and day and such until you read them.

(Note that this will totally confuse you if you are using a debugger because the debugger will typically call one of the get() s to display values in the debug console. That will fix the Calendar object and you won't have the problem when single-stepping. Can you tell I've been there? )

So ... it can get confused and the magic line above makes it work if you put it in enough in the right place. And it never hurts.

NOTE

If you store the calendar as a TIMESTAMP in a database using JDBC, it will store the millisecond time (or we can think of it that way).

Then, when JDBC reads the millisecond time, creates a Calendar object and returns it to you. The created Calendar has the default TimeZone in it.

Deal with this just as you did with converting the London time to UTC.

cal.get(Calendar.HOUR_OF_DAY); // funky Calendar magic to make sure it works
cal.setTimeZone(TimeZone.getTimeZone("UTC"));

All this does is change the stored TimeZone so that when the next code like get(Calendar.HOUR_OF_DAY) executes, it converts the stored millisecond value to the correct timezone's hour of the day (ie UTC).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM