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:
parent
c62bd30765
commit
9cbf70d822
|
@ -621,6 +621,51 @@ public class DateUtils {
|
|||
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 @@ public class DateUtils {
|
|||
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");
|
||||
|
||||
|
|
|
@ -882,6 +882,81 @@ public class DateUtilsTest extends TestCase {
|
|||
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 class DateUtilsTest extends TestCase {
|
|||
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.
|
||||
|
|
Loading…
Reference in New Issue