diff -r dee028db6e9b -r 73bdfa70b04e src/net/fortuna/ical4j/model/TimeZone.java --- a/src/net/fortuna/ical4j/model/TimeZone.java Tue Feb 10 19:25:00 2015 +0100 +++ b/src/net/fortuna/ical4j/model/TimeZone.java Tue Feb 10 19:38:00 2015 +0100 @@ -72,16 +72,27 @@ /** * {@inheritDoc} */ - public final int getOffset(final int era, final int year, final int month, final int day, + public final int getOffset(final int era, final int year, final int month, final int dayOfMonth, final int dayOfWeek, final int milliseconds) { + + // calculate time of day + int ms = milliseconds; + final int hour = ms / 3600000; + ms -= hour*3600000; + final int minute = ms / 60000; + ms -= minute*60000; + final int second = ms / 1000; + ms -= second*1000; + + final Calendar cal = Calendar.getInstance(); + cal.clear(); // don't retain current date/time, it may disturb the calculation - final Calendar cal = Calendar.getInstance(); + // set date and time cal.set(Calendar.ERA, era); - cal.set(Calendar.YEAR, year); - cal.set(Calendar.MONTH, month); - cal.set(Calendar.DAY_OF_YEAR, day); cal.set(Calendar.DAY_OF_WEEK, dayOfWeek); - cal.set(Calendar.MILLISECOND, milliseconds); + cal.set(year, month, dayOfMonth, hour, minute, second); + cal.set(Calendar.MILLISECOND, ms); + final Observance observance = vTimeZone.getApplicableObservance(new DateTime(cal.getTime())); if (observance != null) { final TzOffsetTo offset = (TzOffsetTo) observance.getProperty(Property.TZOFFSETTO); @@ -97,7 +108,12 @@ final Observance observance = vTimeZone.getApplicableObservance(new DateTime(date)); if (observance != null) { final TzOffsetTo offset = (TzOffsetTo) observance.getProperty(Property.TZOFFSETTO); - return (int) offset.getOffset().getOffset(); + if (offset.getOffset().getOffset() < getRawOffset()) { + return getRawOffset(); + } + else { + return (int) offset.getOffset().getOffset(); + } } return 0; } @@ -145,26 +161,34 @@ } private static final int getRawOffset(VTimeZone vt) { - // per spec, rawoffset is the raw offset at the current date - final DateTime now = new DateTime(); List seasonalTimes = vt.getObservances().getComponents(Observance.STANDARD); // if no standard time use daylight time.. - if (seasonalTimes.size() == 0) { + if (seasonalTimes.isEmpty()) { seasonalTimes = vt.getObservances().getComponents(Observance.DAYLIGHT); + if (seasonalTimes.isEmpty()) { + return 0; + } } Observance latestSeasonalTime = null; - Date latestOnset = null; - for (int i = 0; i < seasonalTimes.size(); i++) { - Observance seasonalTime = (Observance) seasonalTimes.get(i); - Date onset = seasonalTime.getLatestOnset(now); - if (onset == null) { - continue; + if (seasonalTimes.size() > 1) { + // per java spec and when dealing with historical time, + // rawoffset is the raw offset at the current date + final DateTime now = new DateTime(); + Date latestOnset = null; + for (int i = 0; i < seasonalTimes.size(); i++) { + Observance seasonalTime = (Observance) seasonalTimes.get(i); + Date onset = seasonalTime.getLatestOnset(now); + if (onset == null) { + continue; + } + if (latestOnset == null || onset.after(latestOnset)) { + latestOnset = onset; + latestSeasonalTime = seasonalTime; + } } - if (latestOnset == null || onset.after(latestOnset)) { - latestOnset = onset; - latestSeasonalTime = seasonalTime; - } + } else { + latestSeasonalTime = (Observance)seasonalTimes.get(0); } if (latestSeasonalTime != null) { final TzOffsetTo offsetTo = (TzOffsetTo) latestSeasonalTime.getProperty(Property.TZOFFSETTO); @@ -174,4 +198,22 @@ } return 0; } + + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + TimeZone timeZone = (TimeZone) o; + + if (rawOffset != timeZone.rawOffset) return false; + if (vTimeZone != null ? !vTimeZone.equals(timeZone.vTimeZone) : timeZone.vTimeZone != null) return false; + + return true; + } + + public int hashCode() { + int result = vTimeZone != null ? vTimeZone.hashCode() : 0; + result = 31 * result + rawOffset; + return result; + } }