How is it possible in Java to convert an instance of java.util.TimeZone
to org.joda.DateTimeZone
and keeping the daylight saving time?
问题:
回答1:
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.
回答2:
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.