• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GENERATED SOURCE. DO NOT MODIFY. */
2 // © 2016 and later: Unicode, Inc. and others.
3 // License & terms of use: http://www.unicode.org/copyright.html#License
4 /*
5  *******************************************************************************
6  * Copyright (C) 1996-2014, International Business Machines Corporation and    *
7  * others. All Rights Reserved.                                                *
8  *******************************************************************************
9  */
10 
11 package ohos.global.icu.util;
12 
13 import java.util.Date;
14 
15 /**
16  * <b>Note:</b> The Holiday framework is a technology preview.
17  * Despite its age, is still draft API, and clients should treat it as such.
18  *
19  * A Holiday subclass which represents holidays that occur
20  * a fixed number of days before or after Easter.  Supports both the
21  * Western and Orthodox methods for calculating Easter.
22  * @hide exposed on OHOS
23  * @hide draft / provisional / internal are hidden on OHOS
24  */
25 public class EasterHoliday extends Holiday
26 {
27     /**
28      * Construct a holiday that falls on Easter Sunday every year
29      *
30      * @param name The name of the holiday
31      * @hide draft / provisional / internal are hidden on OHOS
32      */
EasterHoliday(String name)33     public EasterHoliday(String name)
34     {
35         super(name, new EasterRule(0, false));
36     }
37 
38     /**
39      * Construct a holiday that falls a specified number of days before
40      * or after Easter Sunday each year.
41      *
42      * @param daysAfter The number of days before (-) or after (+) Easter
43      * @param name      The name of the holiday
44      * @hide draft / provisional / internal are hidden on OHOS
45      */
EasterHoliday(int daysAfter, String name)46     public EasterHoliday(int daysAfter, String name)
47     {
48         super(name, new EasterRule(daysAfter, false));
49     }
50 
51     /**
52      * Construct a holiday that falls a specified number of days before
53      * or after Easter Sunday each year, using either the Western
54      * or Orthodox calendar.
55      *
56      * @param daysAfter The number of days before (-) or after (+) Easter
57      * @param orthodox  Use the Orthodox calendar?
58      * @param name      The name of the holiday
59      * @hide draft / provisional / internal are hidden on OHOS
60      */
EasterHoliday(int daysAfter, boolean orthodox, String name)61     public EasterHoliday(int daysAfter, boolean orthodox, String name)
62     {
63         super(name, new EasterRule(daysAfter, orthodox));
64     }
65 
66     /**
67      * Shrove Tuesday, aka Mardi Gras, 48 days before Easter
68      * @hide draft / provisional / internal are hidden on OHOS
69      */
70     static public final EasterHoliday SHROVE_TUESDAY  = new EasterHoliday(-48,    "Shrove Tuesday");
71 
72     /**
73      * Ash Wednesday, start of Lent, 47 days before Easter
74      * @hide draft / provisional / internal are hidden on OHOS
75      */
76     static public final EasterHoliday ASH_WEDNESDAY   = new EasterHoliday(-47,    "Ash Wednesday");
77 
78     /**
79      * Palm Sunday, 7 days before Easter
80      * @hide draft / provisional / internal are hidden on OHOS
81      */
82     static public final EasterHoliday PALM_SUNDAY     = new EasterHoliday( -7,    "Palm Sunday");
83 
84     /**
85      * Maundy Thursday, 3 days before Easter
86      * @hide draft / provisional / internal are hidden on OHOS
87      */
88     static public final EasterHoliday MAUNDY_THURSDAY = new EasterHoliday( -3,    "Maundy Thursday");
89 
90     /**
91      * Good Friday, 2 days before Easter
92      * @hide draft / provisional / internal are hidden on OHOS
93      */
94     static public final EasterHoliday GOOD_FRIDAY     = new EasterHoliday( -2,    "Good Friday");
95 
96     /**
97      * Easter Sunday
98      * @hide draft / provisional / internal are hidden on OHOS
99      */
100     static public final EasterHoliday EASTER_SUNDAY   = new EasterHoliday(  0,    "Easter Sunday");
101 
102     /**
103      * Easter Monday, 1 day after Easter
104      * @hide draft / provisional / internal are hidden on OHOS
105      */
106     static public final EasterHoliday EASTER_MONDAY   = new EasterHoliday(  1,    "Easter Monday");
107 
108     /**
109      * Ascension, 39 days after Easter
110      * @hide draft / provisional / internal are hidden on OHOS
111      */
112     static public final EasterHoliday ASCENSION       = new EasterHoliday( 39,    "Ascension");
113 
114     /**
115      * Pentecost (aka Whit Sunday), 49 days after Easter
116      * @hide draft / provisional / internal are hidden on OHOS
117      */
118     static public final EasterHoliday PENTECOST       = new EasterHoliday( 49,    "Pentecost");
119 
120     /**
121      * Whit Sunday (aka Pentecost), 49 days after Easter
122      * @hide draft / provisional / internal are hidden on OHOS
123      */
124     static public final EasterHoliday WHIT_SUNDAY     = new EasterHoliday( 49,    "Whit Sunday");
125 
126     /**
127      * Whit Monday, 50 days after Easter
128      * @hide draft / provisional / internal are hidden on OHOS
129      */
130     static public final EasterHoliday WHIT_MONDAY     = new EasterHoliday( 50,    "Whit Monday");
131 
132     /**
133      * Corpus Christi, 60 days after Easter
134      * @hide draft / provisional / internal are hidden on OHOS
135      */
136     static public final EasterHoliday CORPUS_CHRISTI  = new EasterHoliday( 60,    "Corpus Christi");
137 }
138 
139 class EasterRule implements DateRule {
EasterRule(int daysAfterEaster, boolean isOrthodox)140     public EasterRule(int daysAfterEaster, boolean isOrthodox) {
141         this.daysAfterEaster = daysAfterEaster;
142         if (isOrthodox) {
143             calendar.setGregorianChange(new Date(Long.MAX_VALUE));
144         }
145     }
146 
147     /**
148      * Return the first occurrence of this rule on or after the given date
149      */
150     @Override
firstAfter(Date start)151     public Date firstAfter(Date start)
152     {
153         return doFirstBetween(start, null);
154     }
155 
156     /**
157      * Return the first occurrence of this rule on or after
158      * the given start date and before the given end date.
159      */
160     @Override
firstBetween(Date start, Date end)161     public Date firstBetween(Date start, Date end)
162     {
163         return doFirstBetween(start, end);
164     }
165 
166     /**
167      * Return true if the given Date is on the same day as Easter
168      */
169     @Override
isOn(Date date)170     public boolean isOn(Date date)
171     {
172         synchronized(calendar) {
173             calendar.setTime(date);
174             int dayOfYear = calendar.get(Calendar.DAY_OF_YEAR);
175 
176             calendar.setTime(computeInYear(calendar.getTime(), calendar));
177 
178             return calendar.get(Calendar.DAY_OF_YEAR) == dayOfYear;
179         }
180     }
181 
182     /**
183      * Return true if Easter occurs between the two dates given
184      */
185     @Override
isBetween(Date start, Date end)186     public boolean isBetween(Date start, Date end)
187     {
188         return firstBetween(start, end) != null; // TODO: optimize?
189     }
190 
doFirstBetween(Date start, Date end)191     private Date doFirstBetween(Date start, Date end)
192     {
193         //System.out.println("doFirstBetween: start   = " + start.toString());
194         //System.out.println("doFirstBetween: end     = " + end.toString());
195 
196         synchronized(calendar) {
197             // Figure out when this holiday lands in the given year
198             Date result = computeInYear(start, calendar);
199 
200          //System.out.println("                result  = " + result.toString());
201 
202             // We might have gotten a date that's in the same year as "start", but
203             // earlier in the year.  If so, go to next year
204             if (result.before(start))
205             {
206                 calendar.setTime(start);
207                 calendar.get(Calendar.YEAR);    // JDK 1.1.2 bug workaround
208                 calendar.add(Calendar.YEAR, 1);
209 
210                 //System.out.println("                Result before start, going to next year: "
211                 //                        + calendar.getTime().toString());
212 
213                 result = computeInYear(calendar.getTime(), calendar);
214                 //System.out.println("                result  = " + result.toString());
215             }
216 
217             if (end != null && !result.before(end)) {
218                 //System.out.println("Result after end, returning null");
219                 return null;
220             }
221             return result;
222         }
223     }
224 
225     /**
226      * Compute the month and date on which this holiday falls in the year
227      * containing the date "date".  First figure out which date Easter
228      * lands on in this year, and then add the offset for this holiday to get
229      * the right date.
230      * <p>
231      * The algorithm here is taken from the
232      * <a href="http://www.faqs.org/faqs/calendars/faq/">Calendar FAQ</a>.
233      */
computeInYear(Date date, GregorianCalendar cal)234     private Date computeInYear(Date date, GregorianCalendar cal)
235     {
236         if (cal == null) cal = calendar;
237 
238         synchronized(cal) {
239             cal.setTime(date);
240 
241             int year = cal.get(Calendar.YEAR);
242             int g = year % 19;  // "Golden Number" of year - 1
243             int i = 0;          // # of days from 3/21 to the Paschal full moon
244             int j = 0;          // Weekday (0-based) of Paschal full moon
245 
246             if (cal.getTime().after( cal.getGregorianChange()))
247             {
248                 // We're past the Gregorian switchover, so use the Gregorian rules.
249                 int c = year / 100;
250                 int h = (c - c/4 - (8*c+13)/25 + 19*g + 15) % 30;
251                 i = h - (h/28)*(1 - (h/28)*(29/(h+1))*((21-g)/11));
252                 j = (year + year/4 + i + 2 - c + c/4) % 7;
253             }
254             else
255             {
256                 // Use the old Julian rules.
257                 i = (19*g + 15) % 30;
258                 j = (year + year/4 + i) % 7;
259             }
260             int l = i - j;
261             int m = 3 + (l+40)/44;              // 1-based month in which Easter falls
262             int d = l + 28 - 31*(m/4);          // Date of Easter within that month
263 
264             cal.clear();
265             cal.set(Calendar.ERA, GregorianCalendar.AD);
266             cal.set(Calendar.YEAR, year);
267             cal.set(Calendar.MONTH, m-1);       // 0-based
268             cal.set(Calendar.DATE, d);
269             cal.getTime();                      // JDK 1.1.2 bug workaround
270             cal.add(Calendar.DATE, daysAfterEaster);
271 
272             return cal.getTime();
273         }
274     }
275 
276     private int               daysAfterEaster;
277     private GregorianCalendar calendar = new GregorianCalendar();
278 }
279