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:
parent
a6fba24d1a
commit
af0eef9988
@ -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
|
-1; // used to specify that date is invalid
|
||||||
private static final long DAY_MILLISECONDS = 24 * 60 * 60 * 1000;
|
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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a Date, converts it into a double representing its internal Excel representation,
|
* 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.
|
* 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;
|
) / ( double ) DAY_MILLISECONDS;
|
||||||
calStart = dayStart(calStart);
|
calStart = dayStart(calStart);
|
||||||
|
|
||||||
return fraction + ( double ) absoluteDay(calStart)
|
double value = fraction + absoluteDay(calStart);
|
||||||
- CAL_1900_ABSOLUTE;
|
|
||||||
|
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
|
* @param cal the Calendar
|
||||||
* @exception IllegalArgumentException if date is invalid
|
* @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.
|
* @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.
|
* @exception IllegalArgumentException if year is outside of range.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private static int daysInPriorYears(int yr)
|
private static int daysInPriorYears(int yr)
|
||||||
{
|
{
|
||||||
if (yr < 1601)
|
if (yr < 1900) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException(
|
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
|
int yr1 = yr - 1;
|
||||||
+ y / 4 // plus julian leap days in prior years
|
int leapDays = yr1 / 4 // plus julian leap days in prior years
|
||||||
- y / 100 // minus prior century years
|
- yr1 / 100 // minus prior century years
|
||||||
+ y / 400; // plus years divisible by 400
|
+ yr1 / 400 // plus years divisible by 400
|
||||||
|
- 460; // leap days in previous 1900 years
|
||||||
return days;
|
|
||||||
|
return 365 * (yr - 1900) + leapDays;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set HH:MM:SS fields of cal to 00:00:00:000
|
// set HH:MM:SS fields of cal to 00:00:00:000
|
||||||
private static Calendar dayStart(final Calendar cal)
|
private static Calendar dayStart(final Calendar cal)
|
||||||
{
|
{
|
||||||
|
@ -42,6 +42,12 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
|||||||
public class TestHSSFDateUtil
|
public class TestHSSFDateUtil
|
||||||
extends TestCase
|
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)
|
public TestHSSFDateUtil(String s)
|
||||||
{
|
{
|
||||||
super(s);
|
super(s);
|
||||||
@ -308,9 +314,37 @@ public class TestHSSFDateUtil
|
|||||||
assertTrue(HSSFDateUtil.isCellDateFormatted(cell));
|
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) {
|
public static void main(String [] args) {
|
||||||
System.out
|
System.out
|
||||||
.println("Testing org.apache.poi.hssf.usermodel.TestHSSFDateUtil");
|
.println("Testing org.apache.poi.hssf.usermodel.TestHSSFDateUtil");
|
||||||
junit.textui.TestRunner.run(TestHSSFDateUtil.class);
|
junit.textui.TestRunner.run(TestHSSFDateUtil.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user