/* ******************************************************************************* * Copyright (C) 1996-2010, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ package com.ibm.icu.dev.test.calendar; import java.util.Date; import java.util.Enumeration; import java.util.Hashtable; import java.util.Locale; import com.ibm.icu.dev.test.TestFmwk; import com.ibm.icu.text.DateFormat; import com.ibm.icu.text.SimpleDateFormat; import com.ibm.icu.util.Calendar; import com.ibm.icu.util.ChineseCalendar; import com.ibm.icu.util.GregorianCalendar; import com.ibm.icu.util.SimpleTimeZone; /** * A base class for classes that test individual Calendar subclasses. * Defines various useful utility methods and constants */ public class CalendarTest extends TestFmwk { // Constants for use by subclasses, solely to save typing public final static int SUN = Calendar.SUNDAY; public final static int MON = Calendar.MONDAY; public final static int TUE = Calendar.TUESDAY; public final static int WED = Calendar.WEDNESDAY; public final static int THU = Calendar.THURSDAY; public final static int FRI = Calendar.FRIDAY; public final static int SAT = Calendar.SATURDAY; public final static int ERA = Calendar.ERA; public final static int YEAR = Calendar.YEAR; public final static int MONTH = Calendar.MONTH; public final static int DATE = Calendar.DATE; public final static int HOUR = Calendar.HOUR; public final static int MINUTE = Calendar.MINUTE; public final static int SECOND = Calendar.SECOND; public final static int DOY = Calendar.DAY_OF_YEAR; public final static int WOY = Calendar.WEEK_OF_YEAR; public final static int WOM = Calendar.WEEK_OF_MONTH; public final static int DOW = Calendar.DAY_OF_WEEK; public final static int DOWM = Calendar.DAY_OF_WEEK_IN_MONTH; public final static SimpleTimeZone UTC = new SimpleTimeZone(0, "GMT"); private static final String[] FIELD_NAME = { "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH", "DAY_OF_MONTH", "DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR", "HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET", "DST_OFFSET", "YEAR_WOY", "DOW_LOCAL", "EXTENDED_YEAR", "JULIAN_DAY", "MILLISECONDS_IN_DAY", "IS_LEAP_MONTH" // (ChineseCalendar only) }; public static final String fieldName(int f) { return (f>=0 && f"); } /** * Iterates through a list of calendar TestCase objects and * makes sure that the time-to-fields and fields-to-time calculations work * correnctly for the values in each test case. */ public void doTestCases(TestCase[] cases, Calendar cal) { cal.setTimeZone(UTC); // Get a format to use for printing dates in the calendar system we're testing DateFormat format = DateFormat.getDateTimeInstance(cal, DateFormat.SHORT, -1, Locale.getDefault()); final String pattern = (cal instanceof ChineseCalendar) ? "E MMl/dd/y G HH:mm:ss.S z" : "E, MM/dd/yyyy G HH:mm:ss.S z"; ((SimpleDateFormat)format).applyPattern(pattern); // This format is used for printing Gregorian dates. DateFormat gregFormat = new SimpleDateFormat(pattern); gregFormat.setTimeZone(UTC); GregorianCalendar pureGreg = new GregorianCalendar(UTC); pureGreg.setGregorianChange(new Date(Long.MIN_VALUE)); DateFormat pureGregFmt = new SimpleDateFormat("E M/d/yyyy G"); pureGregFmt.setCalendar(pureGreg); // Now iterate through the test cases and see what happens for (int i = 0; i < cases.length; i++) { logln("\ntest case: " + i); TestCase test = cases[i]; // // First we want to make sure that the millis -> fields calculation works // test.applyTime will call setTime() on the calendar object, and // test.fieldsEqual will retrieve all of the field values and make sure // that they're the same as the ones in the testcase // test.applyTime(cal); if (!test.fieldsEqual(cal, this)) { errln("Fail: (millis=>fields) " + gregFormat.format(test.getTime()) + " => " + format.format(cal.getTime()) + ", expected " + test); } // // If that was OK, check the fields -> millis calculation // test.applyFields will set all of the calendar's fields to // match those in the test case. // cal.clear(); test.applyFields(cal); if (!test.equals(cal)) { errln("Fail: (fields=>millis) " + test + " => " + pureGregFmt.format(cal.getTime()) + ", expected " + pureGregFmt.format(test.getTime())); } } } static public final boolean ROLL = true; static public final boolean ADD = false; /** * Process test cases for add and roll methods. * Each test case is an array of integers, as follows: * * For example: *
     *   //       input                add by          output
     *   //  year  month     day     field amount    year  month     day
     *   {   5759, HESHVAN,   2,     MONTH,   1,     5759, KISLEV,    2 },
     * 
* * @param roll true or ROLL to test the roll method; * false or ADD to test the add0 ? i= mark) { logln("(" + i + " days)"); mark += 5000; // 5 sec } cal.setTimeInMillis(greg.getTimeInMillis()); for (int j=0; j minHigh) { errln("Fail: " + ymdToString(cal) + " Range for min of " + FIELD_NAME[f] + "(" + f + ")=" + minLow + ".." + minHigh + ", actual_min=" + minActual); } if (maxActual < maxLow || maxActual > maxHigh) { errln("Fail: " + ymdToString(cal) + " Range for max of " + FIELD_NAME[f] + "(" + f + ")=" + maxLow + ".." + maxHigh + ", actual_max=" + maxActual); } if (v < minActual || v > maxActual) { errln("Fail: " + ymdToString(cal) + " " + FIELD_NAME[f] + "(" + f + ")=" + v + ", actual range=" + minActual + ".." + maxActual + ", allowed=(" + minLow + ".." + minHigh + ")..(" + maxLow + ".." + maxHigh + ")"); } } greg.add(Calendar.DAY_OF_YEAR, 1); } // Check actual maxima and minima seen against ranges returned // by API. StringBuffer buf = new StringBuffer(); for (int j=0; j expected) { errln("FAIL: Maximum value of DAY_OF_YEAR is too big: " + maxDOY + "/expected: <=" + expected); } expected = lmaxM*lmaxDOM; if (lmaxDOW < expected) { errln("FAIL: Least maximum value of DAY_OF_YEAR is too small: " + lmaxDOW + "/expected: >=" + expected); } } // Week of year expected = maxDOY/nDOW + 1; if (maxWOY > expected) { errln("FAIL: Maximum value of WEEK_OF_YEAR is too big: " + maxWOY + "/expected: <=" + expected); } expected = lmaxDOW/nDOW; if (lmaxWOY < expected) { errln("FAIL: Least maximum value of WEEK_OF_YEAR is too small: " + lmaxWOY + "/expected >=" + expected); } // Day of week in month expected = (maxDOM + nDOW - 1)/nDOW; if (maxDOWIM != expected) { errln("FAIL: Maximum value of DAY_OF_WEEK_IN_MONTH is incorrect: " + maxDOWIM + "/expected: " + expected); } expected = (lmaxDOM + nDOW - 1)/nDOW; if (lmaxDOWIM != expected) { errln("FAIL: Least maximum value of DAY_OF_WEEK_IN_MONTH is incorrect: " + lmaxDOWIM + "/expected: " + expected); } // Week of month expected = (maxDOM + (nDOW - 1) + (nDOW - minDaysInFirstWeek)) / nDOW; if (maxWOM != expected) { errln("FAIL: Maximum value of WEEK_OF_MONTH is incorrect: " + maxWOM + "/expected: " + expected); } expected = (lmaxDOM + (nDOW - minDaysInFirstWeek)) / nDOW; if (lmaxWOM != expected) { errln("FAIL: Least maximum value of WEEK_OF_MONTH is incorrect: " + lmaxWOM + "/expected: " + expected); } } /** * Convert year,month,day values to the form "year/month/day". * On input the month value is zero-based, but in the result string it is one-based. */ static public String ymdToString(int year, int month, int day) { return "" + year + "/" + (month+1) + "/" + day; } /** * Convert year,month,day values to the form "year/month/day". */ static public String ymdToString(Calendar cal) { double day = getJulianDay(cal); if (cal instanceof ChineseCalendar) { return "" + cal.get(Calendar.EXTENDED_YEAR) + "/" + (cal.get(Calendar.MONTH)+1) + (cal.get(Calendar.IS_LEAP_MONTH)==1?"(leap)":"") + "/" + cal.get(Calendar.DATE) + " (" + day + ", time=" + cal.getTimeInMillis() + ")"; } return ymdToString(cal.get(Calendar.EXTENDED_YEAR), cal.get(MONTH), cal.get(DATE)) + " (" + day + ", time=" + cal.getTimeInMillis() + ")"; } static double getJulianDay(Calendar cal) { return (cal.getTime().getTime() - JULIAN_EPOCH) / DAY_MS; } static final double DAY_MS = 24*60*60*1000.0; static final long JULIAN_EPOCH = -210866760000000L; // 1/1/4713 BC 12:00 }