1/*
2 *******************************************************************************
3 * Copyright (C) 1996-2014, International Business Machines Corporation and    *
4 * others. All Rights Reserved.                                                *
5 *******************************************************************************
6 */
7package com.ibm.icu.dev.test.calendar;
8
9import java.util.Date;
10import java.util.Locale;
11
12import com.ibm.icu.dev.test.TestFmwk;
13import com.ibm.icu.impl.LocaleUtility;
14import com.ibm.icu.util.Calendar;
15import com.ibm.icu.util.EasterHoliday;
16import com.ibm.icu.util.GregorianCalendar;
17import com.ibm.icu.util.Holiday;
18import com.ibm.icu.util.RangeDateRule;
19import com.ibm.icu.util.SimpleDateRule;
20import com.ibm.icu.util.SimpleHoliday;
21import com.ibm.icu.util.TimeZone;
22import com.ibm.icu.util.ULocale;
23
24/**
25 * Tests for the <code>Holiday</code> class.
26 */
27public class HolidayTest extends TestFmwk {
28    public static void main(String args[]) throws Exception {
29        new HolidayTest().run(args);
30    }
31    protected void init()throws Exception{
32        if(cal==null){
33            cal = new GregorianCalendar(1, 0, 1);
34            longTimeAgo = cal.getTime();
35            now = new Date();
36        }
37    }
38    static  Calendar cal;
39    static  Date longTimeAgo;
40    static  Date now;
41    static  long awhile = 3600L * 24 * 28; // 28 days
42
43    public void TestAPI() {
44        {
45            // getHolidays
46            Holiday[] holidays = Holiday.getHolidays();
47            exerciseHolidays(holidays, Locale.getDefault());
48        }
49
50        {
51            // getHolidays(Locale)
52            String[] localeNames =
53            {
54                "en_US",
55                "da",
56                "da_DK",
57                "de",
58                "de_AT",
59                "de_DE",
60                "el",
61                "el_GR",
62                "en",
63                "en_CA",
64                "en_GB",
65                "es",
66                "es_MX",
67                "fr",
68                "fr_CA",
69                "fr_FR",
70                "it",
71                "it_IT",
72                "iw",
73                "iw_IL",
74                "ja",
75                "ja_JP",
76            };
77
78            for (int i = 0; i < localeNames.length; ++i) {
79                Locale locale = LocaleUtility.getLocaleFromName(localeNames[i]);
80                Holiday[] holidays = Holiday.getHolidays(locale);
81                exerciseHolidays(holidays, locale);
82            }
83        }
84    }
85
86    void exerciseHolidays(Holiday[] holidays, Locale locale) {
87        for (int i = 0; i < holidays.length; ++i) {
88            exerciseHoliday(holidays[i], locale);
89        }
90    }
91
92    void exerciseHoliday(Holiday h, Locale locale) {
93        logln("holiday: " + h.getDisplayName());
94        logln("holiday in " + locale + ": " + h.getDisplayName(locale));
95
96        Date first = h.firstAfter(longTimeAgo);
97        logln("firstAfter: " + longTimeAgo + " is " + first);
98        if (first == null) {
99            first = longTimeAgo;
100        }
101        first.setTime(first.getTime() + awhile);
102
103        Date second = h.firstBetween(first, now);
104        logln("firstBetween: " + first + " and " + now + " is " + second);
105        if (second == null) {
106            second = now;
107        } else {
108            if(second.after(now)) {
109                errln("Error: "+h.getDisplayName()+".firstBetween("+first+", "+now+")="+second);
110            }
111        }
112
113        logln("is on " + first + ": " + h.isOn(first));
114        logln("is on " + now + ": " + h.isOn(now));
115        logln(
116              "is between "
117              + first
118              + " and "
119              + now
120              + ": "
121              + h.isBetween(first, now));
122        logln(
123              "is between "
124              + first
125              + " and "
126              + second
127              + ": "
128              + h.isBetween(first, second));
129
130        //        logln("rule: " + h.getRule().toString());
131
132        //        h.setRule(h.getRule());
133
134
135        logln("HolidayCalendarDemo test");
136        {
137            final Calendar c = Calendar.getInstance(TimeZone.GMT_ZONE); // Temporary copy
138            c.set(2014, 10, 8); // when this test was hit
139            final Date fStartOfMonth = startOfMonth((Calendar)c.clone());
140
141            // Stash away a few useful constants for this calendar and display
142            //minDay = c.getMinimum(Calendar.DAY_OF_WEEK);
143            //daysInWeek = c.getMaximum(Calendar.DAY_OF_WEEK) - minDay + 1;
144
145            //firstDayOfWeek = Calendar.getInstance(fDisplayLocale).getFirstDayOfWeek();
146
147            // Stash away a Date for the start of this month
148
149            // Find the day of week of the first day in this month
150            c.setTime(fStartOfMonth);
151            //firstDayInMonth = c.get(Calendar.DAY_OF_WEEK);
152
153            // Now find the # of days in the month
154            c.roll(Calendar.DATE, false);
155            // final int daysInMonth = c.get(Calendar.DATE);
156
157            // Finally, find the end of the month, i.e. the start of the next one
158            c.roll(Calendar.DATE, true);
159            c.add(Calendar.MONTH, 1);
160            c.getTime();        // JDK 1.1.2 bug workaround
161            c.add(Calendar.SECOND, -1);
162            Date endOfMonth = c.getTime();
163
164            //
165            // Calculate the number of full or partial weeks in this month.
166            // To do this I can just reuse the code that calculates which
167            // calendar cell contains a given date.
168            //
169            //numWeeks = dateToCell(daysInMonth).y - dateToCell(1).y + 1;
170
171            // Remember which holidays fall on which days in this month,
172            // to save the trouble of having to do it later
173            //fHolidays.setSize(0);
174            int patience=100;
175
176            //for (int h = 0; h < fAllHolidays.length; h++)
177            {
178                Date d = fStartOfMonth;
179                while ( (d = h.firstBetween(d, endOfMonth) ) != null)
180                {
181                    if(--patience <= 0) {
182                        errln("Patience exceeded for " + h.getDisplayName() +" at " + d);
183                        break;
184                    }
185                    if(d.after(endOfMonth)) {
186                        errln("Error: for " + h.getDisplayName()+": " + d +" is after end of month " + endOfMonth);
187                        break;
188                    }
189                    c.setTime(d);
190                    logln("New date: " + d);
191//                    fHolidays.addElement( new HolidayInfo(c.get(Calendar.DATE),
192//                                            fAllHolidays[h],
193//                                            fAllHolidays[h].getDisplayName(fDisplayLocale) ));
194
195                    d.setTime( d.getTime() + 1000 );    // "d++"
196                }
197            }
198//            dirty = false;
199        }
200        // end HolidayDemoApplet code
201
202    }
203
204    // from HolidayCalendarDemo
205    private Date startOfMonth(/*Date dateInMonth,*/ Calendar fCalendar)
206    {
207        //synchronized(fCalendar) {
208        //    fCalendar.setTime(dateInMonth);             // TODO: synchronization
209
210            int era = fCalendar.get(Calendar.ERA);
211            int year = fCalendar.get(Calendar.YEAR);
212            int month = fCalendar.get(Calendar.MONTH);
213
214            fCalendar.clear();
215            fCalendar.set(Calendar.ERA, era);
216            fCalendar.set(Calendar.YEAR, year);
217            fCalendar.set(Calendar.MONTH, month);
218            fCalendar.set(Calendar.DATE, 1);
219
220            return fCalendar.getTime();
221       // }
222    }
223
224    public void TestCoverage(){
225        Holiday[] h = { new EasterHoliday("Ram's Easter"),
226                        new SimpleHoliday(2, 29, 0, "Leap year", 1900, 2100)};
227        exerciseHolidays(h, Locale.getDefault());
228
229        RangeDateRule rdr = new RangeDateRule();
230        rdr.add(new SimpleDateRule(7, 10));
231        Date mbd = getDate(1953, Calendar.JULY, 10);
232        Date dbd = getDate(1958, Calendar.AUGUST, 15);
233        Date nbd = getDate(1990, Calendar.DECEMBER, 17);
234        Date abd = getDate(1992, Calendar.SEPTEMBER, 16);
235        Date xbd = getDate(1976, Calendar.JULY, 4);
236        Date ybd = getDate(2003, Calendar.DECEMBER, 8);
237        rdr.add(new SimpleDateRule(Calendar.JULY, 10, Calendar.MONDAY, false));
238        rdr.add(dbd, new SimpleDateRule(Calendar.AUGUST, 15, Calendar.WEDNESDAY, true));
239        rdr.add(xbd, null);
240        rdr.add(nbd, new SimpleDateRule(Calendar.DECEMBER, 17, Calendar.MONDAY, false));
241        rdr.add(ybd, null);
242
243        logln("first after " + mbd + " is " + rdr.firstAfter(mbd));
244        logln("first between " + mbd + " and " + dbd + " is " + rdr.firstBetween(mbd, dbd));
245        logln("first between " + dbd + " and " + nbd + " is " + rdr.firstBetween(dbd, nbd));
246        logln("first between " + nbd + " and " + abd + " is " + rdr.firstBetween(nbd, abd));
247        logln("first between " + abd + " and " + xbd + " is " + rdr.firstBetween(abd, xbd));
248        logln("first between " + abd + " and " + null + " is " + rdr.firstBetween(abd, null));
249        logln("first between " + xbd + " and " + null + " is " + rdr.firstBetween(xbd, null));
250
251        //getRule, setRule
252        logln("The rule in the holiday: " + h[1].getRule());
253        exerciseHoliday(h[1], Locale.getDefault());
254        h[1].setRule(rdr);
255        logln("Set the new rule to the SimpleHoliday ...");
256        if (!rdr.equals(h[1].getRule())) {
257            errln("FAIL: getRule and setRule not matched.");
258        }
259        exerciseHoliday(h[1], Locale.getDefault());
260    }
261
262    public void TestEaster(){
263        // Verify that Easter is working. Should be April 20, 2014
264        final Holiday h = new EasterHoliday("Easter Sunday");
265        final Date beginApril = getDate(2014, Calendar.APRIL, 1);
266        final Date endApril   = getDate(2014, Calendar.APRIL, 30);
267        final Date expect     = getDate(2014, Calendar.APRIL, 20);
268        final Date actual     = h.firstBetween(beginApril, endApril);
269
270        if(actual == null) {
271            errln("Error: Easter 2014 should be on " + expect + " but got null.");
272        } else {
273            Calendar c = Calendar.getInstance(TimeZone.GMT_ZONE, Locale.US);
274            c.setTime(actual);
275            assertEquals("Easter's year:  ", 2014, c.get(Calendar.YEAR));
276            assertEquals("Easter's month: ", Calendar.APRIL, c.get(Calendar.MONTH));
277            assertEquals("Easter's date:  ", 20, c.get(Calendar.DATE));
278        }
279    }
280
281    public void TestIsOn() {
282        // jb 1901
283        SimpleHoliday sh = new SimpleHoliday(Calendar.AUGUST, 15, "Doug's Day", 1958, 2058);
284
285        Calendar gcal = new GregorianCalendar();
286        gcal.clear();
287        gcal.set(Calendar.YEAR, 2000);
288        gcal.set(Calendar.MONTH, Calendar.AUGUST);
289        gcal.set(Calendar.DAY_OF_MONTH, 15);
290
291        Date d0 = gcal.getTime();
292        gcal.add(Calendar.SECOND, 1);
293        Date d1 = gcal.getTime();
294        gcal.add(Calendar.SECOND, -2);
295        Date d2 = gcal.getTime();
296        gcal.add(Calendar.DAY_OF_MONTH, 1);
297        Date d3 = gcal.getTime();
298        gcal.add(Calendar.SECOND, 1);
299        Date d4 = gcal.getTime();
300        gcal.add(Calendar.SECOND, -2);
301        gcal.set(Calendar.YEAR, 1957);
302        Date d5 = gcal.getTime();
303        gcal.set(Calendar.YEAR, 1958);
304        Date d6 = gcal.getTime();
305        gcal.set(Calendar.YEAR, 2058);
306        Date d7 = gcal.getTime();
307        gcal.set(Calendar.YEAR, 2059);
308        Date d8 = gcal.getTime();
309
310        Date[] dates = { d0, d1, d2, d3, d4, d5, d6, d7, d8 };
311        boolean[] isOns = { true, true, false, true, false, false, true, true, false };
312        for (int i = 0; i < dates.length; ++i) {
313            Date d = dates[i];
314            logln("\ndate: " + d);
315            boolean isOn = sh.isOn(d);
316            logln("isOnDate: " + isOn);
317            if (isOn != isOns[i]) {
318                errln("date: " + d + " should be on Doug's Day!");
319            }
320            Date h = sh.firstAfter(d);
321            logln("firstAfter: " + h);
322        }
323    }
324
325    public void TestDisplayName() {
326        Holiday[] holidays = Holiday.getHolidays(ULocale.US);
327        for (int i = 0; i < holidays.length; ++i) {
328            Holiday h = holidays[i];
329            // only need to test one
330            // if the display names differ, we're using our data.  We know these names
331            // should differ for this holiday (not all will).
332            if ("Christmas".equals(h.getDisplayName(ULocale.US))) {
333                if ("Christmas".equals(h.getDisplayName(ULocale.GERMANY))) {
334                    errln("Using default name for holidays");
335                }
336            }
337        }
338    }
339}
340