How is it possible in Java to convert an instance of java.util.TimeZone
to org.joda.DateTimeZone
and keeping the daylight saving time?

- 809
- 8
- 21
-
What's wrong with [DateTimeZone#forTimeZone(TimeZone)](http://joda-time.sourceforge.net/apidocs/org/joda/time/DateTimeZone.html#forTimeZone(java.util.TimeZone))? – Costi Ciudatu Apr 06 '17 at 21:50
-
It's returning a FixedDateTimeZone instance which does not contains the daylight saving time values – Woody Apr 06 '17 at 21:53
-
1No, it doesn't. Post your code. – JB Nizet Apr 06 '17 at 22:36
-
Are you only interested in Joda-Time? The Joda-Time project is now in maintenance mode, with its creators advising migration to their new creation: the java.time classes built into Java 8 and later. – Basil Bourque Apr 07 '17 at 00:56
-
TimeZone timeZone = (Clock.buildTimeZone("test", 60, DateUtilTests.createDate(2013, Calendar.MARCH, 27), DateUtilTests.createDate(2013, Calendar.OCTOBER, 31), 180)); DateTime gmtDateTime = new DateTime(DateUtilTests.createDate(2013, Calendar.APRIL, 20, 02,00,0), DateTimeZone.forID("GMT")); DateTime localDateTime = gmtDateTime.withZone(DateTimeZone.forTimeZone(timeZone)); System.out.print(localDateTime); This is returning 2013-04-20T03:00:00.000+01:00 (Daylight saving time not taken into account) – Woody Apr 07 '17 at 13:24
-
In this example the timezone is gmt + 1 with 180 minutes for DST from 27 march to 31 of october – Woody Apr 07 '17 at 13:25
2 Answers
Joda-Time in maintenance-mode
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
java.time.ZoneId
The modern replacement for java.util.TimeZone
is java.time.ZoneId
& java.time.ZoneOffset
.
You should avoid the old legacy date-time classes. But if necessary, you can convert to/from the java.time types. Look to new methods added to the old classes. You can move between TimeZone
and ZoneId
.
java.util.TimeZone tz = java.util.TimeZone.getTimeZone( myZoneId );
…and…
java.time.ZoneId z = myLegacyTimeZone.toZoneId();
If you are looking for the offset-from-UTC or Daylight Saving Time (DST) info for the zone, look at the ZoneRules
class. Search Stack Overflow for more discussion and examples on that, or edit your Question to describe more about your goal.

- 303,325
- 100
- 852
- 1,154
-
You are right, I use now the new Java 8 API. And the code is simplier this way. Problem was the legacy system was generating custom TimeZone java object with wrong ids so the toZoneId was generating exception because these IDs was not supported – Woody Aug 08 '17 at 15:08
When you call DateTimeZone.forTimeZone
, it uses the timezone ID and Joda creates the equivalent object using its own DST rules - it doesn't import the rules from the TimeZone
object.
Another detail is that you're using "GMT", which is a zone without DST rules (just check the value for DateTimeZone.forID("GMT").isFixed()
- it returns true
meaning that the zone is fixed, AKA it doesn't have offset changes, AKA it has no DST).
It seems that you want a zone with London DST rules (based on the dates you've chosen to DST start and end). If that's the case, you can just create a zone using DateTimeZone.forID("Europe/London")
.
But if you want to create a custom zone with specific DST rules, you have to do it manually by extending DateTimeZone
class. One example of a zone with DST starting at 27/Mar/2013 and ending at 31/Oct/2013, both at midnight (you can change the values according to your needs though).
public class CustomTimeZone extends DateTimeZone {
private DateTime dstStart;
private DateTime dstEnd;
protected CustomTimeZone(String id) {
super(id);
// DST starts at 27/Mar/2013 and ends at 31/Oct/2013
this.dstStart = new DateTime(2013, 3, 27, 0, 0, 0, 0, DateTimeZone.UTC);
this.dstEnd = new DateTime(2013, 10, 30, 23, 0, 0, 0, DateTimeZone.UTC);
}
@Override
public String getNameKey(long instant) {
return this.getID();
}
@Override
public int getOffset(long instant) {
// check if it's in DST
if (dstStart.getMillis() <= instant && instant < dstEnd.getMillis()) {
// DST, offset is 1 hour ahead of UTC - value must be in milliseconds
return 3600000;
}
return 0;
}
@Override
public int getStandardOffset(long instant) {
// assuming stardard offset is zero (same as UTC)
return 0;
}
@Override
public boolean isFixed() {
return false;
}
@Override
public long nextTransition(long instant) {
if (instant < dstStart.getMillis()) {
return dstStart.getMillis();
}
if (instant < dstEnd.getMillis()) {
return dstEnd.getMillis();
}
return instant;
}
@Override
public long previousTransition(long instant) {
if (instant > dstEnd.getMillis()) {
return dstEnd.getMillis();
}
if (instant > dstStart.getMillis()) {
return dstStart.getMillis();
}
return instant;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof CustomTimeZone) {
return getID().equals(((CustomTimeZone) obj).getID());
}
return false;
}
}
Testing this zone:
CustomTimeZone customZone = new CustomTimeZone("Custom");
// date in DST (between March and October)
DateTime d = new DateTime(2013, 4, 20, 0, 0, 0, 0, customZone);
System.out.println(d); // 2013-04-20T00:00:00.000+01:00
// one minute before DST starts - offset is zero ("Z")
d = new DateTime(2013, 3, 26, 23, 59, 0, 0, customZone);
System.out.println(d); // 2013-03-26T23:59:00.000Z
// add 1 minute - DST starts and offset changes to +01:00 (clock moves 1 hour forward to 1 AM)
System.out.println(d.plusMinutes(1)); // 2013-03-27T01:00:00.000+01:00
// one minute before DST ends - offset is +01:00
d = new DateTime(1383173940000L, customZone);
System.out.println(d); // 2013-10-30T23:59:00.000+01:00
// add 1 minute - DST starts and offset changes to zero ("Z") (clock moves 1 hour back to 23 PM)
System.out.println(d.plusMinutes(1)); // 2013-10-30T23:00:00.000Z
I've created just a simple case with just one DST transition, but you can make the class as complex as you want, storing all the DST changes you need and adjusting the start and end dates (and the offsets as well) accordingly.