1.1 --- a/src/net/fortuna/ical4j/model/TimeZone.java Tue Feb 10 19:25:00 2015 +0100 1.2 +++ b/src/net/fortuna/ical4j/model/TimeZone.java Tue Feb 10 19:38:00 2015 +0100 1.3 @@ -72,16 +72,27 @@ 1.4 /** 1.5 * {@inheritDoc} 1.6 */ 1.7 - public final int getOffset(final int era, final int year, final int month, final int day, 1.8 + public final int getOffset(final int era, final int year, final int month, final int dayOfMonth, 1.9 final int dayOfWeek, final int milliseconds) { 1.10 + 1.11 + // calculate time of day 1.12 + int ms = milliseconds; 1.13 + final int hour = ms / 3600000; 1.14 + ms -= hour*3600000; 1.15 + final int minute = ms / 60000; 1.16 + ms -= minute*60000; 1.17 + final int second = ms / 1000; 1.18 + ms -= second*1000; 1.19 + 1.20 + final Calendar cal = Calendar.getInstance(); 1.21 + cal.clear(); // don't retain current date/time, it may disturb the calculation 1.22 1.23 - final Calendar cal = Calendar.getInstance(); 1.24 + // set date and time 1.25 cal.set(Calendar.ERA, era); 1.26 - cal.set(Calendar.YEAR, year); 1.27 - cal.set(Calendar.MONTH, month); 1.28 - cal.set(Calendar.DAY_OF_YEAR, day); 1.29 cal.set(Calendar.DAY_OF_WEEK, dayOfWeek); 1.30 - cal.set(Calendar.MILLISECOND, milliseconds); 1.31 + cal.set(year, month, dayOfMonth, hour, minute, second); 1.32 + cal.set(Calendar.MILLISECOND, ms); 1.33 + 1.34 final Observance observance = vTimeZone.getApplicableObservance(new DateTime(cal.getTime())); 1.35 if (observance != null) { 1.36 final TzOffsetTo offset = (TzOffsetTo) observance.getProperty(Property.TZOFFSETTO); 1.37 @@ -97,7 +108,12 @@ 1.38 final Observance observance = vTimeZone.getApplicableObservance(new DateTime(date)); 1.39 if (observance != null) { 1.40 final TzOffsetTo offset = (TzOffsetTo) observance.getProperty(Property.TZOFFSETTO); 1.41 - return (int) offset.getOffset().getOffset(); 1.42 + if (offset.getOffset().getOffset() < getRawOffset()) { 1.43 + return getRawOffset(); 1.44 + } 1.45 + else { 1.46 + return (int) offset.getOffset().getOffset(); 1.47 + } 1.48 } 1.49 return 0; 1.50 } 1.51 @@ -145,26 +161,34 @@ 1.52 } 1.53 1.54 private static final int getRawOffset(VTimeZone vt) { 1.55 - // per spec, rawoffset is the raw offset at the current date 1.56 - final DateTime now = new DateTime(); 1.57 1.58 List seasonalTimes = vt.getObservances().getComponents(Observance.STANDARD); 1.59 // if no standard time use daylight time.. 1.60 - if (seasonalTimes.size() == 0) { 1.61 + if (seasonalTimes.isEmpty()) { 1.62 seasonalTimes = vt.getObservances().getComponents(Observance.DAYLIGHT); 1.63 + if (seasonalTimes.isEmpty()) { 1.64 + return 0; 1.65 + } 1.66 } 1.67 Observance latestSeasonalTime = null; 1.68 - Date latestOnset = null; 1.69 - for (int i = 0; i < seasonalTimes.size(); i++) { 1.70 - Observance seasonalTime = (Observance) seasonalTimes.get(i); 1.71 - Date onset = seasonalTime.getLatestOnset(now); 1.72 - if (onset == null) { 1.73 - continue; 1.74 + if (seasonalTimes.size() > 1) { 1.75 + // per java spec and when dealing with historical time, 1.76 + // rawoffset is the raw offset at the current date 1.77 + final DateTime now = new DateTime(); 1.78 + Date latestOnset = null; 1.79 + for (int i = 0; i < seasonalTimes.size(); i++) { 1.80 + Observance seasonalTime = (Observance) seasonalTimes.get(i); 1.81 + Date onset = seasonalTime.getLatestOnset(now); 1.82 + if (onset == null) { 1.83 + continue; 1.84 + } 1.85 + if (latestOnset == null || onset.after(latestOnset)) { 1.86 + latestOnset = onset; 1.87 + latestSeasonalTime = seasonalTime; 1.88 + } 1.89 } 1.90 - if (latestOnset == null || onset.after(latestOnset)) { 1.91 - latestOnset = onset; 1.92 - latestSeasonalTime = seasonalTime; 1.93 - } 1.94 + } else { 1.95 + latestSeasonalTime = (Observance)seasonalTimes.get(0); 1.96 } 1.97 if (latestSeasonalTime != null) { 1.98 final TzOffsetTo offsetTo = (TzOffsetTo) latestSeasonalTime.getProperty(Property.TZOFFSETTO); 1.99 @@ -174,4 +198,22 @@ 1.100 } 1.101 return 0; 1.102 } 1.103 + 1.104 + public boolean equals(Object o) { 1.105 + if (this == o) return true; 1.106 + if (o == null || getClass() != o.getClass()) return false; 1.107 + 1.108 + TimeZone timeZone = (TimeZone) o; 1.109 + 1.110 + if (rawOffset != timeZone.rawOffset) return false; 1.111 + if (vTimeZone != null ? !vTimeZone.equals(timeZone.vTimeZone) : timeZone.vTimeZone != null) return false; 1.112 + 1.113 + return true; 1.114 + } 1.115 + 1.116 + public int hashCode() { 1.117 + int result = vTimeZone != null ? vTimeZone.hashCode() : 0; 1.118 + result = 31 * result + rawOffset; 1.119 + return result; 1.120 + } 1.121 }