I need to compare time zones such that Asia/Singapore
< UTC
< Pacific/Honolulu
.
I'm working with java.util.TimeZone
(which doesn't implement Comparable
).
My search for an existing implementation was unsuccessful because of the overwhelming number of questions about comparing dates with different time zones.
Question: What is a correct implementation of Comparator<TimeZone>
that will solve this problem (and what makes it better than other solutions, if applicable)?
Note that I'm not able to use Joda Time for this problem, so "use Joda Time" is not a valid answer.
The <
notation above was not well defined. My particular use case only requires a naive "geographical" ordering from east to west. As the comments have pointed out, a more advanced and generalizable solution would take into account temporal factors like daylight savings time and historical GMT offset changes. So I think there are two orderings we can consider, each requiring a different Comparator<TimeZone>
implementation:
I rolled my own Comparator<TimeZone>
implementation using getRawOffset
for the comparison:
@Override
public int compare(TimeZone tz1, TimeZone tz2) {
return tz2.getRawOffset() - tz1.getRawOffset();
}
It seems to have passed a quick test:
final List<TimeZone> timeZones = Arrays.asList(
TimeZone.getTimeZone("UTC"),
TimeZone.getTimeZone("America/Los_Angeles"),
TimeZone.getTimeZone("America/New_York"),
TimeZone.getTimeZone("Pacific/Honolulu"),
TimeZone.getTimeZone("Asia/Singapore")
);
final List<TimeZone> expectedOrder = Arrays.asList(
TimeZone.getTimeZone("Asia/Singapore"),
TimeZone.getTimeZone("UTC"),
TimeZone.getTimeZone("America/New_York"),
TimeZone.getTimeZone("America/Los_Angeles"),
TimeZone.getTimeZone("Pacific/Honolulu")
);
Collections.sort(timeZones, new Comparator<TimeZone>() {
@Override
public int compare(TimeZone tz1, TimeZone tz2) {
return tz2.getRawOffset() - tz1.getRawOffset();
}
});
//Impl note: see AbstractList.equals
System.out.println(timeZones.equals(expectedOrder)); //true
But I'm still wondering whether there are pitfalls to this solution and/or if there's something preferable.
One might be able to create a Comparator<TimeZone>
that takes into account time zone differences. The TimeZone
may or may not obvserve daylight savings time, which would adjust the raw offset, thus messing up raw-offset-only comparisons. The TimeZone
class seems to support the adjustment based on the 2 getOffset
methods, but they need a reference date. How about:
public class TimeZoneComparator implements Comparator<TimeZone>
{
private long date;
public TimeZoneComparator(long date)
{
this.date = date;
}
public int compare(TimeZone tz1, TimeZone tz2)
{
return tz2.getOffset(this.date) - tz2.getOffset(this.date);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With