simonC
simonC

Reputation: 4327

How to convert a UTC time to CET time in java

How can I convert a UTC time to CET time possibly using Joda-Time library in Java?

I was triing wit this but it looks like I'm doing something wrong

DateTime dateTime = new LocalDateTime(utdDate.getTime()).toDateTime(DateTimeZone.forID("CET"));

if I use this I get out the same time as I put in.

Upvotes: 4

Views: 13854

Answers (2)

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 78945

The accepted answer is excellent. I have written this answer about upgrading to java.time API. The java.time API was released in March 2014 as part of Java 8. The new code should use java.time.

java.time

Shown below is a notice on the Joda-Time Home Page:

Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.

Avoid time zone abbreviations

Given below is a note from the Java 7 Timezone documentation:

Three-letter time zone IDs

For compatibility with JDK 1.1.x, some other three-letter time zone IDs (such as "PST", "CTT", "AST") are also supported. However, their use is deprecated because the same abbreviation is often used for multiple time zones (for example, "CST" could be U.S. "Central Standard Time" and "China Standard Time"), and the Java platform can then only recognize one of them.

So, instead of CET, use a specific ZoneId e.g. Europe/Paris. Wikipedia maintains a list of zone names.

ZonedDateTime#withZoneSameInstant

Use ZonedDateTime#withZoneSameInstant to convert a ZonedDateTime to another ZonedDateTime in a different ZoneId.

If you have a LocalDateTime, first convert it into a ZonedDateTime using LocalDateTime#atZone before you use ZonedDateTime#withZoneSameInstant.

Demo:

class Main {
        public static void main(String[] args) {
                ZoneId sourceZone = ZoneId.of("Etc/UTC");
                ZoneId targetZone = ZoneId.of("Europe/Paris");

                // A sample local date-time at UTC
                LocalDateTime ldt = LocalDateTime.now(sourceZone);

                ZonedDateTime sourceZdt = ldt.atZone(sourceZone);
                ZonedDateTime targetZdt = sourceZdt.withZoneSameInstant(targetZone);

                System.out.println(sourceZdt);
                System.out.println(targetZdt);
        }
}

Output from a sample run:

2025-01-10T14:15:45.863591Z[Etc/UTC]
2025-01-10T15:15:45.863591+01:00[Europe/Paris]

Try it on Ideone

Note: If for some reason, you need an instance of java.util.Date, get it as java.util.Date.from(targetZdt.toInstant()).

Learn more about the modern Date-Time API from Trail: Date Time.

Upvotes: 3

Meno Hochschild
Meno Hochschild

Reputation: 44061

I strongly advise you to avoid the use of timezone names like "CET" because of the inherent localized nature. This might only be okay in formatted output for the end user, but not in internal coding.

CET stands for many different timezone ids like the IANA-IDs Europe/Berlin, Europe/Paris etc. In my timezone "Europe/Berlin" your code works like followed:

DateTime dateTime =
  new LocalDateTime(utdDate.getTime()) // attention: implicit timezone conversion
  .toDateTime(DateTimeZone.forID("CET"));
System.out.println(dateTime.getZone()); // CET
System.out.println(dateTime); // 2014-04-16T18:39:06.976+02:00

Remember that the expression new LocalDateTime(utdDate.getTime()) implicitly uses the system timezone for conversion and will therefore not change anything if your CET zone is internally recognized with equal timezone offset compared with your system timezone. In order to force JodaTime to recognize an UTC-input you should specify it like this way:

Date utdDate = new Date();
DateTime dateTime = new DateTime(utdDate, DateTimeZone.UTC);
System.out.println(dateTime); // 2014-04-16T16:51:31.195Z

dateTime = dateTime.withZone(DateTimeZone.forID("Europe/Berlin"));
System.out.println(dateTime); // 2014-04-16T18:51:31.195+02:00

This example preserves the instant that is the absolute time in milliseconds since UNIX epoch. If you want to preserve the fields and thereby changing the instant then you can use the method withZoneRetainFields:

Date utdDate = new Date();
dateTime = new DateTime(utdDate, DateTimeZone.UTC);
System.out.println(dateTime); // 2014-04-16T16:49:08.394Z

dateTime = dateTime.withZoneRetainFields(DateTimeZone.forID("Europe/Berlin"));
System.out.println(dateTime); // 2014-04-16T16:49:08.394+02:00

Upvotes: 3

Related Questions