70 } |
70 } |
71 |
71 |
72 /** |
72 /** |
73 * {@inheritDoc} |
73 * {@inheritDoc} |
74 */ |
74 */ |
75 public final int getOffset(final int era, final int year, final int month, final int day, |
75 public final int getOffset(final int era, final int year, final int month, final int dayOfMonth, |
76 final int dayOfWeek, final int milliseconds) { |
76 final int dayOfWeek, final int milliseconds) { |
|
77 |
|
78 // calculate time of day |
|
79 int ms = milliseconds; |
|
80 final int hour = ms / 3600000; |
|
81 ms -= hour*3600000; |
|
82 final int minute = ms / 60000; |
|
83 ms -= minute*60000; |
|
84 final int second = ms / 1000; |
|
85 ms -= second*1000; |
|
86 |
|
87 final Calendar cal = Calendar.getInstance(); |
|
88 cal.clear(); // don't retain current date/time, it may disturb the calculation |
77 |
89 |
78 final Calendar cal = Calendar.getInstance(); |
90 // set date and time |
79 cal.set(Calendar.ERA, era); |
91 cal.set(Calendar.ERA, era); |
80 cal.set(Calendar.YEAR, year); |
|
81 cal.set(Calendar.MONTH, month); |
|
82 cal.set(Calendar.DAY_OF_YEAR, day); |
|
83 cal.set(Calendar.DAY_OF_WEEK, dayOfWeek); |
92 cal.set(Calendar.DAY_OF_WEEK, dayOfWeek); |
84 cal.set(Calendar.MILLISECOND, milliseconds); |
93 cal.set(year, month, dayOfMonth, hour, minute, second); |
|
94 cal.set(Calendar.MILLISECOND, ms); |
|
95 |
85 final Observance observance = vTimeZone.getApplicableObservance(new DateTime(cal.getTime())); |
96 final Observance observance = vTimeZone.getApplicableObservance(new DateTime(cal.getTime())); |
86 if (observance != null) { |
97 if (observance != null) { |
87 final TzOffsetTo offset = (TzOffsetTo) observance.getProperty(Property.TZOFFSETTO); |
98 final TzOffsetTo offset = (TzOffsetTo) observance.getProperty(Property.TZOFFSETTO); |
88 return (int) offset.getOffset().getOffset(); |
99 return (int) offset.getOffset().getOffset(); |
89 } |
100 } |
95 */ |
106 */ |
96 public int getOffset(long date) { |
107 public int getOffset(long date) { |
97 final Observance observance = vTimeZone.getApplicableObservance(new DateTime(date)); |
108 final Observance observance = vTimeZone.getApplicableObservance(new DateTime(date)); |
98 if (observance != null) { |
109 if (observance != null) { |
99 final TzOffsetTo offset = (TzOffsetTo) observance.getProperty(Property.TZOFFSETTO); |
110 final TzOffsetTo offset = (TzOffsetTo) observance.getProperty(Property.TZOFFSETTO); |
100 return (int) offset.getOffset().getOffset(); |
111 if (offset.getOffset().getOffset() < getRawOffset()) { |
|
112 return getRawOffset(); |
|
113 } |
|
114 else { |
|
115 return (int) offset.getOffset().getOffset(); |
|
116 } |
101 } |
117 } |
102 return 0; |
118 return 0; |
103 } |
119 } |
104 |
120 |
105 /** |
121 /** |
143 public final VTimeZone getVTimeZone() { |
159 public final VTimeZone getVTimeZone() { |
144 return vTimeZone; |
160 return vTimeZone; |
145 } |
161 } |
146 |
162 |
147 private static final int getRawOffset(VTimeZone vt) { |
163 private static final int getRawOffset(VTimeZone vt) { |
148 // per spec, rawoffset is the raw offset at the current date |
|
149 final DateTime now = new DateTime(); |
|
150 |
164 |
151 List seasonalTimes = vt.getObservances().getComponents(Observance.STANDARD); |
165 List seasonalTimes = vt.getObservances().getComponents(Observance.STANDARD); |
152 // if no standard time use daylight time.. |
166 // if no standard time use daylight time.. |
153 if (seasonalTimes.size() == 0) { |
167 if (seasonalTimes.isEmpty()) { |
154 seasonalTimes = vt.getObservances().getComponents(Observance.DAYLIGHT); |
168 seasonalTimes = vt.getObservances().getComponents(Observance.DAYLIGHT); |
|
169 if (seasonalTimes.isEmpty()) { |
|
170 return 0; |
|
171 } |
155 } |
172 } |
156 Observance latestSeasonalTime = null; |
173 Observance latestSeasonalTime = null; |
157 Date latestOnset = null; |
174 if (seasonalTimes.size() > 1) { |
158 for (int i = 0; i < seasonalTimes.size(); i++) { |
175 // per java spec and when dealing with historical time, |
159 Observance seasonalTime = (Observance) seasonalTimes.get(i); |
176 // rawoffset is the raw offset at the current date |
160 Date onset = seasonalTime.getLatestOnset(now); |
177 final DateTime now = new DateTime(); |
161 if (onset == null) { |
178 Date latestOnset = null; |
162 continue; |
179 for (int i = 0; i < seasonalTimes.size(); i++) { |
163 } |
180 Observance seasonalTime = (Observance) seasonalTimes.get(i); |
164 if (latestOnset == null || onset.after(latestOnset)) { |
181 Date onset = seasonalTime.getLatestOnset(now); |
165 latestOnset = onset; |
182 if (onset == null) { |
166 latestSeasonalTime = seasonalTime; |
183 continue; |
167 } |
184 } |
|
185 if (latestOnset == null || onset.after(latestOnset)) { |
|
186 latestOnset = onset; |
|
187 latestSeasonalTime = seasonalTime; |
|
188 } |
|
189 } |
|
190 } else { |
|
191 latestSeasonalTime = (Observance)seasonalTimes.get(0); |
168 } |
192 } |
169 if (latestSeasonalTime != null) { |
193 if (latestSeasonalTime != null) { |
170 final TzOffsetTo offsetTo = (TzOffsetTo) latestSeasonalTime.getProperty(Property.TZOFFSETTO); |
194 final TzOffsetTo offsetTo = (TzOffsetTo) latestSeasonalTime.getProperty(Property.TZOFFSETTO); |
171 if (offsetTo != null) { |
195 if (offsetTo != null) { |
172 return (int) offsetTo.getOffset().getOffset(); |
196 return (int) offsetTo.getOffset().getOffset(); |
173 } |
197 } |
174 } |
198 } |
175 return 0; |
199 return 0; |
176 } |
200 } |
|
201 |
|
202 public boolean equals(Object o) { |
|
203 if (this == o) return true; |
|
204 if (o == null || getClass() != o.getClass()) return false; |
|
205 |
|
206 TimeZone timeZone = (TimeZone) o; |
|
207 |
|
208 if (rawOffset != timeZone.rawOffset) return false; |
|
209 if (vTimeZone != null ? !vTimeZone.equals(timeZone.vTimeZone) : timeZone.vTimeZone != null) return false; |
|
210 |
|
211 return true; |
|
212 } |
|
213 |
|
214 public int hashCode() { |
|
215 int result = vTimeZone != null ? vTimeZone.hashCode() : 0; |
|
216 result = 31 * result + rawOffset; |
|
217 return result; |
|
218 } |
177 } |
219 } |