]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/classes/core/src/com/ibm/icu/util/SimpleDateRule.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / classes / core / src / com / ibm / icu / util / SimpleDateRule.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 1996-2010, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 \r
8 package com.ibm.icu.util;\r
9 \r
10 import java.util.Date;\r
11 \r
12 /**\r
13  * <b>Note:</b> The Holiday framework is a technology preview.\r
14  * Despite its age, is still draft API, and clients should treat it as such.\r
15  * \r
16  * Simple implementation of DateRule.\r
17  * @draft ICU 2.8 (retainAll)\r
18  * @provisional This API might change or be removed in a future release.\r
19  */\r
20 public class SimpleDateRule implements DateRule\r
21 {\r
22     /**\r
23      * Construct a rule for a fixed date within a month\r
24      *\r
25      * @param month         The month in which this rule occurs (0-based).\r
26      * @param dayOfMonth    The date in that month (1-based).\r
27      * @draft ICU 2.8\r
28      * @provisional This API might change or be removed in a future release.\r
29      */\r
30     public SimpleDateRule(int month, int dayOfMonth)\r
31     {\r
32         this.month      = month;\r
33         this.dayOfMonth = dayOfMonth;\r
34         this.dayOfWeek  = 0;\r
35     }\r
36 \r
37     // temporary\r
38     /* package */SimpleDateRule(int month, int dayOfMonth, Calendar cal)\r
39     {\r
40         this.month      = month;\r
41         this.dayOfMonth = dayOfMonth;\r
42         this.dayOfWeek  = 0;\r
43         this.calendar   = cal;\r
44     }\r
45 \r
46     /**\r
47      * Construct a rule for a weekday within a month, e.g. the first Monday.\r
48      *\r
49      * @param month         The month in which this rule occurs (0-based).\r
50      * @param dayOfMonth    A date within that month (1-based).\r
51      * @param dayOfWeek     The day of the week on which this rule occurs.\r
52      * @param after         If true, this rule selects the first dayOfWeek\r
53      *                      on or after dayOfMonth.  If false, the rule selects\r
54      *                      the first dayOfWeek on or before dayOfMonth.\r
55      * @draft ICU 2.8\r
56      * @provisional This API might change or be removed in a future release.\r
57      */\r
58     public SimpleDateRule(int month, int dayOfMonth, int dayOfWeek, boolean after)\r
59     {\r
60         this.month      = month;\r
61         this.dayOfMonth = dayOfMonth;\r
62         this.dayOfWeek  = after ? dayOfWeek : -dayOfWeek;\r
63     }\r
64 \r
65     /**\r
66      * Return the first occurrance of the event represented by this rule\r
67      * that is on or after the given start date.\r
68      *\r
69      * @param start Only occurrances on or after this date are returned.\r
70      *\r
71      * @return      The date on which this event occurs, or null if it\r
72      *              does not occur on or after the start date.\r
73      *\r
74      * @see #firstBetween\r
75      * @draft ICU 2.8\r
76      * @provisional This API might change or be removed in a future release.\r
77      */\r
78     public Date firstAfter(Date start)\r
79     {\r
80         return doFirstBetween(start, null);\r
81     }\r
82 \r
83     /**\r
84      * Return the first occurrance of the event represented by this rule\r
85      * that is on or after the given start date and before the given\r
86      * end date.\r
87      *\r
88      * @param start Only occurrances on or after this date are returned.\r
89      * @param end   Only occurrances before this date are returned.\r
90      *\r
91      * @return      The date on which this event occurs, or null if it\r
92      *              does not occur between the start and end dates.\r
93      *\r
94      * @see #firstAfter\r
95      * @draft ICU 2.8\r
96      * @provisional This API might change or be removed in a future release.\r
97      */\r
98     public Date firstBetween(Date start, Date end)\r
99     {\r
100         // Pin to the min/max dates for this rule\r
101         return doFirstBetween(start, end);\r
102     }\r
103 \r
104     /**\r
105      * Checks whether this event occurs on the given date.  This does\r
106      * <em>not</em> take time of day into account; instead it checks\r
107      * whether this event and the given date are on the same day.\r
108      * This is useful for applications such as determining whether a given\r
109      * day is a holiday.\r
110      *\r
111      * @param date  The date to check.\r
112      * @return      true if this event occurs on the given date.\r
113      * @draft ICU 2.8\r
114      * @provisional This API might change or be removed in a future release.\r
115      */\r
116     public boolean isOn(Date date)\r
117     {\r
118         Calendar c = calendar;\r
119 \r
120         synchronized(c) {\r
121             c.setTime(date);\r
122 \r
123             int dayOfYear = c.get(Calendar.DAY_OF_YEAR);\r
124 \r
125             c.setTime(computeInYear(c.get(Calendar.YEAR), c));\r
126 \r
127 //              System.out.println("  isOn: dayOfYear = " + dayOfYear);\r
128 //              System.out.println("        holiday   = " + c.get(Calendar.DAY_OF_YEAR));\r
129 \r
130             return c.get(Calendar.DAY_OF_YEAR) == dayOfYear;\r
131         }\r
132     }\r
133 \r
134     /**\r
135      * Check whether this event occurs at least once between the two\r
136      * dates given.\r
137      * @draft ICU 2.8\r
138      * @provisional This API might change or be removed in a future release.\r
139      */\r
140     public boolean isBetween(Date start, Date end)\r
141     {\r
142         return firstBetween(start, end) != null; // TODO: optimize?\r
143     }\r
144 \r
145     private Date doFirstBetween(Date start, Date end)\r
146     {\r
147         Calendar c = calendar;\r
148 \r
149         synchronized(c) {\r
150             c.setTime(start);\r
151 \r
152             int year = c.get(Calendar.YEAR);\r
153             int mon = c.get(Calendar.MONTH);\r
154 \r
155             // If the rule is earlier in the year than the start date\r
156             // we have to go to the next year.\r
157             if (mon > this.month) {\r
158                 year++;\r
159             }\r
160 \r
161             // Figure out when the rule lands in the given year\r
162             Date result = computeInYear(year, c);\r
163 \r
164             // If the rule is in the same month as the start date, it's possible\r
165             // to get a result that's before the start.  If so, go to next year.\r
166             if (mon == this.month && result.before(start)) {\r
167                 result = computeInYear(year+1, c);\r
168             }\r
169 \r
170             if (end != null && result.after(end)) {\r
171                 return null;\r
172             }\r
173             return result;\r
174         }\r
175     }\r
176 \r
177     private Date computeInYear(int year, Calendar c)\r
178     {\r
179         synchronized(c) {\r
180             c.clear();\r
181             c.set(Calendar.ERA, c.getMaximum(Calendar.ERA));\r
182             c.set(Calendar.YEAR, year);\r
183             c.set(Calendar.MONTH, month);\r
184             c.set(Calendar.DATE, dayOfMonth);\r
185 \r
186             //System.out.println("     computeInYear: start at " + c.getTime().toString());\r
187 \r
188             if (dayOfWeek != 0) {\r
189                 c.setTime(c.getTime());        // JDK 1.1.2 workaround\r
190                 int weekday = c.get(Calendar.DAY_OF_WEEK);\r
191 \r
192                 //System.out.println("                    weekday = " + weekday);\r
193                 //System.out.println("                    dayOfYear = " + c.get(Calendar.DAY_OF_YEAR));\r
194 \r
195                 int delta = 0;\r
196                 if (dayOfWeek > 0) {\r
197                     // We want the first occurrance of the given day of the week\r
198                     // on or after the specified date in the month.\r
199                     delta = (dayOfWeek - weekday + 7) % 7;\r
200                 }\r
201                 else {\r
202                     // We want the first occurrance of the (-dayOfWeek)\r
203                     // on or before the specified date in the month.\r
204                     delta = -((dayOfWeek + weekday + 7) % 7);\r
205                 }\r
206                 //System.out.println("                    adding " + delta + " days");\r
207                 c.add(Calendar.DATE, delta);\r
208             }\r
209 \r
210             return c.getTime();\r
211         }\r
212     }\r
213 \r
214     /**\r
215      * @draft ICU 2.8\r
216      * @provisional This API might change or be removed in a future release.\r
217      */\r
218 //    public void setCalendar(Calendar c) {\r
219 //        calendar = c;\r
220 //    }\r
221 \r
222     private static GregorianCalendar gCalendar = new GregorianCalendar();\r
223 \r
224     private Calendar calendar = gCalendar;\r
225 \r
226     private int     month;\r
227     private int     dayOfMonth;\r
228     private int     dayOfWeek;\r
229 }\r