1/* 2 ******************************************************************************* 3 * Copyright (C) 2005-2010, 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.impl.LocaleUtility; 13import com.ibm.icu.text.DateFormat; 14import com.ibm.icu.text.SimpleDateFormat; 15import com.ibm.icu.util.Calendar; 16import com.ibm.icu.util.CopticCalendar; 17import com.ibm.icu.util.EthiopicCalendar; 18import com.ibm.icu.util.GregorianCalendar; 19import com.ibm.icu.util.TimeZone; 20import com.ibm.icu.util.ULocale; 21 22/** 23 * Tests for the <code>CopticCalendar</code> class. 24 */ 25public class CopticTest extends CalendarTest 26{ 27 public static void main(String args[]) throws Exception { 28 new CopticTest().run(args); 29 } 30 31 /** Constants to save typing. */ 32 public static final int TOUT = CopticCalendar.TOUT; 33 public static final int BABA = CopticCalendar.BABA; 34 public static final int HATOR = CopticCalendar.HATOR; 35 public static final int KIAHK = CopticCalendar.KIAHK; 36 public static final int TOBA = CopticCalendar.TOBA; 37 public static final int AMSHIR = CopticCalendar.AMSHIR; 38 public static final int BARAMHAT = CopticCalendar.BARAMHAT; 39 public static final int BARAMOUDA = CopticCalendar.BARAMOUDA; 40 public static final int BASHANS = CopticCalendar.BASHANS; 41 public static final int PAONA = CopticCalendar.PAONA; 42 public static final int EPEP = CopticCalendar.EPEP; 43 public static final int MESRA = CopticCalendar.MESRA; 44 public static final int NASIE = CopticCalendar.NASIE; 45 46 /* Test dates from: 47 * "The Amharic Letters of Emperor Theodore of Ethiopia to Queen Victoria and 48 * Her Special Envoy", David Appleyard, Girma Selasse Asfaw, Oxford University Press, 49 * June 1 1979, ISBN: 0856726605, Longwood Pr Ltd 50 * 51 * Coptic Gregorian JD 52 * 20/02/1579 29/10/1862 2401443 53 * 29/10/1581 05/07/1865 2402423 54 * 22/05/1582 29/01/1866 2402631 55 * 10/08/1582 17/04/1866 2402709 56 * 28/04/1583 05/01/1867 2402972 57 * 05/05/1584 13/01/1868 2403345 58 * 59 * -------------------------------------------------- 60 * 61 * From the Calendrica applet: http://emr.cs.iit.edu/home/reingold/calendar-book/Calendrica.html 62 * 63 * Coptic Gregorian JD 64 * 07/05/-284 01/01/0000 1721060 65 * 08/05/-283 01/01/0001 1721426 66 * 06/13/-1 29/08/0283 1824664 67 * 68 * 01/01/0000 30/08/0283 1824665 69 * 01/01/0001 29/08/0284 1825030 70 * 01/01/0002 29/08/0285 1825395 71 * 01/01/0003 29/08/0286 1825760 72 * 01/01/0004 30/08/0287 1826126 73 * 05/13/0000 28/08/0284 1825029 74 * 05/13/0001 28/08/0285 1825394 75 * 05/13/0002 28/08/0286 1825759 76 * 05/13/0003 28/08/0287 1826124 77 * 06/13/0003 29/08/0287 1826125 first coptic leap year 78 * 05/13/0004 28/08/0288 1826490 79 * 80 * 06/02/1299 13/10/1582 2299159 81 * 07/02/1299 14/10/1582 2299160 Julian 04/10/1582 82 * 08/02/1299 15/10/1582 2299161 83 * 09/02/1299 16/10/1582 2299162 84 * 85 * 23/04/1616 01/01/1900 2415021 86 * 23/04/1721 01/01/2005 2453372 87 * 05/13/2000 12/09/2284 2555529 88 */ 89 90 91 /** A huge list of test cases to make sure that computeTime and computeFields 92 * work properly for a wide range of data in the civil calendar. 93 */ 94 public void TestCases() 95 { 96 final TestCase[] tests = { 97 // 98 // The months in this table are 1-based rather than 0-based, 99 // because it's easier to edit that way. 100 // Coptic 101 // Julian Day Era Year Month Day WkDay Hour Min Sec 102 // 103 // Dates from "Emporer Theodore..." 104 105 new TestCase(2401442.5, 1, 1579, 2, 20, WED, 0, 0, 0), // Gregorian: 20/10/1862 106 new TestCase(2402422.5, 1, 1581, 10, 29, WED, 0, 0, 0), // Gregorian: 05/07/1865 107 new TestCase(2402630.5, 1, 1582, 5, 22, MON, 0, 0, 0), // Gregorian: 29/01/1866 108 new TestCase(2402708.5, 1, 1582, 8, 10, TUE, 0, 0, 0), // Gregorian: 17/04/1866 109 new TestCase(2402971.5, 1, 1583, 4, 28, SAT, 0, 0, 0), // Gregorian: 05/01/1867 110 new TestCase(2403344.5, 1, 1584, 5, 5, MON, 0, 0, 0), // Gregorian: 13/01/1868 111 new TestCase(1721059.5, 0, 285, 5, 7, SAT, 0, 0, 0), // Gregorian: 01/01/0000 112 new TestCase(1721425.5, 0, 284, 5, 8, MON, 0, 0, 0), // Gregorian: 01/01/0001 113 new TestCase(1824663.5, 0, 2, 13, 6, WED, 0, 0, 0), // Gregorian: 29/08/0283 114 new TestCase(1824664.5, 0, 1, 1, 1, THU, 0, 0, 0), // Gregorian: 30/08/0283 115 new TestCase(1825029.5, 1, 1, 1, 1, FRI, 0, 0, 0), // Gregorian: 29/08/0284 116 new TestCase(1825394.5, 1, 2, 1, 1, SAT, 0, 0, 0), // Gregorian: 29/08/0285 117 new TestCase(1825759.5, 1, 3, 1, 1, SUN, 0, 0, 0), // Gregorian: 29/08/0286 118 new TestCase(1826125.5, 1, 4, 1, 1, TUE, 0, 0, 0), // Gregorian: 30/08/0287 119 new TestCase(1825028.5, 0, 1, 13, 5, THU, 0, 0, 0), // Gregorian: 28/08/0284 120 new TestCase(1825393.5, 1, 1, 13, 5, FRI, 0, 0, 0), // Gregorian: 28/08/0285 121 new TestCase(1825758.5, 1, 2, 13, 5, SAT, 0, 0, 0), // Gregorian: 28/08/0286 122 new TestCase(1826123.5, 1, 3, 13, 5, SUN, 0, 0, 0), // Gregorian: 28/08/0287 123 new TestCase(1826124.5, 1, 3, 13, 6, MON, 0, 0, 0), // Gregorian: 29/08/0287 124 // above is first coptic leap year 125 new TestCase(1826489.5, 1, 4, 13, 5, TUE, 0, 0, 0), // Gregorian: 28/08/0288 126 new TestCase(2299158.5, 1, 1299, 2, 6, WED, 0, 0, 0), // Gregorian: 13/10/1582 127 new TestCase(2299159.5, 1, 1299, 2, 7, THU, 0, 0, 0), // Gregorian: 14/10/1582 128 129 new TestCase(2299160.5, 1, 1299, 2, 8, FRI, 0, 0, 0), // Gregorian: 15/10/1582 130 new TestCase(2299161.5, 1, 1299, 2, 9, SAT, 0, 0, 0), // Gregorian: 16/10/1582 131 132 new TestCase(2415020.5, 1, 1616, 4, 23, MON, 0, 0, 0), // Gregorian: 01/01/1900 133 new TestCase(2453371.5, 1, 1721, 4, 23, SAT, 0, 0, 0), // Gregorian: 01/01/2005 134 new TestCase(2555528.5, 1, 2000, 13, 5, FRI, 0, 0, 0), // Gregorian: 12/09/2284 135 }; 136 137 CopticCalendar testCalendar = new CopticCalendar(); 138 testCalendar.setLenient(true); 139 doTestCases(tests, testCalendar); 140 } 141 142 // basic sanity check that the conversion algorithm round-trips 143 public void TestCopticToJD() { 144 CopticCalendar cal = new CopticCalendar(); 145 cal.clear(); 146 for (int y = -2; y < 3; ++y) { 147 for (int m = 0; m < 12; ++m) { // don't understand rules for 13th month 148 for (int d = 1; d < 25; d += 3) { // play it safe on days per month 149 int jd = CopticCalendar.copticToJD(y, m, d); 150 cal.set(Calendar.JULIAN_DAY, jd); 151 int eyear = cal.get(Calendar.EXTENDED_YEAR); 152 int month = cal.get(Calendar.MONTH); 153 int day = cal.get(Calendar.DAY_OF_MONTH); 154 if (!(y == eyear && 155 m == month && 156 d == day)) { 157 errln("y: " + y + 158 " m: " + m + 159 " d: " + d + 160 " --> jd: " + jd + 161 " --> y: " + eyear + 162 " m: " + month + 163 " d: " + day); 164 } 165 } 166 } 167 } 168 } 169 170 // basic check to see that we print out eras ok 171 // eventually should modify to use locale strings and formatter appropriate to coptic calendar 172 public void TestEraStart() { 173 SimpleDateFormat fmt = new SimpleDateFormat("EEE MMM dd, yyyy GG"); 174 SimpleDateFormat copticFmt = new SimpleDateFormat("EEE MMM dd, yyyy GG"); 175 copticFmt.setCalendar(new CopticCalendar()); 176 177 CopticCalendar cal = new CopticCalendar(1, 0, 1); 178 assertEquals("Coptic Date", "Fri Jan 01, 0001 AD", copticFmt.format(cal)); 179 assertEquals("Gregorian Date", "Fri Aug 29, 0284 AD", fmt.format(cal.getTime())); 180 181 cal.set(Calendar.ERA, 0); 182 cal.set(Calendar.YEAR, 1); 183 assertEquals("Coptic Date", "Thu Jan 01, 0001 BC", copticFmt.format(cal)); 184 assertEquals("Gregorian Date", "Thu Aug 30, 0283 AD", fmt.format(cal.getTime())); 185 } 186 187 public void TestBasic() { 188 CopticCalendar cal = new CopticCalendar(); 189 cal.clear(); 190 cal.set(1000, 0, 30); 191 logln("1000/0/30-> " + 192 cal.get(YEAR) + "/" + 193 cal.get(MONTH) + "/" + 194 cal.get(DATE)); 195 cal.clear(); 196 cal.set(1, 0, 30); 197 logln("1/0/30 -> " + 198 cal.get(YEAR) + "/" + 199 cal.get(MONTH) + "/" + 200 cal.get(DATE)); 201 } 202 203 /** 204 * Test limits of the Coptic calendar 205 */ 206 public void TestLimits() { 207 Calendar cal = Calendar.getInstance(); 208 cal.set(2007, Calendar.JANUARY, 1); 209 CopticCalendar coptic = new CopticCalendar(); 210 doLimitsTest(coptic, null, cal.getTime()); 211 doTheoreticalLimitsTest(coptic, true); 212 } 213 214 /** 215 * Test for track ticket 6379 - proper reporting of 216 * maximum month lengths 217 */ 218 public void Test6379() 219 { 220 CopticCalendar copticCal = new CopticCalendar(); 221 copticCal.clear(); 222 223 for (int year = 1725; year < 1735; year++) { // Coptic 1725-01-01 = Gregorian 2008-09-11 224 boolean isLeap = ((year % 4) == 3); 225 copticCal.set(Calendar.YEAR, year); 226 227 int maxMonth = copticCal.getActualMaximum(Calendar.MONTH); 228 229 for (int month = 0; month <= maxMonth; month++) { 230 copticCal.set(Calendar.MONTH, month); 231 int maxDayOfMonth = copticCal.getActualMaximum(Calendar.DAY_OF_MONTH); 232 233 int expected = (month != maxMonth) ? 30 : (isLeap ? 6 : 5); 234 if (maxDayOfMonth != expected) { 235 errln("FAIL: Expected maximum " + expected + " days for month #" 236 + (month + 1) + " - returned:" + maxDayOfMonth); 237 } 238 } 239 } 240 } 241 242 public void TestCoverage() { 243 244 { 245 // new CopticCalendar(TimeZone) 246 CopticCalendar cal = new CopticCalendar(TimeZone.getDefault()); 247 if(cal == null){ 248 errln("could not create CopticCalendar with TimeZone"); 249 } 250 } 251 252 { 253 // new CopticCalendar(ULocale) 254 CopticCalendar cal = new CopticCalendar(ULocale.getDefault()); 255 if(cal == null){ 256 errln("could not create CopticCalendar with ULocale"); 257 } 258 } 259 260 { 261 // new CopticCalendar(Locale) 262 CopticCalendar cal = new CopticCalendar(Locale.getDefault()); 263 if(cal == null){ 264 errln("could not create CopticCalendar with Locale"); 265 } 266 } 267 268 { 269 // new CopticCalendar(TimeZone, Locale) 270 CopticCalendar cal = new CopticCalendar(TimeZone.getDefault(),Locale.getDefault()); 271 if(cal == null){ 272 errln("could not create CopticCalendar with TimeZone, Locale"); 273 } 274 } 275 276 { 277 // new CopticCalendar(TimeZone, ULocale) 278 CopticCalendar cal = new CopticCalendar(TimeZone.getDefault(),ULocale.getDefault()); 279 if(cal == null){ 280 errln("could not create CopticCalendar with TimeZone, ULocale"); 281 } 282 } 283 284 { 285 // new CopticCalendar(Date) 286 CopticCalendar cal = new CopticCalendar(new Date()); 287 if(cal == null){ 288 errln("could not create CopticCalendar with Date"); 289 } 290 } 291 292 { 293 // new CopticCalendar(int year, int month, int date) 294 CopticCalendar cal = new CopticCalendar(1997, CopticCalendar.TOUT, 1); 295 if(cal == null){ 296 errln("could not create CopticCalendar with year,month,date"); 297 } 298 } 299 300 { 301 // new CopticCalendar(int year, int month, int date, int hour, int minute, int second) 302 CopticCalendar cal = new CopticCalendar(1997, CopticCalendar.TOUT, 1, 1, 1, 1); 303 if(cal == null){ 304 errln("could not create CopticCalendar with year,month,date,hour,minute,second"); 305 } 306 } 307 308 { 309 // data 310 CopticCalendar cal = new CopticCalendar(1997, CopticCalendar.TOUT, 1); 311 Date time = cal.getTime(); 312 313 String[] calendarLocales = { 314 "am_ET", "gez_ET", "ti_ET" 315 }; 316 317 String[] formatLocales = { 318 "en", "am", "am_ET", "gez", "ti" 319 }; 320 for (int i = 0; i < calendarLocales.length; ++i) { 321 String calLocName = calendarLocales[i]; 322 Locale calLocale = LocaleUtility.getLocaleFromName(calLocName); 323 cal = new CopticCalendar(calLocale); 324 325 for (int j = 0; j < formatLocales.length; ++j) { 326 String locName = formatLocales[j]; 327 Locale formatLocale = LocaleUtility.getLocaleFromName(locName); 328 DateFormat format = DateFormat.getDateTimeInstance(cal, DateFormat.FULL, DateFormat.FULL, formatLocale); 329 logln(calLocName + "/" + locName + " --> " + format.format(time)); 330 } 331 } 332 } 333 } 334 335 public void TestYear() { 336 // Gregorian Calendar 337 Calendar gCal= new GregorianCalendar(); 338 Date gToday=gCal.getTime(); 339 gCal.add(GregorianCalendar.MONTH,2); 340 Date gFuture=gCal.getTime(); 341 DateFormat gDF = DateFormat.getDateInstance(gCal,DateFormat.FULL); 342 logln("gregorian calendar: " + gDF.format(gToday) + 343 " + 2 months = " + gDF.format(gFuture)); 344 345 // Coptic Calendar 346 CopticCalendar cCal= new CopticCalendar(); 347 Date cToday=cCal.getTime(); 348 cCal.add(CopticCalendar.MONTH,2); 349 Date cFuture=cCal.getTime(); 350 DateFormat cDF = DateFormat.getDateInstance(cCal,DateFormat.FULL); 351 logln("coptic calendar: " + cDF.format(cToday) + 352 " + 2 months = " + cDF.format(cFuture)); 353 354 // EthiopicCalendar 355 EthiopicCalendar eCal= new EthiopicCalendar(); 356 Date eToday=eCal.getTime(); 357 eCal.add(EthiopicCalendar.MONTH,2); // add 2 months 358 eCal.setAmeteAlemEra(false); 359 Date eFuture=eCal.getTime(); 360 DateFormat eDF = DateFormat.getDateInstance(eCal,DateFormat.FULL); 361 logln("ethiopic calendar: " + eDF.format(eToday) + 362 " + 2 months = " + eDF.format(eFuture)); 363 } 364 365 public void TestAddSet() { 366 class TestAddSetItem { 367 private int startYear; 368 private int startMonth; // 0-based 369 private int startDay; // 1-based 370 private int fieldToChange; 371 private int fieldDelta; 372 private int endYear; 373 private int endMonth; 374 private int endDay; 375 TestAddSetItem(int sYr, int sMo, int sDa, int field, int delta, int eYr, int eMo, int eDa) { 376 startYear = sYr; 377 startMonth = sMo; 378 startDay = sDa; 379 fieldToChange = field; 380 fieldDelta = delta; 381 endYear = eYr; 382 endMonth = eMo; 383 endDay = eDa; 384 } 385 public int getStartYear() { return startYear; } 386 public int getStartMonth() { return startMonth; } 387 public int getStartDay() { return startDay; } 388 public int getField() { return fieldToChange; } 389 public int getDelta() { return fieldDelta; } 390 public int getEndYear() { return endYear; } 391 public int getEndMonth() { return endMonth; } 392 public int getEndDay() { return endDay; } 393 } 394 final TestAddSetItem[] tests = { 395 new TestAddSetItem( 1724, 12, 1, Calendar.MONTH, +1, 1725, 0, 1 ), 396 new TestAddSetItem( 1724, 12, 1, Calendar.MONTH, +9, 1725, 8, 1 ), 397 new TestAddSetItem( 1723, 12, 2, Calendar.MONTH, +1, 1724, 0, 2 ), // 1723 is a leap year 398 new TestAddSetItem( 1723, 12, 2, Calendar.MONTH, +9, 1724, 8, 2 ), 399 new TestAddSetItem( 1725, 0, 1, Calendar.MONTH, -1, 1724, 12, 1 ), 400 new TestAddSetItem( 1725, 0, 1, Calendar.MONTH, -6, 1724, 7, 1 ), 401 new TestAddSetItem( 1724, 12, 1, Calendar.DATE, +8, 1725, 0, 4 ), 402 new TestAddSetItem( 1723, 12, 1, Calendar.DATE, +8, 1724, 0, 3 ), // 1723 is a leap year 403 new TestAddSetItem( 1724, 0, 1, Calendar.DATE, -1, 1723, 12, 6 ), 404 }; 405 CopticCalendar testCalendar = new CopticCalendar(); 406 for ( int i = 0; i < tests.length; i++ ) { 407 TestAddSetItem item = tests[i]; 408 testCalendar.set( item.getStartYear(), item.getStartMonth(), item.getStartDay(), 9, 0 ); 409 testCalendar.add( item.getField(), item.getDelta() ); 410 int endYear = testCalendar.get(Calendar.YEAR); 411 int endMonth = testCalendar.get(Calendar.MONTH); 412 int endDay = testCalendar.get(Calendar.DATE); 413 if ( endYear != item.getEndYear() || endMonth != item.getEndMonth() || endDay != item.getEndDay() ) { 414 errln("CToJD FAILS: field " + item.getField() + " delta " + item.getDelta() + 415 " expected yr " + item.getEndYear() + " mo " + item.getEndMonth() + " da " + item.getEndDay() + 416 " got yr " + endYear + " mo " + endMonth + " da " + endDay); 417 } 418 } 419 } 420} 421