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