]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/classes/core/src/com/ibm/icu/util/AnnualTimeZoneRule.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / classes / core / src / com / ibm / icu / util / AnnualTimeZoneRule.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 2007-2010, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 package com.ibm.icu.util;\r
8 import java.util.Date;\r
9 \r
10 import com.ibm.icu.impl.Grego;\r
11 \r
12 \r
13 /**\r
14  * <code>AnnualTimeZoneRule</code> is a class used for representing a time zone\r
15  * rule which takes effect annually.  Years used in this class are\r
16  * all Gregorian calendar years.\r
17  * \r
18  * @stable ICU 3.8\r
19  */\r
20 public class AnnualTimeZoneRule extends TimeZoneRule {\r
21 \r
22     private static final long serialVersionUID = -8870666707791230688L;\r
23 \r
24     /**\r
25      * The constant representing the maximum year used for designating a rule is permanent.\r
26      * @stable ICU 3.8\r
27      */\r
28     public static final int MAX_YEAR = Integer.MAX_VALUE;\r
29 \r
30     private final DateTimeRule dateTimeRule;\r
31     private final int startYear;\r
32     private final int endYear;\r
33 \r
34     /**\r
35      * Constructs a <code>AnnualTimeZoneRule</code> with the name, the GMT offset of its\r
36      * standard time, the amount of daylight saving offset adjustment,\r
37      * the annual start time rule and the start/until years.\r
38      * \r
39      * @param name          The time zone name.\r
40      * @param rawOffset     The GMT offset of its standard time in milliseconds.\r
41      * @param dstSavings    The amount of daylight saving offset adjustment in\r
42      *                      milliseconds.  If this ia a rule for standard time,\r
43      *                      the value of this argument is 0.\r
44      * @param dateTimeRule  The start date/time rule repeated annually.\r
45      * @param startYear     The first year when this rule takes effect.\r
46      * @param endYear       The last year when this rule takes effect.  If this\r
47      *                      rule is effective forever in future, specify MAX_YEAR.\r
48      * \r
49      * @stable ICU 3.8\r
50      */\r
51     public AnnualTimeZoneRule(String name, int rawOffset, int dstSavings,\r
52             DateTimeRule dateTimeRule, int startYear, int endYear) {\r
53         super(name, rawOffset, dstSavings);\r
54         this.dateTimeRule = dateTimeRule;\r
55         this.startYear = startYear;\r
56         this.endYear = endYear > MAX_YEAR ? MAX_YEAR : endYear;\r
57     }\r
58 \r
59     /**\r
60      * Gets the start date/time rule associated used by this rule.\r
61      * \r
62      * @return  An <code>AnnualDateTimeRule</code> which represents the start date/time\r
63      *          rule used by this time zone rule.\r
64      * \r
65      * @stable ICU 3.8\r
66      */\r
67     public DateTimeRule getRule() {\r
68         return dateTimeRule;\r
69     }\r
70 \r
71     /**\r
72      * Gets the first year when this rule takes effect.\r
73      * \r
74      * @return  The start year of this rule.  The year is in Gregorian calendar\r
75      *          with 0 == 1 BCE, -1 == 2 BCE, etc.\r
76      * \r
77      * @stable ICU 3.8\r
78      */\r
79     public int getStartYear() {\r
80         return startYear;\r
81     }\r
82 \r
83     /**\r
84      * Gets the end year when this rule takes effect.\r
85      * \r
86      * @return  The end year of this rule (inclusive). The year is in Gregorian calendar\r
87      *          with 0 == 1 BCE, -1 == 2 BCE, etc.\r
88      * \r
89      * @stable ICU 3.8\r
90      */\r
91     public int getEndYear() {\r
92         return endYear;\r
93     }\r
94 \r
95     /**\r
96      * Gets the time when this rule takes effect in the given year.\r
97      * \r
98      * @param year              The Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc.\r
99      * @param prevRawOffset     The standard time offset from UTC before this rule\r
100      *                          takes effect in milliseconds.\r
101      * @param prevDSTSavings    The amount of daylight saving offset from the\r
102      *                          standard time.\r
103      * \r
104      * @return  The time when this rule takes effect in the year, or\r
105      *          null if this rule is not applicable in the year.\r
106      * \r
107      * @stable ICU 3.8\r
108      */\r
109     public Date getStartInYear(int year, int prevRawOffset, int prevDSTSavings) {\r
110         if (year < startYear || year > endYear) {\r
111             return null;\r
112         }\r
113 \r
114         long ruleDay;\r
115         int type = dateTimeRule.getDateRuleType();\r
116 \r
117         if (type == DateTimeRule.DOM) {\r
118             ruleDay = Grego.fieldsToDay(year, dateTimeRule.getRuleMonth(), dateTimeRule.getRuleDayOfMonth());\r
119         } else {\r
120             boolean after = true;\r
121             if (type == DateTimeRule.DOW) {\r
122                 int weeks = dateTimeRule.getRuleWeekInMonth();\r
123                 if (weeks > 0) {\r
124                     ruleDay = Grego.fieldsToDay(year, dateTimeRule.getRuleMonth(), 1);\r
125                     ruleDay += 7 * (weeks - 1);\r
126                 } else {\r
127                     after = false;\r
128                     ruleDay = Grego.fieldsToDay(year, dateTimeRule.getRuleMonth(), \r
129                             Grego.monthLength(year, dateTimeRule.getRuleMonth()));\r
130                     ruleDay += 7 * (weeks + 1);\r
131                 }\r
132             } else {\r
133                 int month = dateTimeRule.getRuleMonth();\r
134                 int dom = dateTimeRule.getRuleDayOfMonth();\r
135                 if (type == DateTimeRule.DOW_LEQ_DOM) {\r
136                     after = false;\r
137                     // Handle Feb <=29\r
138                     if (month == Calendar.FEBRUARY && dom == 29 && !Grego.isLeapYear(year)) {\r
139                         dom--;\r
140                     }\r
141                 }\r
142                 ruleDay = Grego.fieldsToDay(year, month, dom);\r
143             }\r
144 \r
145             int dow = Grego.dayOfWeek(ruleDay);\r
146             int delta = dateTimeRule.getRuleDayOfWeek() - dow;\r
147             if (after) {\r
148                 delta = delta < 0 ? delta + 7 : delta;\r
149             } else {\r
150                 delta = delta > 0 ? delta - 7 : delta;\r
151             }\r
152             ruleDay += delta;\r
153         }\r
154 \r
155         long ruleTime = ruleDay * Grego.MILLIS_PER_DAY + dateTimeRule.getRuleMillisInDay();\r
156         if (dateTimeRule.getTimeRuleType() != DateTimeRule.UTC_TIME) {\r
157             ruleTime -= prevRawOffset;\r
158         }\r
159         if (dateTimeRule.getTimeRuleType() == DateTimeRule.WALL_TIME) {\r
160             ruleTime -= prevDSTSavings;\r
161         }\r
162         return new Date(ruleTime);\r
163     }\r
164 \r
165     /**\r
166      * {@inheritDoc}\r
167      * @stable ICU 3.8\r
168      */\r
169     public Date getFirstStart(int prevRawOffset, int prevDSTSavings) {\r
170         return getStartInYear(startYear, prevRawOffset, prevDSTSavings);\r
171     }\r
172 \r
173     /**\r
174      * {@inheritDoc}\r
175      * @stable ICU 3.8\r
176      */\r
177     public Date getFinalStart(int prevRawOffset, int prevDSTSavings) {\r
178         if (endYear == MAX_YEAR) {\r
179             return null;\r
180         }\r
181         return getStartInYear(endYear, prevRawOffset, prevDSTSavings);\r
182     }\r
183 \r
184     /**\r
185      * {@inheritDoc}\r
186      * @stable ICU 3.8\r
187      */\r
188     public Date getNextStart(long base, int prevRawOffset, int prevDSTSavings, boolean inclusive) {\r
189         int[] fields = Grego.timeToFields(base, null);\r
190         int year = fields[0];\r
191         if (year < startYear) {\r
192             return getFirstStart(prevRawOffset, prevDSTSavings);\r
193         }\r
194         Date d = getStartInYear(year, prevRawOffset, prevDSTSavings);\r
195         if (d != null && (d.getTime() < base || (!inclusive && (d.getTime() == base)))) {\r
196             d = getStartInYear(year + 1, prevRawOffset, prevDSTSavings);\r
197         }\r
198         return d;\r
199     }\r
200 \r
201     /**\r
202      * {@inheritDoc}\r
203      * @stable ICU 3.8\r
204      */\r
205     public Date getPreviousStart(long base, int prevRawOffset, int prevDSTSavings, boolean inclusive) {\r
206         int[] fields = Grego.timeToFields(base, null);\r
207         int year = fields[0];\r
208         if (year > endYear) {\r
209             return getFinalStart(prevRawOffset, prevDSTSavings);\r
210         }\r
211         Date d = getStartInYear(year, prevRawOffset, prevDSTSavings);\r
212         if (d != null && (d.getTime() > base || (!inclusive && (d.getTime() == base)))) {\r
213             d = getStartInYear(year - 1, prevRawOffset, prevDSTSavings);\r
214         }\r
215         return d;\r
216     }\r
217 \r
218     /**\r
219      * {@inheritDoc}\r
220      * @stable ICU 3.8\r
221      */\r
222     public boolean isEquivalentTo(TimeZoneRule other) {\r
223         if (!(other instanceof AnnualTimeZoneRule)) {\r
224             return false;\r
225         }\r
226         AnnualTimeZoneRule otherRule = (AnnualTimeZoneRule)other;\r
227         if (startYear == otherRule.startYear\r
228                 && endYear == otherRule.endYear\r
229                 && dateTimeRule.equals(otherRule.dateTimeRule)) {\r
230             return super.isEquivalentTo(other);\r
231         }\r
232         return false;\r
233     }\r
234 \r
235     /**\r
236      * {@inheritDoc}<br><br>\r
237      * Note: This method in <code>AnnualTimeZoneRule</code> always returns true.\r
238      * @stable ICU 3.8\r
239      */\r
240     public boolean isTransitionRule() {\r
241         return true;\r
242     }\r
243 \r
244     /**\r
245      * Returns a <code>String</code> representation of this <code>AnnualTimeZoneRule</code> object.\r
246      * This method is used for debugging purpose only.  The string representation can be changed\r
247      * in future version of ICU without any notice.\r
248      * \r
249      * @stable ICU 3.8\r
250      */\r
251     public String toString() {\r
252         StringBuilder buf = new StringBuilder();\r
253         buf.append(super.toString());\r
254         buf.append(", rule={" + dateTimeRule + "}");\r
255         buf.append(", startYear=" + startYear);\r
256         buf.append(", endYear=");\r
257         if (endYear == MAX_YEAR) {\r
258             buf.append("max");\r
259         } else {\r
260             buf.append(endYear);\r
261         }\r
262         return buf.toString();\r
263     }\r
264 }\r