Reputation: 4327
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
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.
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]
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
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