Adding Niall's fix for LANG-59 - an edge case in date truncation - and his enhancement

for the unit test that was there. 

git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/lang/trunk@424192 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Henri Yandell 2006-07-21 05:47:07 +00:00
parent c62bd30765
commit 9cbf70d822
2 changed files with 123 additions and 9 deletions

View File

@ -621,6 +621,51 @@ private static void modify(Calendar val, int field, boolean round) {
throw new ArithmeticException("Calendar value too large for accurate calculations");
}
if (field == Calendar.MILLISECOND) {
return;
}
// ----------------- Fix for LANG-59 ---------------------- START ---------------
// see http://issues.apache.org/jira/browse/LANG-59
//
// Manually truncate milliseconds, seconds and minutes, rather than using
// Calendar methods.
Date date = val.getTime();
long time = date.getTime();
boolean done = false;
// truncate milliseconds
int millisecs = val.get(Calendar.MILLISECOND);
if (!round || millisecs < 500) {
time = time - millisecs;
if (field == Calendar.SECOND) {
done = true;
}
}
// truncate seconds
int seconds = val.get(Calendar.SECOND);
if (!done && (!round || seconds < 30)) {
time = time - (seconds * 1000L);
if (field == Calendar.MINUTE) {
done = true;
}
}
// truncate minutes
int minutes = val.get(Calendar.MINUTE);
if (!done && (!round || minutes < 30)) {
time = time - (minutes * 60000L);
}
// reset time
if (date.getTime() != time) {
date.setTime(time);
val.setTime(date);
}
// ----------------- Fix for LANG-59 ----------------------- END ----------------
boolean roundUp = false;
for (int i = 0; i < fields.length; i++) {
for (int j = 0; j < fields[i].length; j++) {
@ -689,7 +734,9 @@ private static void modify(Calendar val, int field, boolean round) {
roundUp = offset > ((max - min) / 2);
}
//We need to remove this field
val.set(fields[i][0], val.get(fields[i][0]) - offset);
if (offset != 0) {
val.set(fields[i][0], val.get(fields[i][0]) - offset);
}
}
throw new IllegalArgumentException("The field " + field + " is not supported");

View File

@ -882,6 +882,81 @@ public void testTruncate() throws Exception {
assertEquals(0, cal.get(Calendar.HOUR));
}
/**
* Tests for LANG-59
*
* see http://issues.apache.org/jira/browse/LANG-59
*/
public void testTruncateLang59() throws Exception {
// Set TimeZone to Mountain Time
TimeZone MST_MDT = TimeZone.getTimeZone("MST7MDT");
TimeZone.setDefault(MST_MDT);
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
format.setTimeZone(MST_MDT);
Date oct31_01MDT = new Date(1099206000000L);
Date oct31MDT = new Date(oct31_01MDT.getTime() - 3600000L); // - 1 hour
Date oct31_01_02MDT = new Date(oct31_01MDT.getTime() + 120000L); // + 2 minutes
Date oct31_01_02_03MDT = new Date(oct31_01_02MDT.getTime() + 3000L); // + 3 seconds
Date oct31_01_02_03_04MDT = new Date(oct31_01_02_03MDT.getTime() + 4L); // + 4 milliseconds
assertEquals("Check 00:00:00.000", "2004-10-31 00:00:00.000 MDT", format.format(oct31MDT));
assertEquals("Check 01:00:00.000", "2004-10-31 01:00:00.000 MDT", format.format(oct31_01MDT));
assertEquals("Check 01:02:00.000", "2004-10-31 01:02:00.000 MDT", format.format(oct31_01_02MDT));
assertEquals("Check 01:02:03.000", "2004-10-31 01:02:03.000 MDT", format.format(oct31_01_02_03MDT));
assertEquals("Check 01:02:03.004", "2004-10-31 01:02:03.004 MDT", format.format(oct31_01_02_03_04MDT));
// ------- Demonstrate Problem -------
Calendar gval = Calendar.getInstance();
gval.setTime(new Date(oct31_01MDT.getTime()));
gval.set(Calendar.MINUTE, gval.get(Calendar.MINUTE)); // set minutes to the same value
assertEquals("Demonstrate Problem", gval.getTime().getTime(), oct31_01MDT.getTime() + 3600000L);
// ---------- Test Truncate ----------
assertEquals("Truncate Calendar.MILLISECOND",
oct31_01_02_03_04MDT, DateUtils.truncate(oct31_01_02_03_04MDT, Calendar.MILLISECOND));
assertEquals("Truncate Calendar.SECOND",
oct31_01_02_03MDT, DateUtils.truncate(oct31_01_02_03_04MDT, Calendar.SECOND));
assertEquals("Truncate Calendar.MINUTE",
oct31_01_02MDT, DateUtils.truncate(oct31_01_02_03_04MDT, Calendar.MINUTE));
assertEquals("Truncate Calendar.HOUR_OF_DAY",
oct31_01MDT, DateUtils.truncate(oct31_01_02_03_04MDT, Calendar.HOUR_OF_DAY));
assertEquals("Truncate Calendar.HOUR",
oct31_01MDT, DateUtils.truncate(oct31_01_02_03_04MDT, Calendar.HOUR));
assertEquals("Truncate Calendar.DATE",
oct31MDT, DateUtils.truncate(oct31_01_02_03_04MDT, Calendar.DATE));
// ---------- Test Round (down) ----------
assertEquals("Round Calendar.MILLISECOND",
oct31_01_02_03_04MDT, DateUtils.round(oct31_01_02_03_04MDT, Calendar.MILLISECOND));
assertEquals("Round Calendar.SECOND",
oct31_01_02_03MDT, DateUtils.round(oct31_01_02_03_04MDT, Calendar.SECOND));
assertEquals("Round Calendar.MINUTE",
oct31_01_02MDT, DateUtils.round(oct31_01_02_03_04MDT, Calendar.MINUTE));
assertEquals("Round Calendar.HOUR_OF_DAY",
oct31_01MDT, DateUtils.round(oct31_01_02_03_04MDT, Calendar.HOUR_OF_DAY));
assertEquals("Round Calendar.HOUR",
oct31_01MDT, DateUtils.round(oct31_01_02_03_04MDT, Calendar.HOUR));
assertEquals("Round Calendar.DATE",
oct31MDT, DateUtils.round(oct31_01_02_03_04MDT, Calendar.DATE));
// restore default time zone
TimeZone.setDefault(defaultZone);
}
/**
* Tests the iterator exceptions
*/
@ -978,14 +1053,6 @@ public void testMonthIterator() throws Exception {
dateParser.parse("December 2, 2001"));
}
// Tests LANG-59
public void testLang59() throws Exception {
// truncate 2004-10-31 01:00:00 MDT
Date oct31_01MDT = new Date(1099206000000L);
Date result = DateUtils.truncate(oct31_01MDT, Calendar.HOUR_OF_DAY);
assertEquals(oct31_01MDT, result);
}
/**
* This checks that this is a 7 element iterator of Calendar objects
* that are dates (no time), and exactly 1 day spaced after each other.