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