The failing test cases:
src/test/java/org/joda/time/TestDateTimeZoneCutover.java:1097-1102
public void testWithSecondOfMinuteInDstChange() {
DateTime dateTime = new DateTime("2010-10-31T02:30:10.123+02:00", ZONE_PARIS);
assertEquals("2010-10-31T02:30:10.123+02:00", dateTime.toString());
DateTime test = dateTime.withSecondOfMinute(0);
assertEquals("2010-10-31T02:30:00.123+02:00", test.toString()); // <-- TC fails here
}
src/test/java/org/joda/time/TestDateTimeZoneCutover.java:1090-1095
public void testWithMinuteOfHourInDstChange() {
DateTime dateTime = new DateTime("2010-10-31T02:30:10.123+02:00", ZONE_PARIS);
assertEquals("2010-10-31T02:30:10.123+02:00", dateTime.toString());
DateTime test = dateTime.withMinuteOfHour(0);
assertEquals("2010-10-31T02:00:10.123+02:00", test.toString()); // <-- TC fails here
}
src/test/java/org/joda/time/TestDateTimeZoneCutover.java:1063-1081
public void testWithMinuteOfHourInDstChange_mockZone() {
DateTime cutover = new DateTime(2010, 10, 31, 1, 15, DateTimeZone.forOffsetHoursMinutes(0, 30));
assertEquals("2010-10-31T01:15:00.000+00:30", cutover.toString());
DateTimeZone halfHourZone = new MockZone(cutover.getMillis(), 3600000, -1800);
DateTime pre = new DateTime(2010, 10, 31, 1, 0, halfHourZone);
assertEquals("2010-10-31T01:00:00.000+01:00", pre.toString());
DateTime post = new DateTime(2010, 10, 31, 1, 59, halfHourZone);
assertEquals("2010-10-31T01:59:00.000+00:30", post.toString());
DateTime testPre1 = pre.withMinuteOfHour(30);
assertEquals("2010-10-31T01:30:00.000+01:00", testPre1.toString()); // retain offset // <-- TC fails here
DateTime testPre2 = pre.withMinuteOfHour(50);
assertEquals("2010-10-31T01:50:00.000+00:30", testPre2.toString());
DateTime testPost1 = post.withMinuteOfHour(30);
assertEquals("2010-10-31T01:30:00.000+00:30", testPost1.toString()); // retain offset
DateTime testPost2 = post.withMinuteOfHour(10);
assertEquals("2010-10-31T01:10:00.000+01:00", testPost2.toString());
}
src/test/java/org/joda/time/TestDateTimeZoneCutover.java:1153-1170
public void testBug2182444_usCentral() {
Chronology chronUSCentral = GregorianChronology.getInstance(DateTimeZone.forID("US/Central"));
Chronology chronUTC = GregorianChronology.getInstance(DateTimeZone.UTC);
DateTime usCentralStandardInUTC = new DateTime(2008, 11, 2, 7, 0, 0, 0, chronUTC);
DateTime usCentralDaylightInUTC = new DateTime(2008, 11, 2, 6, 0, 0, 0, chronUTC);
assertTrue("Should be standard time", chronUSCentral.getZone().isStandardOffset(usCentralStandardInUTC.getMillis()));
assertFalse("Should be daylight time", chronUSCentral.getZone().isStandardOffset(usCentralDaylightInUTC.getMillis()));
DateTime usCentralStandardInUSCentral = usCentralStandardInUTC.toDateTime(chronUSCentral);
DateTime usCentralDaylightInUSCentral = usCentralDaylightInUTC.toDateTime(chronUSCentral);
assertEquals(1, usCentralStandardInUSCentral.getHourOfDay());
assertEquals(usCentralStandardInUSCentral.getHourOfDay(), usCentralDaylightInUSCentral.getHourOfDay());
assertTrue(usCentralStandardInUSCentral.getMillis() != usCentralDaylightInUSCentral.getMillis());
assertEquals(usCentralStandardInUSCentral, usCentralStandardInUSCentral.withHourOfDay(1)); // <-- TC fails here
assertEquals(usCentralStandardInUSCentral.getMillis() + 3, usCentralStandardInUSCentral.withMillisOfSecond(3).getMillis());
assertEquals(usCentralDaylightInUSCentral, usCentralDaylightInUSCentral.withHourOfDay(1));
assertEquals(usCentralDaylightInUSCentral.getMillis() + 3, usCentralDaylightInUSCentral.withMillisOfSecond(3).getMillis());
}
src/test/java/org/joda/time/TestDateTimeZoneCutover.java:1104-1109
public void testWithMillisOfSecondInDstChange_Paris_summer() {
DateTime dateTime = new DateTime("2010-10-31T02:30:10.123+02:00", ZONE_PARIS);
assertEquals("2010-10-31T02:30:10.123+02:00", dateTime.toString());
DateTime test = dateTime.withMillisOfSecond(0);
assertEquals("2010-10-31T02:30:10.000+02:00", test.toString()); // <-- TC fails here
}
src/test/java/org/joda/time/TestDateTimeZoneCutover.java:1083-1088
public void testWithHourOfDayInDstChange() {
DateTime dateTime = new DateTime("2010-10-31T02:30:10.123+02:00", ZONE_PARIS);
assertEquals("2010-10-31T02:30:10.123+02:00", dateTime.toString());
DateTime test = dateTime.withHourOfDay(2);
assertEquals("2010-10-31T02:30:10.123+02:00", test.toString()); // <-- TC fails here
}
src/test/java/org/joda/time/TestDateTimeZoneCutover.java:1125-1130
public void testWithMillisOfSecondInDstChange_NewYork_winter() {
DateTime dateTime = new DateTime("2007-11-04T01:30:00.123-05:00", ZONE_NEW_YORK);
assertEquals("2007-11-04T01:30:00.123-05:00", dateTime.toString());
DateTime test = dateTime.withMillisOfSecond(0);
assertEquals("2007-11-04T01:30:00.000-05:00", test.toString()); // <-- TC fails here
}
src/test/java/org/joda/time/TestDateTimeZoneCutover.java:1172-1189
public void testBug2182444_ausNSW() {
Chronology chronAusNSW = GregorianChronology.getInstance(DateTimeZone.forID("Australia/NSW"));
Chronology chronUTC = GregorianChronology.getInstance(DateTimeZone.UTC);
DateTime australiaNSWStandardInUTC = new DateTime(2008, 4, 5, 16, 0, 0, 0, chronUTC);
DateTime australiaNSWDaylightInUTC = new DateTime(2008, 4, 5, 15, 0, 0, 0, chronUTC);
assertTrue("Should be standard time", chronAusNSW.getZone().isStandardOffset(australiaNSWStandardInUTC.getMillis()));
assertFalse("Should be daylight time", chronAusNSW.getZone().isStandardOffset(australiaNSWDaylightInUTC.getMillis()));
DateTime australiaNSWStandardInAustraliaNSW = australiaNSWStandardInUTC.toDateTime(chronAusNSW);
DateTime australiaNSWDaylightInAusraliaNSW = australiaNSWDaylightInUTC.toDateTime(chronAusNSW);
assertEquals(2, australiaNSWStandardInAustraliaNSW.getHourOfDay());
assertEquals(australiaNSWStandardInAustraliaNSW.getHourOfDay(), australiaNSWDaylightInAusraliaNSW.getHourOfDay());
assertTrue(australiaNSWStandardInAustraliaNSW.getMillis() != australiaNSWDaylightInAusraliaNSW.getMillis());
assertEquals(australiaNSWStandardInAustraliaNSW, australiaNSWStandardInAustraliaNSW.withHourOfDay(2));
assertEquals(australiaNSWStandardInAustraliaNSW.getMillis() + 3, australiaNSWStandardInAustraliaNSW.withMillisOfSecond(3).getMillis());
assertEquals(australiaNSWDaylightInAusraliaNSW, australiaNSWDaylightInAusraliaNSW.withHourOfDay(2)); // <-- TC fails here
assertEquals(australiaNSWDaylightInAusraliaNSW.getMillis() + 3, australiaNSWDaylightInAusraliaNSW.withMillisOfSecond(3).getMillis());
}
The faulty code:
Line is covered but NOT in slice
Line is covered and in slice
Line is in slice but NOT covered
src/main/java/org/joda/time/chrono/ZonedChronology.java:428-438
public long add(long instant, int value) {
if (iTimeField) {
int offset = getOffsetToAdd(instant);
long localInstant = iField.add(instant + offset, value);
return localInstant - offset;
} else {
long localInstant = iZone.convertUTCToLocal(instant);
localInstant = iField.add(localInstant, value);
return iZone.convertLocalToUTC(localInstant, false); //<-- BUG!!
}
}
src/main/java/org/joda/time/chrono/ZonedChronology.java:440-450
public long add(long instant, long value) {
if (iTimeField) {
int offset = getOffsetToAdd(instant);
long localInstant = iField.add(instant + offset, value);
return localInstant - offset;
} else {
long localInstant = iZone.convertUTCToLocal(instant);
localInstant = iField.add(localInstant, value);
return iZone.convertLocalToUTC(localInstant, false); //<-- BUG!!
}
}
src/main/java/org/joda/time/chrono/ZonedChronology.java:452-462
public long addWrapField(long instant, int value) {
if (iTimeField) {
int offset = getOffsetToAdd(instant);
long localInstant = iField.addWrapField(instant + offset, value);
return localInstant - offset;
} else {
long localInstant = iZone.convertUTCToLocal(instant);
localInstant = iField.addWrapField(localInstant, value);
return iZone.convertLocalToUTC(localInstant, false); //<-- BUG!!
}
}
src/main/java/org/joda/time/chrono/ZonedChronology.java:464-475
public long set(long instant, int value) {
long localInstant = iZone.convertUTCToLocal(instant);
localInstant = iField.set(localInstant, value);
long result = iZone.convertLocalToUTC(localInstant, false); //<-- BUG!!
if (get(result) != value) {
throw new IllegalFieldValueException(iField.getType(), new Integer(value),
"Illegal instant due to time zone offset transition: " +
DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS").print(new Instant(localInstant)) +
" (" + iZone.getID() + ")");
}
return result;
}
src/main/java/org/joda/time/chrono/ZonedChronology.java:477-482
public long set(long instant, String text, Locale locale) {
// cannot verify that new value stuck because set may be lenient
long localInstant = iZone.convertUTCToLocal(instant);
localInstant = iField.set(localInstant, text, locale);
return iZone.convertLocalToUTC(localInstant, false); //<-- BUG!!
}
src/main/java/org/joda/time/chrono/ZonedChronology.java:520-530
public long roundFloor(long instant) {
if (iTimeField) {
int offset = getOffsetToAdd(instant);
instant = iField.roundFloor(instant + offset);
return instant - offset;
} else {
long localInstant = iZone.convertUTCToLocal(instant);
localInstant = iField.roundFloor(localInstant);
return iZone.convertLocalToUTC(localInstant, false); //<-- BUG!!
}
}
src/main/java/org/joda/time/chrono/ZonedChronology.java:532-542
public long roundCeiling(long instant) {
if (iTimeField) {
int offset = getOffsetToAdd(instant);
instant = iField.roundCeiling(instant + offset);
return instant - offset;
} else {
long localInstant = iZone.convertUTCToLocal(instant);
localInstant = iField.roundCeiling(localInstant);
return iZone.convertLocalToUTC(localInstant, false); //<-- BUG!!
}
}
src/main/java/org/joda/time/field/LenientDateTimeField.java:69-76
public long set(long instant, int value) {
// lenient needs to handle time zone chronologies
// so we do the calculation using local milliseconds
long localInstant = iBase.getZone().convertUTCToLocal(instant);
long difference = FieldUtils.safeSubtract(value, get(instant));
localInstant = getType().getField(iBase.withUTC()).add(localInstant, difference);
return iBase.getZone().convertLocalToUTC(localInstant, false, instant); //<-- BUG!!
}