home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / test / intltest / tzregts.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-19  |  29.7 KB  |  837 lines

  1. /*
  2. ********************************************************************
  3. * COPYRIGHT: 
  4. * (C) Copyright int32_ternational Business Machines Corporation, 1998
  5. * Licensed Material - Program-Property of IBM - All Rights Reserved. 
  6. * US Government Users Restricted Rights - Use, duplication, or disclosure 
  7. * restricted by GSA ADP Schedule Contract with IBM Corp. 
  8. *
  9. ********************************************************************
  10. */
  11.  
  12. #include "tzregts.h"
  13.  
  14. #include "calregts.h"
  15.  
  16. #include "simpletz.h"
  17. #include "smpdtfmt.h"
  18.  
  19. #include <limits.h>
  20.  
  21. // *****************************************************************************
  22. // class TimeZoneRegressionTest
  23. // *****************************************************************************
  24.  
  25. #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break;
  26.  
  27. void 
  28. TimeZoneRegressionTest::runIndexedTest( int32_t index, bool_t exec, char* &name, char* par )
  29. {
  30.     // if (exec) logln((UnicodeString)"TestSuite NumberFormatRegressionTest");
  31.     switch (index) {
  32.  
  33.         CASE(0, Test4052967)
  34.         CASE(1, Test4073209)
  35.         CASE(2, Test4073215)
  36.         CASE(3, Test4084933)
  37.         CASE(4, Test4096952)
  38.         CASE(5, Test4109314)
  39.         CASE(6, Test4126678)
  40.         CASE(7, Test4151406)
  41.         CASE(8, Test4151429)
  42.         CASE(9, Test4154537)
  43.         CASE(10, Test4154542)
  44.         CASE(11, Test4154650)
  45.         CASE(12, Test4154525)
  46.         CASE(13, Test4162593)
  47.         CASE(14, TestJDK12API)
  48.  
  49.         default: name = ""; break;
  50.     }
  51. }
  52.  
  53. bool_t 
  54. TimeZoneRegressionTest::failure(UErrorCode status, const char* msg)
  55. {
  56.     if(U_FAILURE(status)) {
  57.         errln(UnicodeString("FAIL: ") + msg + " failed, error " + errorName(status));
  58.         return TRUE;
  59.     }
  60.  
  61.     return FALSE;
  62. }
  63.  
  64. /**
  65.  * @bug 4052967
  66.  */
  67. void TimeZoneRegressionTest:: Test4052967() {
  68.     // {sfb} not applicable in C++ ?
  69.     /*logln("*** CHECK TIMEZONE AGAINST HOST OS SETTING ***");
  70.     logln("user.timezone:" + System.getProperty("user.timezone", "<not set>"));
  71.     logln(new Date().toString());
  72.     logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");*/
  73. }
  74.  
  75. /**
  76.  * @bug 4073209
  77.  */
  78. void TimeZoneRegressionTest:: Test4073209() {
  79.     TimeZone *z1 = TimeZone::createTimeZone("PST");
  80.     TimeZone *z2 = TimeZone::createTimeZone("PST");
  81.     if (z1 == z2) 
  82.         errln("Fail: TimeZone should return clones");
  83.     delete z1;
  84.     delete z2;
  85. }
  86.  
  87. /**
  88.  * @bug 4073215
  89.  */
  90. // {sfb} will this work using a Calendar?
  91. void TimeZoneRegressionTest:: Test4073215() 
  92. {
  93.     UErrorCode status = U_ZERO_ERROR;
  94.     SimpleTimeZone *z = (SimpleTimeZone*) TimeZone::createTimeZone("GMT");
  95.     if (z->useDaylightTime())
  96.         errln("Fail: Fix test to start with non-DST zone");
  97.     z->setStartRule(Calendar::FEBRUARY, 1, Calendar::SUNDAY, 0, status);
  98.     failure(status, "z->setStartRule()");
  99.     z->setEndRule(Calendar::MARCH, -1, Calendar::SUNDAY, 0, status);
  100.     failure(status, "z->setStartRule()");
  101.     if (!z->useDaylightTime())
  102.         errln("Fail: DST not active");
  103.     GregorianCalendar *cal = new GregorianCalendar(97, Calendar::JANUARY, 31, status);
  104.     failure(status, "new GregorianCalendar");
  105.     if (z->inDaylightTime(cal->getTime(status), status) || U_FAILURE(status) ) {
  106.         errln("Fail: DST not working as expected");
  107.     }
  108.     cal->set(97, Calendar::MARCH, 1);
  109.     failure(status, "GregorianCalendar->set()");
  110.     if (! z->inDaylightTime(cal->getTime(status), status) || U_FAILURE(status) ) {
  111.         errln("Fail: DST not working as expected");
  112.     }
  113.     cal->set(97, Calendar::MARCH, 31);
  114.     failure(status, "GregorianCalendar->set()");
  115.     if (z->inDaylightTime(cal->getTime(status), status) || U_FAILURE(status)) {
  116.         errln("Fail: DST not working as expected");
  117.     }
  118.  
  119.     delete z;
  120.     delete cal;
  121. }
  122.  
  123. /**
  124.  * @bug 4084933
  125.  * The expected behavior of TimeZone around the boundaries is:
  126.  * (Assume transition time of 2:00 AM)
  127.  *    day of onset 1:59 AM STD  = display name 1:59 AM ST
  128.  *                 2:00 AM STD  = display name 3:00 AM DT
  129.  *    day of end   0:59 AM STD  = display name 1:59 AM DT
  130.  *                 1:00 AM STD  = display name 1:00 AM ST
  131.  */
  132. void TimeZoneRegressionTest:: Test4084933() {
  133.     TimeZone *tz = TimeZone::createTimeZone("PST");
  134.  
  135.     int32_t offset1 = tz->getOffset(1,
  136.         1997, Calendar::OCTOBER, 26, Calendar::SUNDAY, (2*60*60*1000));
  137.     int32_t offset2 = tz->getOffset(1,
  138.         1997, Calendar::OCTOBER, 26, Calendar::SUNDAY, (2*60*60*1000)-1);
  139.  
  140.     int32_t offset3 = tz->getOffset(1,
  141.         1997, Calendar::OCTOBER, 26, Calendar::SUNDAY, (1*60*60*1000));
  142.     int32_t offset4 = tz->getOffset(1,
  143.         1997, Calendar::OCTOBER, 26, Calendar::SUNDAY, (1*60*60*1000)-1);
  144.  
  145.     /*
  146.      *  The following was added just for consistency.  It shows that going *to* Daylight
  147.      *  Savings Time (PDT) does work at 2am.
  148.      */
  149.  
  150.     int32_t offset5 = tz->getOffset(1,
  151.         1997, Calendar::APRIL, 6, Calendar::SUNDAY, (2*60*60*1000));
  152.     int32_t offset6 = tz->getOffset(1,
  153.         1997, Calendar::APRIL, 6, Calendar::SUNDAY, (2*60*60*1000)-1);
  154.  
  155.     int32_t offset7 = tz->getOffset(1,
  156.         1997, Calendar::APRIL, 6, Calendar::SUNDAY, (1*60*60*1000));
  157.     int32_t offset8 = tz->getOffset(1,
  158.         1997, Calendar::APRIL, 6, Calendar::SUNDAY, (1*60*60*1000)-1);
  159.  
  160.     int32_t SToffset = -8 * 60*60*1000L;
  161.     int32_t DToffset = -7 * 60*60*1000L;
  162.     if (offset1 != SToffset || offset2 != SToffset ||
  163.         offset3 != SToffset || offset4 != DToffset ||
  164.         offset5 != DToffset || offset6 != SToffset ||
  165.         offset7 != SToffset || offset8 != SToffset)
  166.         errln("Fail: TimeZone misbehaving");
  167.  
  168.     delete tz;
  169. }
  170.  
  171. /**
  172.  * @bug 4096952
  173.  */
  174. void TimeZoneRegressionTest:: Test4096952() {
  175.     // {sfb} serialization not applicable
  176. /*
  177.     UnicodeString ZONES [] = { UnicodeString("GMT"), UnicodeString("MET"), UnicodeString("IST") };
  178.     bool_t pass = TRUE;
  179.     //try {
  180.         for (int32_t i=0; i < ZONES.length; ++i) {
  181.             TimeZone *zone = TimeZone::createTimeZone(ZONES[i]);
  182.             UnicodeString id;
  183.             if (zone->getID(id) != ZONES[i])
  184.                 errln("Fail: Test broken; zones not instantiating");
  185.  
  186.             ByteArrayOutputStream baos;
  187.             ObjectOutputStream ostream =
  188.                 new ObjectOutputStream(baos = new 
  189.                                        ByteArrayOutputStream());
  190.             ostream.writeObject(zone);
  191.             ostream.close();
  192.             baos.close();
  193.             ObjectInputStream istream =
  194.                 new ObjectInputStream(new 
  195.                                       ByteArrayInputStream(baos.toByteArray()));
  196.             TimeZone frankenZone = (TimeZone) istream.readObject();
  197.             //logln("Zone:        " + zone);
  198.             //logln("FrankenZone: " + frankenZone);
  199.             if (!zone.equals(frankenZone)) {
  200.                 logln("TimeZone " + zone.getID() +
  201.                       " not equal to serialized/deserialized one");
  202.                 pass = false;
  203.             }
  204.         }
  205.         if (!pass) errln("Fail: TimeZone serialization/equality bug");
  206.     }
  207.     catch (IOException e) {
  208.         errln("Fail: " + e);
  209.         e.print32_tStackTrace();
  210.     }
  211.     catch (ClassNotFoundException e) {
  212.         errln("Fail: " + e);
  213.         e.print32_tStackTrace();
  214.     }
  215. */
  216. }
  217.  
  218. /**
  219.  * @bug 4109314
  220.  */
  221. void TimeZoneRegressionTest:: Test4109314() {
  222.     UErrorCode status = U_ZERO_ERROR;
  223.     GregorianCalendar *testCal = (GregorianCalendar*)Calendar::createInstance(status); 
  224.     failure(status, "Calendar::createInstance");
  225.     TimeZone *PST = TimeZone::createTimeZone("PST");
  226.     /*Object[] testData = {
  227.         PST, new Date(98,Calendar.APRIL,4,22,0), new Date(98, Calendar.APRIL, 5,6,0),
  228.         PST, new Date(98,Calendar.OCTOBER,24,22,0), new Date(98,Calendar.OCTOBER,25,6,0),
  229.     };*/
  230.     UDate testData [] = {
  231.         CalendarRegressionTest::makeDate(98,Calendar::APRIL,4,22,0),    
  232.         CalendarRegressionTest::makeDate(98, Calendar::APRIL,5,6,0),
  233.         CalendarRegressionTest::makeDate(98,Calendar::OCTOBER,24,22,0), 
  234.         CalendarRegressionTest::makeDate(98,Calendar::OCTOBER,25,6,0)
  235.     };
  236.     bool_t pass = TRUE;
  237.     for (int32_t i = 0; i < 4; i+=2) {
  238.         //testCal->setTimeZone((TimeZone) testData[i]);
  239.         testCal->setTimeZone(*PST);
  240.         UDate t        = testData[i];
  241.         UDate end    = testData[i+1];
  242.         while(testCal->getTime(status) < end) { 
  243.             testCal->setTime(t, status);
  244.             if ( ! checkCalendar314(testCal, PST))
  245.                 pass = FALSE;
  246.             t += 60*60*1000.0;
  247.         } 
  248.     }
  249.     if ( ! pass) 
  250.         errln("Fail: TZ API inconsistent");
  251.  
  252.     delete testCal;
  253.     delete PST;
  254.  
  255. bool_t 
  256. TimeZoneRegressionTest::checkCalendar314(GregorianCalendar *testCal, TimeZone *testTZ) 
  257. {
  258.     UErrorCode status = U_ZERO_ERROR;
  259.     // GregorianCalendar testCal = (GregorianCalendar)aCal.clone(); 
  260.  
  261.     int32_t tzOffset, tzRawOffset; 
  262.     float tzOffsetFloat,tzRawOffsetFloat; 
  263.     // Here is where the user made an error.  They were passing in the value of
  264.     // the MILLSECOND field; you need to pass in the millis in the day in STANDARD
  265.     // time.
  266.     UDate millis = testCal->get(Calendar::MILLISECOND, status) +
  267.         1000.0 * (testCal->get(Calendar::SECOND, status) +
  268.         60.0 * (testCal->get(Calendar::MINUTE, status) +
  269.         60.0 * (testCal->get(Calendar::HOUR_OF_DAY, status)))) -
  270.         testCal->get(Calendar::DST_OFFSET, status);
  271.  
  272.     /* Fix up millis to be in range.  ASSUME THAT WE ARE NOT AT THE
  273.      * BEGINNING OR END OF A MONTH.  We must add this code because
  274.      * getOffset() has been changed to be more strict about the parameters
  275.      * it receives -- it turns out that this test was passing in illegal
  276.      * values. */
  277.     int32_t date = testCal->get(Calendar::DATE, status);
  278.     int32_t dow  = testCal->get(Calendar::DAY_OF_WEEK, status);
  279.     while(millis < 0) {
  280.         millis += U_MILLIS_PER_DAY;
  281.         --date;
  282.         dow = Calendar::SUNDAY + ((dow - Calendar::SUNDAY + 6) % 7);
  283.     }
  284.     while (millis >= U_MILLIS_PER_DAY) {
  285.         millis -= U_MILLIS_PER_DAY;
  286.         ++date;
  287.         dow = Calendar::SUNDAY + ((dow - Calendar::SUNDAY + 1) % 7);
  288.     }
  289.  
  290.     tzOffset = testTZ->getOffset((uint8_t)testCal->get(Calendar::ERA, status), 
  291.                                 testCal->get(Calendar::YEAR, status), 
  292.                                 testCal->get(Calendar::MONTH, status), 
  293.                                 date, 
  294.                                 (uint8_t)dow, 
  295.                                 (int32_t)millis,
  296.                                 status); 
  297.     tzRawOffset = testTZ->getRawOffset(); 
  298.     tzOffsetFloat = (float)tzOffset/(float)3600000; 
  299.     tzRawOffsetFloat = (float)tzRawOffset/(float)3600000; 
  300.  
  301.     UDate testDate = testCal->getTime(status); 
  302.  
  303.     bool_t inDaylightTime = testTZ->inDaylightTime(testDate, status); 
  304.     SimpleDateFormat *sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm", status); 
  305.     sdf->setCalendar(*testCal); 
  306.     UnicodeString inDaylightTimeString; 
  307.  
  308.     bool_t passed; 
  309.  
  310.     if(inDaylightTime) 
  311.     { 
  312.         inDaylightTimeString = " DST "; 
  313.         passed = (tzOffset == (tzRawOffset + 3600000));
  314.     } 
  315.     else 
  316.     { 
  317.         inDaylightTimeString = "     "; 
  318.         passed = (tzOffset == tzRawOffset);
  319.     } 
  320.  
  321.     UnicodeString output;
  322.     FieldPosition pos(0);
  323.     output = testTZ->getID(output) + " " + sdf->format(testDate, output, pos) +
  324.         " Offset(" + tzOffsetFloat + ")" +
  325.         " RawOffset(" + tzRawOffsetFloat + ")" + 
  326.         " " + millis/(float)3600000 + " " +
  327.         inDaylightTimeString; 
  328.  
  329.     if (passed) 
  330.         output += "     "; 
  331.     else 
  332.         output += "ERROR"; 
  333.  
  334.     if (passed) 
  335.         logln(output); 
  336.     else 
  337.         errln(output);
  338.  
  339.     delete sdf;
  340.     return passed;
  341.  
  342. /**
  343.  * @bug 4126678
  344.  * CANNOT REPRODUDE
  345.  *
  346.  * Yet another _alleged_ bug in TimeZone::getOffset(), a method that never
  347.  * should have been made public.  It's simply too hard to use correctly.
  348.  *
  349.  * The original test code failed to do the following:
  350.  * (1) Call Calendar::setTime() before getting the fields!
  351.  * (2) Use the right millis (as usual) for getOffset(); they were passing
  352.  *     in the MILLIS field, instead of the STANDARD MILLIS IN DAY.
  353.  * When you fix these two problems, the test passes, as expected.
  354.  */
  355. void TimeZoneRegressionTest:: Test4126678() 
  356. {
  357.     UErrorCode status = U_ZERO_ERROR;
  358.     Calendar *cal = Calendar::createInstance(status);
  359.     failure(status, "Calendar::createInstance");
  360.     TimeZone *tz = TimeZone::createTimeZone("PST");
  361.     cal->adoptTimeZone(tz);
  362.  
  363.     cal->set(1998 - 1900, Calendar::APRIL, 5, 10, 0);
  364.     //Date dt = new Date(1998-1900, Calendar::APRIL, 5, 10, 0);
  365.     
  366.     if (! tz->inDaylightTime(cal->getTime(status), status) || U_FAILURE(status))
  367.         errln("We're not in Daylight Savings Time and we should be.\n");
  368.  
  369.     //cal.setTime(dt);
  370.     int32_t era = cal->get(Calendar::ERA, status);
  371.     int32_t year = cal->get(Calendar::YEAR, status);
  372.     int32_t month = cal->get(Calendar::MONTH, status);
  373.     int32_t day = cal->get(Calendar::DATE, status);
  374.     int32_t dayOfWeek = cal->get(Calendar::DAY_OF_WEEK, status);
  375.     int32_t millis = cal->get(Calendar::MILLISECOND, status) +
  376.         (cal->get(Calendar::SECOND, status) +
  377.          (cal->get(Calendar::MINUTE, status) +
  378.           (cal->get(Calendar::HOUR, status) * 60) * 60) * 1000) -
  379.         cal->get(Calendar::DST_OFFSET, status);
  380.  
  381.     failure(status, "cal->get");
  382.     int32_t offset = tz->getOffset((uint8_t)era, year, month, day, (uint8_t)dayOfWeek, millis);
  383.     int32_t raw_offset = tz->getRawOffset();
  384.     if (offset == raw_offset)
  385.         errln("Offsets should not match when in DST");
  386.  
  387.     delete cal;
  388. }
  389.  
  390. /**
  391.  * @bug 4151406
  392.  * TimeZone::getAvailableIDs(int32_t) throws exception for certain values,
  393.  * due to a faulty constant in TimeZone::java.
  394.  */
  395. void TimeZoneRegressionTest:: Test4151406() {
  396.     int32_t max = 0;
  397.     for (int32_t h=-28; h<=30; ++h) {
  398.         // h is in half-hours from GMT; rawoffset is in millis
  399.         int32_t rawoffset = h * 1800000;
  400.         int32_t hh = (h<0) ? -h : h;
  401.         UnicodeString hname = ((h<0) ? UnicodeString("GMT-") : UnicodeString("GMT+")) +
  402.             ((hh/2 < 10) ? "0" : "") +
  403.             (hh/2) + ':' +
  404.             ((hh%2==0) ? "00" : "30");
  405.         //try {
  406.             int32_t count;
  407.             const UnicodeString **ids = TimeZone::createAvailableIDs(rawoffset, count);
  408.             if (count> max) 
  409.                 max = count;
  410.             logln(hname + ' ' + count +
  411.                   ((count > 0) ? (" e.g. " + *ids[0]) : UnicodeString("")));
  412.             delete [] ids;
  413.         /*} catch (Exception e) {
  414.             errln(hname + ' ' + "Fail: " + e);
  415.         }*/
  416.     }
  417.     logln("Maximum zones per offset = " + max);
  418. }
  419.  
  420. /**
  421.  * @bug 4151429
  422.  */
  423. void TimeZoneRegressionTest:: Test4151429() {
  424.     // {sfb} silly test in C++, since we are using an enum and not an int
  425.     //try {
  426.         /*TimeZone *tz = TimeZone::createTimeZone("GMT");
  427.         UnicodeString name;
  428.         tz->getDisplayName(TRUE, TimeZone::LONG,
  429.                                         Locale.getDefault(), name);
  430.         errln("IllegalArgumentException not thrown by TimeZone::getDisplayName()");*/
  431.     //} catch(IllegalArgumentException e) {}
  432. }
  433.  
  434. /**
  435.  * @bug 4154537
  436.  * SimpleTimeZone::hasSameRules() doesn't work for zones with no DST
  437.  * and different DST parameters.
  438.  */
  439. void TimeZoneRegressionTest:: Test4154537() {
  440.     UErrorCode status = U_ZERO_ERROR;
  441.     // tz1 and tz2 have no DST and different rule parameters
  442.     SimpleTimeZone *tz1 = new SimpleTimeZone(0, "1", 0, 0, 0, 0, 2, 0, 0, 0, status);
  443.     SimpleTimeZone *tz2 = new SimpleTimeZone(0, "2", 1, 0, 0, 0, 3, 0, 0, 0, status);
  444.     // tza and tzA have the same rule params
  445.     SimpleTimeZone *tza = new SimpleTimeZone(0, "a", 0, 1, 0, 0, 3, 2, 0, 0, status);
  446.     SimpleTimeZone *tzA = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 3, 2, 0, 0, status);
  447.     // tzb differs from tza
  448.     SimpleTimeZone *tzb = new SimpleTimeZone(0, "b", 0, 1, 0, 0, 3, 1, 0, 0, status);
  449.     
  450.     if(U_FAILURE(status))
  451.         errln("Couldn't create TimeZones");
  452.  
  453.     if (tz1->useDaylightTime() || tz2->useDaylightTime() ||
  454.         !tza->useDaylightTime() || !tzA->useDaylightTime() ||
  455.         !tzb->useDaylightTime()) {
  456.         errln("Test is broken -- rewrite it");
  457.     }
  458.     if (!tza->hasSameRules(*tzA) || tza->hasSameRules(*tzb)) {
  459.         errln("Fail: hasSameRules() broken for zones with rules");
  460.     }
  461.     if (!tz1->hasSameRules(*tz2)) {
  462.         errln("Fail: hasSameRules() returns false for zones without rules");
  463.         //errln("zone 1 = " + tz1);
  464.         //errln("zone 2 = " + tz2);
  465.     }
  466.  
  467.     delete tz1;
  468.     delete tz2;
  469.     delete tza;
  470.     delete tzA;
  471.     delete tzb;
  472. }
  473.  
  474. /**
  475.  * @bug 4154542
  476.  * SimpleTimeZOne constructors, setStartRule(), and setEndRule() don't
  477.  * check for out-of-range arguments.
  478.  */
  479. void TimeZoneRegressionTest:: Test4154542() 
  480. {
  481.     const int32_t GOOD = 1;
  482.     const int32_t BAD  = 0;
  483.  
  484.     const int32_t GOOD_MONTH       = Calendar::JANUARY;
  485.     const int32_t GOOD_DAY         = 1;
  486.     const int32_t GOOD_DAY_OF_WEEK = Calendar::SUNDAY;
  487.     const int32_t GOOD_TIME        = 0;
  488.  
  489.     int32_t DATA [] = {
  490.         GOOD, INT_MIN,    0,  INT_MAX,   INT_MIN,
  491.         GOOD, Calendar::JANUARY,    -5,  Calendar::SUNDAY,     0,
  492.         GOOD, Calendar::DECEMBER,    5,  Calendar::SATURDAY,   24*60*60*1000,
  493.         BAD,  Calendar::DECEMBER,    5,  Calendar::SATURDAY,   24*60*60*1000+1,
  494.         BAD,  Calendar::DECEMBER,    5,  Calendar::SATURDAY,  -1,
  495.         BAD,  Calendar::JANUARY,    -6,  Calendar::SUNDAY,     0,
  496.         BAD,  Calendar::DECEMBER,    6,  Calendar::SATURDAY,   24*60*60*1000,
  497.         GOOD, Calendar::DECEMBER,    1,  0,                   0,
  498.         GOOD, Calendar::DECEMBER,   31,  0,                   0,
  499.         BAD,  Calendar::APRIL,      31,  0,                   0,
  500.         BAD,  Calendar::DECEMBER,   32,  0,                   0,
  501.         BAD,  Calendar::JANUARY-1,   1,  Calendar::SUNDAY,     0,
  502.         BAD,  Calendar::DECEMBER+1,  1,  Calendar::SUNDAY,     0,
  503.         GOOD, Calendar::DECEMBER,   31, -Calendar::SUNDAY,     0,
  504.         GOOD, Calendar::DECEMBER,   31, -Calendar::SATURDAY,   0,
  505.         BAD,  Calendar::DECEMBER,   32, -Calendar::SATURDAY,   0,
  506.         BAD,  Calendar::DECEMBER,  -32, -Calendar::SATURDAY,   0,
  507.         BAD,  Calendar::DECEMBER,   31, -Calendar::SATURDAY-1, 0,
  508.     };
  509.     SimpleTimeZone *zone = new SimpleTimeZone(0, "Z");
  510.     for (int32_t i=0; i < 18*5; i+=5) {
  511.         bool_t shouldBeGood = (DATA[i] == GOOD);
  512.         int32_t month     = DATA[i+1];
  513.         int32_t day       = DATA[i+2];
  514.         int32_t dayOfWeek = DATA[i+3];
  515.         int32_t time      = DATA[i+4];
  516.  
  517.         UErrorCode status = U_ZERO_ERROR;
  518.  
  519.         //Exception ex = null;
  520.         //try {
  521.             zone->setStartRule(month, day, dayOfWeek, time, status);
  522.         //} catch (IllegalArgumentException e) {
  523.         //    ex = e;
  524.         //}
  525.         if (U_SUCCESS(status) != shouldBeGood) {
  526.             errln(UnicodeString("setStartRule(month=") + month + ", day=" + day +
  527.                   ", dayOfWeek=" + dayOfWeek + ", time=" + time +
  528.                   (shouldBeGood ? (") should work")
  529.                    : ") should fail but doesn't"));
  530.         }
  531.  
  532.         //ex = null;
  533.         //try {
  534.         status = U_ZERO_ERROR;
  535.             zone->setEndRule(month, day, dayOfWeek, time, status);
  536.         //} catch (IllegalArgumentException e) {
  537.         //   ex = e;
  538.         //}
  539.         if (U_SUCCESS(status) != shouldBeGood) {
  540.             errln(UnicodeString("setEndRule(month=") + month + ", day=" + day +
  541.                   ", dayOfWeek=" + dayOfWeek + ", time=" + time +
  542.                   (shouldBeGood ? (") should work")
  543.                    : ") should fail but doesn't"));
  544.         }
  545.  
  546.         //ex = null;
  547.         //try {
  548.         // {sfb} need to look into ctor problems! (UErrorCode vs. dst signature confusion)
  549.         status = U_ZERO_ERROR;
  550.             SimpleTimeZone *temp = new SimpleTimeZone(0, "Z",
  551.                     (int8_t)month, (int8_t)day, (int8_t)dayOfWeek, time,
  552.                     (int8_t)GOOD_MONTH, (int8_t)GOOD_DAY, (int8_t)GOOD_DAY_OF_WEEK, 
  553.                     GOOD_TIME,status);
  554.         //} catch (IllegalArgumentException e) {
  555.         //    ex = e;
  556.         //}
  557.         if (U_SUCCESS(status) != shouldBeGood) {
  558.             errln(UnicodeString("SimpleTimeZone(month=") + month + ", day=" + day +
  559.                   ", dayOfWeek=" + dayOfWeek + ", time=" + time +
  560.                   (shouldBeGood ? (", <end>) should work")// + ex)
  561.                    : ", <end>) should fail but doesn't"));
  562.         }
  563.   
  564.         delete temp;
  565.         //ex = null;
  566.         //try {
  567.         status = U_ZERO_ERROR;
  568.             temp = new SimpleTimeZone(0, "Z",
  569.                     (int8_t)GOOD_MONTH, (int8_t)GOOD_DAY, (int8_t)GOOD_DAY_OF_WEEK, 
  570.                     GOOD_TIME,
  571.                     (int8_t)month, (int8_t)day, (int8_t)dayOfWeek, time,status);
  572.         //} catch (IllegalArgumentException e) {
  573.         //    ex = e;
  574.         //}
  575.         if (U_SUCCESS(status) != shouldBeGood) {
  576.             errln(UnicodeString("SimpleTimeZone(<start>, month=") + month + ", day=" + day +
  577.                   ", dayOfWeek=" + dayOfWeek + ", time=" + time +
  578.                   (shouldBeGood ? (") should work")// + ex)
  579.                    : ") should fail but doesn't"));
  580.         }            
  581.         delete temp;
  582.     }
  583. }
  584.  
  585.  
  586. /**
  587.  * @bug 4154525
  588.  * SimpleTimeZone accepts illegal DST savings values.  These values
  589.  * must be non-zero.  There is no upper limit at this time.
  590.  */
  591. void 
  592. TimeZoneRegressionTest::Test4154525() 
  593. {
  594.     const int32_t GOOD = 1, BAD = 0;
  595.     
  596.     int32_t DATA [] = {
  597.         1, GOOD,
  598.         0, BAD,
  599.         -1, BAD,
  600.         60*60*1000, GOOD,
  601.         LONG_MIN, BAD,
  602.         // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time
  603.     };
  604.  
  605.     UErrorCode status = U_ZERO_ERROR;
  606.     for(int32_t i = 0; i < 10; i+=2) {
  607.         int32_t savings = DATA[i];
  608.         bool_t valid = DATA[i+1] == GOOD;
  609.         UnicodeString method;
  610.         for(int32_t j=0; j < 2; ++j) {
  611.             SimpleTimeZone *z;
  612.             switch (j) {
  613.                 case 0:
  614.                     method = "constructor";
  615.                     z = new SimpleTimeZone(0, "id",
  616.                         Calendar::JANUARY, 1, 0, 0,
  617.                         Calendar::MARCH, 1, 0, 0,
  618.                         savings, status); // <- what we're interested in
  619.                     break;
  620.                 case 1:
  621.                     method = "setDSTSavings()";
  622.                     z = new SimpleTimeZone(0, "GMT");
  623.                     z->setDSTSavings(savings, status);
  624.                     break;
  625.             }
  626.                 
  627.             if(U_FAILURE(status)) {
  628.                 if(valid) {
  629.                     errln(UnicodeString("Fail: DST savings of ") + savings + " to " + method + " gave " + errorName(status));
  630.                 } 
  631.                 else {
  632.                     logln(UnicodeString("Pass: DST savings of ") + savings + " to " + method + " gave " + errorName(status));
  633.                 }               
  634.             }
  635.             else {
  636.                 if(valid) {
  637.                     logln(UnicodeString("Pass: DST savings of ") + savings + " accepted by " + method);
  638.                 } 
  639.                 else {
  640.                     errln(UnicodeString("Fail: DST savings of ") + savings + " accepted by " + method);
  641.                 }
  642.             }
  643.             status = U_ZERO_ERROR;
  644.             delete z;
  645.         }
  646.     }
  647. }
  648.  
  649. /**
  650.  * @bug 4154650
  651.  * SimpleTimeZone.getOffset accepts illegal arguments.
  652.  */
  653. void 
  654. TimeZoneRegressionTest::Test4154650() 
  655. {
  656.     const int32_t GOOD = 1, BAD = 0;
  657.     const int32_t GOOD_ERA = GregorianCalendar::AD, GOOD_YEAR = 1998, GOOD_MONTH = Calendar::AUGUST;
  658.     const int32_t GOOD_DAY = 2, GOOD_DOW = Calendar::SUNDAY, GOOD_TIME = 16*3600000;
  659.  
  660.     int32_t DATA []= {
  661.         GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
  662.  
  663.         GOOD, GregorianCalendar::BC, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
  664.         GOOD, GregorianCalendar::AD, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
  665.         BAD,  GregorianCalendar::BC-1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
  666.         BAD,  GregorianCalendar::AD+1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
  667.  
  668.         GOOD, GOOD_ERA, GOOD_YEAR, Calendar::JANUARY, GOOD_DAY, GOOD_DOW, GOOD_TIME,
  669.         GOOD, GOOD_ERA, GOOD_YEAR, Calendar::DECEMBER, GOOD_DAY, GOOD_DOW, GOOD_TIME,
  670.         BAD,  GOOD_ERA, GOOD_YEAR, Calendar::JANUARY-1, GOOD_DAY, GOOD_DOW, GOOD_TIME,
  671.         BAD,  GOOD_ERA, GOOD_YEAR, Calendar::DECEMBER+1, GOOD_DAY, GOOD_DOW, GOOD_TIME,
  672.         
  673.         GOOD, GOOD_ERA, GOOD_YEAR, Calendar::JANUARY, 1, GOOD_DOW, GOOD_TIME,
  674.         GOOD, GOOD_ERA, GOOD_YEAR, Calendar::JANUARY, 31, GOOD_DOW, GOOD_TIME,
  675.         BAD,  GOOD_ERA, GOOD_YEAR, Calendar::JANUARY, 0, GOOD_DOW, GOOD_TIME,
  676.         BAD,  GOOD_ERA, GOOD_YEAR, Calendar::JANUARY, 32, GOOD_DOW, GOOD_TIME,
  677.  
  678.         GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar::SUNDAY, GOOD_TIME,
  679.         GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar::SATURDAY, GOOD_TIME,
  680.         BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar::SUNDAY-1, GOOD_TIME,
  681.         BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar::SATURDAY+1, GOOD_TIME,
  682.  
  683.         GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 0,
  684.         GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000-1,
  685.         BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, -1,
  686.         BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000,
  687.     };
  688.  
  689.     int32_t dataLen = sizeof(DATA) / sizeof(DATA[0]);
  690.  
  691.     UErrorCode status = U_ZERO_ERROR;
  692.     TimeZone *tz = TimeZone::createDefault();
  693.     for(int32_t i = 0; i < dataLen; i += 7) {
  694.         bool_t good = DATA[i] == GOOD;
  695.         //IllegalArgumentException e = null;
  696.         //try {
  697.             int32_t offset = tz->getOffset((uint8_t)DATA[i+1], DATA[i+2], DATA[i+3],
  698.                                       DATA[i+4], (uint8_t)DATA[i+5], DATA[i+6], status); 
  699.        //} catch (IllegalArgumentException ex) {
  700.          //   e = ex;
  701.         //}
  702.         if(good != U_SUCCESS(status)) {
  703.             errln(UnicodeString("Fail: getOffset(") +
  704.                   DATA[i+1] + ", " + DATA[i+2] + ", " + DATA[i+3] + ", " +
  705.                   DATA[i+4] + ", " + DATA[i+5] + ", " + DATA[i+6] +
  706.                   (good ? (UnicodeString(") threw ") + errorName(status)) : UnicodeString(") accepts invalid args")));
  707.         }
  708.         status = U_ZERO_ERROR; // reset
  709.     }
  710.     delete tz;
  711. }
  712.  
  713. /**
  714.  * @bug 4162593
  715.  * TimeZone broken at midnight.  The TimeZone code fails to handle
  716.  * transitions at midnight correctly.
  717.  */
  718. void 
  719. TimeZoneRegressionTest::Test4162593() 
  720. {
  721.     UErrorCode status = U_ZERO_ERROR;
  722.     SimpleDateFormat *fmt = new SimpleDateFormat("z", Locale::US, status);
  723.     const int32_t ONE_HOUR = 60*60*1000;
  724.  
  725.     SimpleTimeZone *asuncion = new SimpleTimeZone(-4*ONE_HOUR, "America/Asuncion" /*PY%sT*/,
  726.         Calendar::OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR,
  727.         Calendar::MARCH, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR, status);
  728.  
  729.     /* Zone
  730.      * Starting time
  731.      * Transition expected between start+1H and start+2H
  732.      */
  733.     TimeZone *DATA_TZ [] = {
  734.       0, 0, 0 };
  735.  
  736.     int32_t DATA_INT [] [5] = {
  737.         {98, Calendar::SEPTEMBER, 30, 22, 0},
  738.         {100, Calendar::FEBRUARY, 28, 22, 0},
  739.         {100, Calendar::FEBRUARY, 29, 22, 0},
  740.      };
  741.  
  742.     bool_t DATA_BOOL [] = {
  743.         TRUE,
  744.         FALSE,
  745.         TRUE,
  746.     };
  747.     
  748.     UnicodeString zone [4];// = new String[4];
  749.     DATA_TZ[0] =  
  750.         new SimpleTimeZone(2*ONE_HOUR, "Asia/Damascus" /*EE%sT*/,
  751.             Calendar::APRIL, 1, 0 /*DOM*/, 0*ONE_HOUR,
  752.             Calendar::OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR, status);
  753.     DATA_TZ[1] = asuncion;  DATA_TZ[2] = asuncion;  
  754.  
  755.     for(int32_t j = 0; j < 3; j++) {
  756.         TimeZone *tz = (TimeZone*)DATA_TZ[j];
  757.         TimeZone::setDefault(*tz);
  758.         fmt->setTimeZone(*tz);
  759.  
  760.         // Must construct the Date object AFTER setting the default zone
  761.         int32_t *p = (int32_t*)DATA_INT[j];
  762.         UDate d = CalendarRegressionTest::makeDate(p[0], p[1], p[2], p[3], p[4]);
  763.         bool_t transitionExpected = DATA_BOOL[j];
  764.  
  765.         UnicodeString temp;
  766.         logln(tz->getID(temp) + ":");
  767.         for (int32_t i = 0; i < 4; ++i) {
  768.             FieldPosition pos(0);
  769.             zone[i].remove();
  770.             zone[i] = fmt->format(d, zone[i], pos);
  771.             logln(UnicodeString("") + i + ": " + d + " / " + zone[i]);
  772.             d += (double) ONE_HOUR;
  773.         }
  774.         if(zone[0] == zone[1] &&
  775.             (zone[1] == zone[2]) != transitionExpected &&
  776.             zone[2] == zone[3]) {
  777.             logln(UnicodeString("Ok: transition ") + transitionExpected);
  778.         } 
  779.         else {
  780.             errln("Fail: boundary transition incorrect");
  781.         }
  782.     }
  783.     delete fmt;
  784.     delete asuncion;
  785.     delete DATA_TZ[0];
  786. }
  787.  
  788. // test new API for JDK 1.2 8/31 putback
  789. void
  790. TimeZoneRegressionTest::TestJDK12API()
  791. {
  792.     TimeZone *pst = TimeZone::createTimeZone("PST");
  793.     TimeZone *cst1 = TimeZone::createTimeZone("CST");
  794.  
  795.     SimpleTimeZone *cst = 0;
  796.  
  797.     if(cst1->getDynamicClassID() == SimpleTimeZone::getStaticClassID())
  798.         cst = (SimpleTimeZone*) cst1;
  799.  
  800.     if(pst->hasSameRules(*cst)) {
  801.         errln("FAILURE: PST and CST have same rules");
  802.     }
  803.  
  804.     UErrorCode status = U_ZERO_ERROR;
  805.     int32_t offset1 = pst->getOffset(1,
  806.         1997, Calendar::OCTOBER, 26, Calendar::SUNDAY, (2*60*60*1000), status);
  807.     failure(status, "getOffset() failed");
  808.  
  809.  
  810.     int32_t offset2 = cst->getOffset(1,
  811.         1997, Calendar::OCTOBER, 26, Calendar::SUNDAY, (2*60*60*1000), 31, status);
  812.     failure(status, "getOffset() failed");
  813.  
  814.     if(offset1 == offset2)
  815.         errln("FAILURE: Sunday Oct. 26 1997 2:00 has same offset for PST and CST");
  816.  
  817.     // verify error checking
  818.     int32_t offset3 = pst->getOffset(1,
  819.         1997, (Calendar::EDateFields)-1, 26, Calendar::SUNDAY, (2*60*60*1000), status);
  820.     if(U_SUCCESS(status))
  821.         errln("FAILURE: getOffset() succeeded with -1 for month");
  822.  
  823.     status = U_ZERO_ERROR;
  824.     cst->setDSTSavings(60*60*1000, status);
  825.     failure(status, "setDSTSavings() failed");
  826.  
  827.     int32_t savings = cst->getDSTSavings();
  828.     if(savings != 60*60*1000) {
  829.         errln("setDSTSavings() failed");
  830.     }
  831.  
  832.     delete pst;
  833.     delete cst;
  834. }
  835.