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