ICU-8753 Fix ICU4J Calendar.add() to handle change in ZONE_OFFSET
X-SVN-Rev: 30660
This commit is contained in:
parent
684bbcecfe
commit
99fa6505ef
@ -2995,7 +2995,8 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
|
||||
|
||||
// We handle most fields in the same way. The algorithm is to add
|
||||
// a computed amount of millis to the current millis. The only
|
||||
// wrinkle is with DST -- for some fields, like the DAY_OF_MONTH,
|
||||
// wrinkle is with DST (and/or a change to the zone's UTC offset, which
|
||||
// we'll include with DST) -- for some fields, like the DAY_OF_MONTH,
|
||||
// we don't want the HOUR to shift due to changes in DST. If the
|
||||
// result of the add operation is to move from DST to Standard, or
|
||||
// vice versa, we need to adjust by an hour forward or back,
|
||||
@ -3081,14 +3082,14 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
|
||||
int dst = 0;
|
||||
int hour = 0;
|
||||
if (keepHourInvariant) {
|
||||
dst = get(DST_OFFSET);
|
||||
dst = get(DST_OFFSET) + get(ZONE_OFFSET);
|
||||
hour = internalGet(HOUR_OF_DAY);
|
||||
}
|
||||
|
||||
setTimeInMillis(getTimeInMillis() + delta);
|
||||
|
||||
if (keepHourInvariant) {
|
||||
dst -= get(DST_OFFSET);
|
||||
dst -= get(DST_OFFSET) + get(ZONE_OFFSET);
|
||||
if (dst != 0) {
|
||||
// We have done an hour-invariant adjustment but the
|
||||
// DST offset has altered. We adjust millis to keep
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2000-2009, International Business Machines Corporation and *
|
||||
* Copyright (C) 2000-2009,2011 International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
@ -754,6 +754,56 @@ public class CompatibilityTest extends com.ibm.icu.dev.test.TestFmwk {
|
||||
y + "/" + (m+1) + "/" + d);
|
||||
}
|
||||
|
||||
// Verify that add works across ZONE_OFFSET and DST_OFFSET transitions
|
||||
public void TestAddAcrossOffsetTransitions() {
|
||||
class TransitionItem {
|
||||
private String zoneName;
|
||||
private int year;
|
||||
private int month;
|
||||
private int day;
|
||||
private int hour;
|
||||
TransitionItem(String zn, int y, int m, int d, int h) {
|
||||
zoneName = zn;
|
||||
year = y;
|
||||
month = m;
|
||||
day = d;
|
||||
hour = h;
|
||||
}
|
||||
public String getZoneName() { return zoneName; }
|
||||
public int getYear() { return year; }
|
||||
public int getMonth() { return month; }
|
||||
public int getDay() { return day; }
|
||||
public int getHour() { return hour; }
|
||||
}
|
||||
final TransitionItem[] transitionItems = {
|
||||
new TransitionItem( "America/Caracas", 2007, Calendar.DECEMBER, 8, 10 ), // day before change in ZONE_OFFSET
|
||||
new TransitionItem( "US/Pacific", 2011, Calendar.MARCH, 12, 10 ), // day before change in DST_OFFSET
|
||||
};
|
||||
for (TransitionItem transitionItem: transitionItems) {
|
||||
String zoneName = transitionItem.getZoneName();
|
||||
Calendar cal = null;
|
||||
try {
|
||||
cal = Calendar.getInstance(TimeZone.getTimeZone(zoneName), Locale.ENGLISH);
|
||||
} catch (Exception e) {
|
||||
errln("Error: Calendar.getInstance fails for zone " + zoneName);
|
||||
continue;
|
||||
}
|
||||
int itemHour = transitionItem.getHour();
|
||||
cal.set( transitionItem.getYear(), transitionItem.getMonth(), transitionItem.getDay(), itemHour, 0 );
|
||||
cal.add( Calendar.DATE, 1 );
|
||||
int hr = cal.get( Calendar.HOUR_OF_DAY );
|
||||
if ( hr != itemHour ) {
|
||||
errln("Error: Calendar.add produced wrong hour " + hr + " when adding day across transition for zone " + zoneName);
|
||||
} else {
|
||||
cal.add( Calendar.DATE, -1 );
|
||||
hr = cal.get( Calendar.HOUR_OF_DAY );
|
||||
if ( hr != itemHour ) {
|
||||
errln("Error: Calendar.add produced wrong hour " + hr + " when subtracting day across transition for zone " + zoneName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that setting fields works. This test fails when an exception is thrown.
|
||||
public void TestFieldSet4781() {
|
||||
try {
|
||||
|
Loading…
Reference in New Issue
Block a user