From 39812e6f72b4105e2aede217f1cec2b42224dea1 Mon Sep 17 00:00:00 2001 From: Yoshito Umaoka Date: Fri, 18 Nov 2011 22:30:34 +0000 Subject: [PATCH] ICU-8943 Fixed NPE problem in RuleBasedTimeZone#getOffsets. X-SVN-Rev: 30975 --- .../com/ibm/icu/util/RuleBasedTimeZone.java | 18 +++++++-- .../dev/test/timezone/TimeZoneRuleTest.java | 39 ++++++++++++++++++- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/RuleBasedTimeZone.java b/icu4j/main/classes/core/src/com/ibm/icu/util/RuleBasedTimeZone.java index 83279ac91a6..24798214b1e 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/util/RuleBasedTimeZone.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/util/RuleBasedTimeZone.java @@ -572,7 +572,7 @@ public class RuleBasedTimeZone extends BasicTimeZone { */ private void getOffset(long time, boolean local, int NonExistingTimeOpt, int DuplicatedTimeOpt, int[] offsets) { complete(); - TimeZoneRule rule; + TimeZoneRule rule = null; if (historicTransitions == null) { rule = initialRule; } else { @@ -587,8 +587,10 @@ public class RuleBasedTimeZone extends BasicTimeZone { if (time > tend) { if (finalRules != null) { rule = findRuleInFinal(time, local, NonExistingTimeOpt, DuplicatedTimeOpt); - } else { - // no final rule, use the last rule + } + if (rule == null) { + // no final rules or the given time is before the first transition + // specified by the final rules -> use the last rule rule = (historicTransitions.get(idx)).getTo(); } } else { @@ -638,6 +640,16 @@ public class RuleBasedTimeZone extends BasicTimeZone { } start1 = finalRules[1].getPreviousStart(base, finalRules[0].getRawOffset(), finalRules[0].getDSTSavings(), true); + if (start0 == null || start1 == null) { + if (start0 != null) { + return finalRules[0]; + } else if (start1 != null) { + return finalRules[1]; + } + // Both rules take effect after the given time + return null; + } + return start0.after(start1) ? finalRules[0] : finalRules[1]; } diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneRuleTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneRuleTest.java index 4fb75f924fa..d2f627f10bc 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneRuleTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneRuleTest.java @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 2007-2010, International Business Machines Corporation and * + * Copyright (C) 2007-2011, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -1788,4 +1788,41 @@ public class TimeZoneRuleTest extends TestFmwk { } return true; } + + // Test case for ticket#8943 + // RuleBasedTimeZone#getOffsets throws NPE + public void TestT8943() { + String id = "Ekaterinburg Time"; + String stdName = "Ekaterinburg Standard Time"; + String dstName = "Ekaterinburg Daylight Time"; + + InitialTimeZoneRule initialRule = new InitialTimeZoneRule(stdName, 18000000, 0); + RuleBasedTimeZone rbtz = new RuleBasedTimeZone(id, initialRule); + + DateTimeRule dtRule = new DateTimeRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 10800000, DateTimeRule.WALL_TIME); + AnnualTimeZoneRule atzRule = new AnnualTimeZoneRule(stdName, 18000000, 0, dtRule, 2000, 2010); + rbtz.addTransitionRule(atzRule); + + dtRule = new DateTimeRule(Calendar.MARCH, -1, Calendar.SUNDAY, 7200000, DateTimeRule.WALL_TIME); + atzRule = new AnnualTimeZoneRule(dstName, 18000000, 3600000, dtRule, 2000, 2010); + rbtz.addTransitionRule(atzRule); + + dtRule = new DateTimeRule(Calendar.JANUARY, 1, 0, DateTimeRule.WALL_TIME); + atzRule = new AnnualTimeZoneRule(stdName, 21600000, 0, dtRule, 2011, AnnualTimeZoneRule.MAX_YEAR); + rbtz.addTransitionRule(atzRule); + + atzRule = new AnnualTimeZoneRule(dstName, 21600000, 3600000, dtRule, 2011, AnnualTimeZoneRule.MAX_YEAR); + rbtz.addTransitionRule(atzRule); + + int[] expected = {21600000, 0}; + int[] offsets = new int[2]; + try { + rbtz.getOffset(1293822000000L /* 2010-12-32 19:00:00 UTC */, false, offsets); + if (offsets[0] != expected[0] || offsets[1] != expected[1]) { + errln("Fail: Wrong offsets: " + offsets[0] + "/" + offsets[1] + " Expected: " + expected[0] + "/" + expected[1]); + } + } catch (Exception e) { + errln("Fail: Exception thrown - " + e.getMessage()); + } + } } \ No newline at end of file -- 2.40.0