Fix from Pavel Krupets for Excel Bug Date (1900/2/29)

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@579194 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2007-09-25 10:52:30 +00:00
parent 19e4ecea6e
commit 994cc7c045
2 changed files with 59 additions and 23 deletions

View File

@ -43,13 +43,10 @@ public class HSSFDateUtil
{
}
private static final int BAD_DATE =
private static final int BAD_DATE =
-1; // used to specify that date is invalid
private static final long DAY_MILLISECONDS = 24 * 60 * 60 * 1000;
private static final double CAL_1900_ABSOLUTE =
( double ) absoluteDay(new GregorianCalendar(1900, Calendar
.JANUARY, 1)) - 2.0;
private static final long DAY_MILLISECONDS = 24 * 60 * 60 * 1000;
/**
* Given a Date, converts it into a double representing its internal Excel representation,
* which is the number of days since 1/1/1900. Fractional days represent hours, minutes, and seconds.
@ -84,8 +81,13 @@ public class HSSFDateUtil
) / ( double ) DAY_MILLISECONDS;
calStart = dayStart(calStart);
return fraction + ( double ) absoluteDay(calStart)
- CAL_1900_ABSOLUTE;
double value = fraction + absoluteDay(calStart);
if (value >= 60) {
value += 1;
}
return value;
}
}
@ -287,9 +289,9 @@ public class HSSFDateUtil
}
/**
* Given a Calendar, return the number of days since 1600/12/31.
* Given a Calendar, return the number of days since 1900/12/31.
*
* @return days number of days since 1600/12/31
* @return days number of days since 1900/12/31
* @param cal the Calendar
* @exception IllegalArgumentException if date is invalid
*/
@ -301,29 +303,29 @@ public class HSSFDateUtil
}
/**
* Return the number of days in prior years since 1601
* Return the number of days in prior years since 1900
*
* @return days number of days in years prior to yr.
* @param yr a year (1600 < yr < 4000)
* @param yr a year (1900 < yr < 4000)
* @exception IllegalArgumentException if year is outside of range.
*/
private static int daysInPriorYears(int yr)
{
if (yr < 1601)
{
if (yr < 1900) {
throw new IllegalArgumentException(
"'year' must be 1601 or greater");
"'year' must be 1900 or greater");
}
int y = yr - 1601;
int days = 365 * y // days in prior years
+ y / 4 // plus julian leap days in prior years
- y / 100 // minus prior century years
+ y / 400; // plus years divisible by 400
return days;
int yr1 = yr - 1;
int leapDays = yr1 / 4 // plus julian leap days in prior years
- yr1 / 100 // minus prior century years
+ yr1 / 400 // plus years divisible by 400
- 460; // leap days in previous 1900 years
return 365 * (yr - 1900) + leapDays;
}
// set HH:MM:SS fields of cal to 00:00:00:000
private static Calendar dayStart(final Calendar cal)
{

View File

@ -42,6 +42,12 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
public class TestHSSFDateUtil
extends TestCase
{
public static final int CALENDAR_JANUARY = 0;
public static final int CALENDAR_FEBRUARY = 0;
public static final int CALENDAR_MARCH = 0;
public static final int CALENDAR_APRIL = 0;
public TestHSSFDateUtil(String s)
{
super(s);
@ -308,9 +314,37 @@ public class TestHSSFDateUtil
assertTrue(HSSFDateUtil.isCellDateFormatted(cell));
}
public void testDateBug_2Excel() {
assertEquals(59.0, HSSFDateUtil.getExcelDate(createDate(1900, CALENDAR_FEBRUARY, 28)), 0.00001);
assertEquals(61.0, HSSFDateUtil.getExcelDate(createDate(1900, CALENDAR_MARCH, 1)), 0.00001);
assertEquals(37315.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_FEBRUARY, 28)), 0.00001);
assertEquals(37316.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_MARCH, 1)), 0.00001);
assertEquals(37257.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_JANUARY, 1)), 0.00001);
assertEquals(38074.00, HSSFDateUtil.getExcelDate(createDate(2004, CALENDAR_MARCH, 28)), 0.00001);
}
public void testDateBug_2Java() {
assertEquals(createDate(1900, Calendar.FEBRUARY, 28), HSSFDateUtil.getJavaDate(59.0));
assertEquals(createDate(1900, Calendar.MARCH, 1), HSSFDateUtil.getJavaDate(61.0));
assertEquals(createDate(2002, Calendar.FEBRUARY, 28), HSSFDateUtil.getJavaDate(37315.00));
assertEquals(createDate(2002, Calendar.MARCH, 1), HSSFDateUtil.getJavaDate(37316.00));
assertEquals(createDate(2002, Calendar.JANUARY, 1), HSSFDateUtil.getJavaDate(37257.00));
assertEquals(createDate(2004, Calendar.MARCH, 28), HSSFDateUtil.getJavaDate(38074.00));
}
private Date createDate(int year, int month, int day) {
Calendar c = new GregorianCalendar();
c.set(year, month, day, 0, 0, 0);
c.set(Calendar.MILLISECOND, 0);
return c.getTime();
}
public static void main(String [] args) {
System.out
.println("Testing org.apache.poi.hssf.usermodel.TestHSSFDateUtil");
junit.textui.TestRunner.run(TestHSSFDateUtil.class);
}
}