24

I am trying to obtain a simple conversion from one time zone into another using Java Date and Calendar. I am trying to run the following code

    Calendar instance = Calendar.getInstance(TimeZone.getTimeZone("Europe/London"));
    Date date = instance.getTime();
    System.out.println(date);

    GregorianCalendar instance2 = new GregorianCalendar(TimeZone.getTimeZone("Europe/Athens"));
    instance2.setTime(instance.getTime());
    System.out.println(instance2.getTime());

but that still returns the same date, rather than +1 hour... The whole problem seems trivial but i cannot find any simple answer to this. Thanks in advance for your help.

Marc
  • 16,170
  • 20
  • 76
  • 119
Bober02
  • 15,034
  • 31
  • 92
  • 178
  • 4
    Would you like to use [Joda time](http://stackoverflow.com/a/375803/1037210)? It's my preference. – Lion Nov 02 '12 at 15:13
  • Check [this answer](http://stackoverflow.com/questions/230126/how-to-handle-calendar-timezones-using-java). It could come in handy. – Fritz Nov 02 '12 at 15:19
  • I found another thing on the web, which is probably the cleanest solution, to use a date time format to parse the date string and return the Date in the corresponding time zone – Bober02 Nov 02 '12 at 15:26
  • See https://www.mkyong.com/java/java-convert-date-and-time-between-timezone/ – Grigory Kislin Jul 20 '16 at 10:32

3 Answers3

37

When you print the date using System.out.println(date); or System.out.println(instance2.getTime());, the Date returned by instance2.getTime() is TimeZone independent and always prints the date in local timezone.

Instead you may want to use DateFormat/SimpleDateFormat:

  DateFormat formatter= new SimpleDateFormat("MM/dd/yyyy HH:mm:ss Z");
  formatter.setTimeZone(TimeZone.getTimeZone("Europe/London"));
  System.out.println(formatter.format(date));

  formatter.setTimeZone(TimeZone.getTimeZone("Europe/Athens"));
  System.out.println(formatter.format(instance2.getTime()))
James
  • 305
  • 2
  • 7
Yogendra Singh
  • 33,927
  • 6
  • 63
  • 73
  • Are you sure it's the local timezone and not EPOCH seconds (timezone-independant)? http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#getTime() – akaIDIOT Nov 02 '12 at 15:14
  • @akaIDIOT the internal representation is since epoch, when the date is printed the the local timezone is used, a feature/bug of `java.util.Date`. – dan Nov 02 '12 at 15:18
  • @Bober02: Did you find something better? If yes, please share. – Yogendra Singh Nov 02 '12 at 15:34
  • 2
    Obviously, formatter.format(instance2.getTime()) changes the timeZone but when we convert this string date back to date object, it again picks up the local timezone. Is there any solution for this? – Parkash Kumar Jun 21 '13 at 10:58
  • @ParkashKumar: Date is timezone independent so you have two workarounds. 1. Adjust the offset to treat the local date with timezone dependent value. 2. Use Timezone dependent objects with right handling. – Yogendra Singh Jun 21 '13 at 14:11
15

The accepted answer is correct. The java.util.Date class has no time zone assigned, yet it's toString implementation confusingly applies the JVM's current default time zone.

Avoid java.util.Date & .Calendar

This is one of many reasons to avoid the notoriously troublesome java.util.Date, .Calendar, and SimpleDateFormat classes bundled with Java. Avoid them. Instead use either:

Joda-Time

Some example code in Joda-Time 2.3 follows. Search StackOveflow for many more examples and much discussion.

DateTimeZone timeZoneLondon = DateTimeZone.forID( "Europe/London" );
DateTimeZone timeZoneAthens = DateTimeZone.forID( "Europe/Athens" );

DateTime nowLondon = DateTime.now( timeZoneLondon );
DateTime nowAthens = nowLondon.withZone( timeZoneAthens );
DateTime nowUtc = nowLondon.withZone( DateTimeZone.UTC );

java.time

Java 8 and later has a new java.time package built-in. This package was inspired by Joda-Time. While they share some similarities and class names, they are different; each has features the other lacks. One notable difference is that java.time avoids constructors, instead uses static instantiation methods.

In the case of this Question, they work in the same fashion. Specify a time zone, and call a now method to get current moment, then create a new instance based on the old immutable instance to adjust for time zone.

Note the two different time zone classes. One is a named time zone including all the rules for Daylight Saving Time and other such anomalies plus an offset from UTC while the other is only the offset.

ZoneId zoneMontréal = ZoneId.of("America/Montreal"); 
ZonedDateTime nowMontréal = ZonedDateTime.now ( zoneMontréal );

ZoneId zoneTokyo = ZoneId.of("Asia/Tokyo"); 
ZonedDateTime nowTokyo = nowMontréal.withZoneSameInstant( zoneTokyo );

ZonedDateTime nowUtc = nowMontréal.withZoneSameInstant( ZoneOffset.UTC );

Actually the java.util.Date class does have a time zone buried within its source code. But the class ignores that time zone for most practical purposes. So, as shorthand, it’s often said that j.u.Date has no time zone assigned. Confusing? Yes. Avoid the mess that is j.u.Date and go with Joda-Time and/or java.time.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
3

You can use the following code snippet

String dateString = "14 Jul 2014 00:11:04 CEST";
date = formatter.parse(dateString);
System.out.println(formatter.format(date));

// Set the formatter to use a different timezone - Indochina Time
formatter.setTimeZone(TimeZone.getTimeZone("Asia/Bangkok"));
System.out.println("ICT time : "+formatter.format(date));
Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Srijani Ghosh
  • 3,935
  • 7
  • 37
  • 68