From abbc83a2870d4e384a239f0bbec5cbd03dbb9a26 Mon Sep 17 00:00:00 2001 From: Yoshito Umaoka Date: Mon, 9 Jul 2007 22:41:48 +0000 Subject: [PATCH] ICU-5454 Added clone implementation in RuleBasedTimeZone and VTimeZone. A bug fix in VTimeZone#write#write to put required new line codes. More test cases to imrove the code coverage. X-SVN-Rev: 21932 --- .../dev/test/timezone/TimeZoneRuleTest.java | 215 +++++++++++++++++- .../com/ibm/icu/util/RuleBasedTimeZone.java | 16 ++ icu4j/src/com/ibm/icu/util/VTimeZone.java | 12 + 3 files changed, 241 insertions(+), 2 deletions(-) diff --git a/icu4j/src/com/ibm/icu/dev/test/timezone/TimeZoneRuleTest.java b/icu4j/src/com/ibm/icu/dev/test/timezone/TimeZoneRuleTest.java index 84d522e553..2e27118460 100644 --- a/icu4j/src/com/ibm/icu/dev/test/timezone/TimeZoneRuleTest.java +++ b/icu4j/src/com/ibm/icu/dev/test/timezone/TimeZoneRuleTest.java @@ -41,7 +41,7 @@ public class TimeZoneRuleTest extends TestFmwk { } /* - * Compare SimpleTimeZone with equivalent RBTZ + * RuleBasedTimeZone test cases */ public void TestSimpleRuleBasedTimeZone() { SimpleTimeZone stz = new SimpleTimeZone(-1*HOUR, "TestSTZ", @@ -59,7 +59,7 @@ public class TimeZoneRuleTest extends TestFmwk { -1*HOUR, // Raw offset 1*HOUR); // DST saving amount - // Original rules + // RBTZ RuleBasedTimeZone rbtz1 = new RuleBasedTimeZone("RBTZ1", ir); dtr = new DateTimeRule(Calendar.SEPTEMBER, 30, Calendar.SATURDAY, false, 1*HOUR, DateTimeRule.WALL_TIME); // SUN<=30 in September, at 1AM wall time @@ -121,6 +121,83 @@ public class TimeZoneRuleTest extends TestFmwk { if (!rbtz1.hasSameRules(rbtz1c)) { errln("FAIL: Cloned RuleBasedTimeZone must have the same rules with the original."); } + + // getOffset + GregorianCalendar cal = new GregorianCalendar(); + int[] offsets = new int[2]; + int offset; + boolean dst; + + cal.setTimeZone(rbtz1); + cal.clear(); + + // Jan 1, 1000 BC + cal.set(Calendar.ERA, GregorianCalendar.BC); + cal.set(1000, Calendar.JANUARY, 1); + + offset = rbtz1.getOffset(cal.get(Calendar.ERA), cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), + cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.DAY_OF_WEEK), cal.get(Calendar.MILLISECONDS_IN_DAY)); + if (offset != 0) { + errln("FAIL: Invalid time zone offset: " + offset + " /expected: 0"); + } + dst = rbtz1.inDaylightTime(cal.getTime()); + if (!dst) { + errln("FAIL: Invalid daylight saving time"); + } + rbtz1.getOffset(cal.getTimeInMillis(), true, offsets); + if (offsets[0] != -3600000) { + errln("FAIL: Invalid time zone raw offset: " + offsets[0] + " /expected: -3600000"); + } + if (offsets[1] != 3600000) { + errln("FAIL: Invalid DST amount: " + offsets[1] + " /expected: 3600000"); + } + + // July 1, 2000, AD + cal.set(Calendar.ERA, GregorianCalendar.AD); + cal.set(2000, Calendar.JULY, 1); + + offset = rbtz1.getOffset(cal.get(Calendar.ERA), cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), + cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.DAY_OF_WEEK), cal.get(Calendar.MILLISECONDS_IN_DAY)); + if (offset != -3600000) { + errln("FAIL: Invalid time zone offset: " + offset + " /expected: -3600000"); + } + dst = rbtz1.inDaylightTime(cal.getTime()); + if (dst) { + errln("FAIL: Invalid daylight saving time"); + } + rbtz1.getOffset(cal.getTimeInMillis(), true, offsets); + if (offsets[0] != -3600000) { + errln("FAIL: Invalid time zone raw offset: " + offsets[0] + " /expected: -3600000"); + } + if (offsets[1] != 0) { + errln("FAIL: Invalid DST amount: " + offsets[1] + " /expected: 0"); + } + + // July 1, 2000, AD + + // Try to add 3rd final rule + dtr = new DateTimeRule(Calendar.OCTOBER, 15, 1*HOUR, DateTimeRule.WALL_TIME); + atzr = new AnnualTimeZoneRule("3RD_ATZ", -1*HOUR, 2*HOUR, dtr, STARTYEAR, AnnualTimeZoneRule.MAX_YEAR); + boolean bException = false; + try { + rbtz1.addTransitionRule(atzr); + } catch (IllegalStateException ise) { + bException = true; + } + if (!bException) { + errln("FAIL: 3rd final rule must be rejected"); + } + + // Try to add an initial rule + bException = false; + try { + rbtz1.addTransitionRule(new InitialTimeZoneRule("Test Initial", 2*HOUR, 0)); + } catch (IllegalArgumentException iae) { + bException = true; + } + if (!bException) { + errln("FAIL: InitialTimeZoneRule must be rejected"); + } } /* @@ -204,6 +281,10 @@ public class TimeZoneRuleTest extends TestFmwk { if (ny.hasSameRules(rbtz) || rbtz.hasSameRules(ny)) { errln("FAIL: hasSameRules must return false"); } + RuleBasedTimeZone rbtzc = (RuleBasedTimeZone)rbtz.clone(); + if (!rbtz.hasSameRules(rbtzc) || !rbtz.hasEquivalentTransitions(rbtzc, jan1_1950, jan1_2010)) { + errln("FAIL: hasSameRules/hasEquivalentTransitions must return true for cloned RBTZs"); + } long times[] = { getUTCMillis(2006, Calendar.MARCH, 15), @@ -369,6 +450,23 @@ public class TimeZoneRuleTest extends TestFmwk { vtz_new = VTimeZone.create(reader); reader.close(); + // Write out VTIMEZONE one more time + ByteArrayOutputStream baos1 = new ByteArrayOutputStream(); + OutputStreamWriter writer1 = new OutputStreamWriter(baos1); + vtz_new.write(writer1); + writer1.close(); + byte[] vtzdata1 = baos1.toByteArray(); + + // Make sure VTIMEZONE data is exactly same with the first one + if (vtzdata.length != vtzdata1.length) { + errln("FAIL: different VTIMEZONE data length"); + } + for (int j = 0; j < vtzdata.length; j++) { + if (vtzdata[j] != vtzdata1[j]) { + errln("FAIL: different VTIMEZONE data"); + break; + } + } } catch (IOException ioe) { errln("FAIL: IO error while writing/reading VTIMEZONE data"); } @@ -969,6 +1067,13 @@ public class TimeZoneRuleTest extends TestFmwk { tzt1 = stz1.getNextTransition(time1, false); if (tzt1 == null) { errln("FAIL: Non-null transition must be returned by getNextTranstion for SimpleTimeZone with a DST rule"); + } else { + String str = tzt1.toString(); + if (str == null || str.length() == 0) { + errln("FAIL: TimeZoneTransition#toString returns null or empty string"); + } else { + logln(str); + } } tzt1 = stz1.getPreviousTransition(time1, false); if (tzt1 == null) { @@ -992,6 +1097,112 @@ public class TimeZoneRuleTest extends TestFmwk { errln("FAIL: Bad transition returned by SimpleTimeZone#getNextTransition"); } } + + /* + * API coverage test for VTimeZone + */ + public void TestVTimeZoneCoverage() { + final String TZID = "Europe/Moscow"; + BasicTimeZone otz = (BasicTimeZone)TimeZone.getTimeZone(TZID); + VTimeZone vtz = VTimeZone.create(TZID); + + // getOffset(era, year, month, day, dayOfWeek, milliseconds) + int offset1 = otz.getOffset(GregorianCalendar.AD, 2007, Calendar.JULY, 1, Calendar.SUNDAY, 0); + int offset2 = vtz.getOffset(GregorianCalendar.AD, 2007, Calendar.JULY, 1, Calendar.SUNDAY, 0); + if (offset1 != offset2) { + errln("FAIL: getOffset(int,int,int,int,int,int) returned different results in VTimeZone and OlsonTimeZone"); + } + + // getOffset(date, local, offsets) + int[] offsets1 = new int[2]; + int[] offsets2 = new int[2]; + long t = System.currentTimeMillis(); + otz.getOffset(t, false, offsets1); + vtz.getOffset(t, false, offsets2); + if (offsets1[0] != offsets2[0] || offsets1[1] != offsets2[1]) { + errln("FAIL: getOffset(long,boolean,int[]) returned different results in VTimeZone and OlsonTimeZone"); + } + + // getRawOffset + if (otz.getRawOffset() != vtz.getRawOffset()) { + errln("FAIL: getRawOffset returned different results in VTimeZone and OlsonTimeZone"); + } + + // inDaylightTime + Date d = new Date(); + if (otz.inDaylightTime(d) != vtz.inDaylightTime(d)) { + errln("FAIL: inDaylightTime returned different results in VTimeZone and OlsonTimeZone"); + } + + // useDaylightTime + if (otz.useDaylightTime() != vtz.useDaylightTime()) { + errln("FAIL: useDaylightTime returned different results in VTimeZone and OlsonTimeZone"); + } + + // setRawOffset + final int RAW = -10*HOUR; + VTimeZone tmpvtz = (VTimeZone)vtz.clone(); + tmpvtz.setRawOffset(RAW); + if (tmpvtz.getRawOffset() != RAW) { + logln("setRawOffset is implemented"); + } + + // hasSameRules + boolean bSame = otz.hasSameRules(vtz); + logln("OlsonTimeZone#hasSameRules(VTimeZone) should return false always for now - actual: " + bSame); + + // getTZURL/setTZURL + final String TZURL = "http://icu-project.org/timezone"; + String tzurl = vtz.getTZURL(); + if (tzurl != null) { + errln("FAIL: getTZURL returned non-null value"); + } + vtz.setTZURL(TZURL); + tzurl = vtz.getTZURL(); + if (!TZURL.equals(tzurl)) { + errln("FAIL: URL returned by getTZURL does not match the one set by setTZURL"); + } + + // getLastModified/setLastModified + Date lastmod = vtz.getLastModified(); + if (lastmod != null) { + errln("FAIL: getLastModified returned non-null value"); + } + Date newdate = new Date(); + vtz.setLastModified(newdate); + lastmod = vtz.getLastModified(); + if (!newdate.equals(lastmod)) { + errln("FAIL: Date returned by getLastModified does not match the one set by setLastModified"); + } + + // getNextTransition/getPreviousTransition + long base = getUTCMillis(2007, Calendar.JULY, 1); + TimeZoneTransition tzt1 = otz.getNextTransition(base, true); + TimeZoneTransition tzt2 = vtz.getNextTransition(base, true); + if (tzt1.equals(tzt2)) { + errln("FAIL: getNextTransition returned different results in VTimeZone and OlsonTimeZone"); + } + tzt1 = otz.getPreviousTransition(base, false); + tzt2 = vtz.getPreviousTransition(base, false); + if (tzt1.equals(tzt2)) { + errln("FAIL: getPreviousTransition returned different results in VTimeZone and OlsonTimeZone"); + } + + // hasEquivalentTransitions + long time1 = getUTCMillis(1950, Calendar.JANUARY, 1); + long time2 = getUTCMillis(2020, Calendar.JANUARY, 1); + if (!vtz.hasEquivalentTransitions(otz, time1, time2)) { + errln("FAIL: hasEquivalentTransitons returned false for the same time zone"); + } + + // getTimeZoneRules + TimeZoneRule[] rulesetAll = vtz.getTimeZoneRules(); + TimeZoneRule[] ruleset1 = vtz.getTimeZoneRules(time1); + TimeZoneRule[] ruleset2 = vtz.getTimeZoneRules(time2); + if (rulesetAll.length < ruleset1.length || ruleset1.length < ruleset2.length) { + errln("FAIL: Number of rules returned by getRules is invalid"); + } + } // Internal utility methods ----------------------------------------- diff --git a/icu4j/src/com/ibm/icu/util/RuleBasedTimeZone.java b/icu4j/src/com/ibm/icu/util/RuleBasedTimeZone.java index c7b1fec562..2ba2913fa9 100644 --- a/icu4j/src/com/ibm/icu/util/RuleBasedTimeZone.java +++ b/icu4j/src/com/ibm/icu/util/RuleBasedTimeZone.java @@ -451,6 +451,22 @@ public class RuleBasedTimeZone extends BasicTimeZone { return result; } + /** + * {@inheritDoc} + * @draft ICU 3.8 + * @provisional This API might change or be removed in a future release. + */ + public Object clone() { + RuleBasedTimeZone other = (RuleBasedTimeZone)super.clone(); + if (historicRules != null) { + other.historicRules = (List)((ArrayList)historicRules).clone(); // rules are immutable + } + if (finalRules != null) { + other.finalRules = (AnnualTimeZoneRule[])finalRules.clone(); + } + return other; + } + // private stuff /* diff --git a/icu4j/src/com/ibm/icu/util/VTimeZone.java b/icu4j/src/com/ibm/icu/util/VTimeZone.java index dbd50470ac..ea930a1cc8 100644 --- a/icu4j/src/com/ibm/icu/util/VTimeZone.java +++ b/icu4j/src/com/ibm/icu/util/VTimeZone.java @@ -214,6 +214,7 @@ public class VTimeZone extends BasicTimeZone { } } else { bw.write(line); + bw.write(NEWLINE); } } bw.flush(); @@ -339,6 +340,17 @@ public class VTimeZone extends BasicTimeZone { return tz.getTimeZoneRules(start); } + /** + * {@inheritDoc} + * @draft ICU 3.8 + * @provisional This API might change or be removed in a future release. + */ + public Object clone() { + VTimeZone other = (VTimeZone)super.clone(); + other.tz = (BasicTimeZone)tz.clone(); + return other; + } + // private stuff ------------------------------------------------------ private BasicTimeZone tz;