Support 1904 date windowing, in addition to 1900 date windowing (patch from bug #43551)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@601004 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
9c421d2930
commit
a14b55b6a8
@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
<!-- Don't forget to update status.xml too! -->
|
<!-- Don't forget to update status.xml too! -->
|
||||||
<release version="3.0.2-FINAL" date="2007-??-??">
|
<release version="3.0.2-FINAL" date="2007-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="add">43551 - [PATCH] Support for 1904 date windowing in HSSF (previously only supported 1900 date windowing)</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">41064 - [PATCH] Support for String continue records</action>
|
<action dev="POI-DEVELOPERS" type="add">41064 - [PATCH] Support for String continue records</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">27511 - [PATCH] Support for data validation, via DVRecord and DVALRecord</action>
|
<action dev="POI-DEVELOPERS" type="add">27511 - [PATCH] Support for data validation, via DVRecord and DVALRecord</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">43877 and 39512 - Fix for handling mixed OBJ and CONTINUE records.</action>
|
<action dev="POI-DEVELOPERS" type="fix">43877 and 39512 - Fix for handling mixed OBJ and CONTINUE records.</action>
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
<!-- Don't forget to update changes.xml too! -->
|
<!-- Don't forget to update changes.xml too! -->
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.0.2-FINAL" date="2007-??-??">
|
<release version="3.0.2-FINAL" date="2007-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="add">43551 - [PATCH] Support for 1904 date windowing in HSSF (previously only supported 1900 date windowing)</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">41064 - [PATCH] Support for String continue records</action>
|
<action dev="POI-DEVELOPERS" type="add">41064 - [PATCH] Support for String continue records</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">27511 - [PATCH] Support for data validation, via DVRecord and DVALRecord</action>
|
<action dev="POI-DEVELOPERS" type="add">27511 - [PATCH] Support for data validation, via DVRecord and DVALRecord</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">43877 - Fix for handling mixed OBJ and CONTINUE records</action>
|
<action dev="POI-DEVELOPERS" type="fix">43877 - Fix for handling mixed OBJ and CONTINUE records</action>
|
||||||
|
@ -521,7 +521,7 @@ public class HSSFCell
|
|||||||
*/
|
*/
|
||||||
public void setCellValue(Date value)
|
public void setCellValue(Date value)
|
||||||
{
|
{
|
||||||
setCellValue(HSSFDateUtil.getExcelDate(value));
|
setCellValue(HSSFDateUtil.getExcelDate(value, this.book.isUsing1904DateWindowing()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,6 +35,8 @@ import java.util.GregorianCalendar;
|
|||||||
* @author Glen Stampoultzis (glens at apache.org)
|
* @author Glen Stampoultzis (glens at apache.org)
|
||||||
* @author Dan Sherman (dsherman at isisph.com)
|
* @author Dan Sherman (dsherman at isisph.com)
|
||||||
* @author Hack Kampbjorn (hak at 2mba.dk)
|
* @author Hack Kampbjorn (hak at 2mba.dk)
|
||||||
|
* @author Alex Jacoby (ajacoby at gmail.com)
|
||||||
|
* @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class HSSFDateUtil
|
public class HSSFDateUtil
|
||||||
@ -54,19 +56,26 @@ public class HSSFDateUtil
|
|||||||
* @return Excel representation of Date (-1 if error - test for error by checking for less than 0.1)
|
* @return Excel representation of Date (-1 if error - test for error by checking for less than 0.1)
|
||||||
* @param date the Date
|
* @param date the Date
|
||||||
*/
|
*/
|
||||||
|
public static double getExcelDate(Date date) {
|
||||||
public static double getExcelDate(Date date)
|
return getExcelDate(date, false);
|
||||||
{
|
}
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @return Excel representation of Date (-1 if error - test for error by checking for less than 0.1)
|
||||||
|
* @param date the Date
|
||||||
|
* @param use1904windowing Should 1900 or 1904 date windowing be used?
|
||||||
|
*/
|
||||||
|
public static double getExcelDate(Date date, boolean use1904windowing) {
|
||||||
Calendar calStart = new GregorianCalendar();
|
Calendar calStart = new GregorianCalendar();
|
||||||
|
calStart.setTime(date); // If date includes hours, minutes, and seconds, set them to 0
|
||||||
|
|
||||||
calStart.setTime(
|
if ((!use1904windowing && calStart.get(Calendar.YEAR) < 1900) ||
|
||||||
date); // If date includes hours, minutes, and seconds, set them to 0
|
(use1904windowing && calStart.get(Calendar.YEAR) < 1904))
|
||||||
if (calStart.get(Calendar.YEAR) < 1900)
|
|
||||||
{
|
{
|
||||||
return BAD_DATE;
|
return BAD_DATE;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Because of daylight time saving we cannot use
|
// Because of daylight time saving we cannot use
|
||||||
// date.getTime() - calStart.getTimeInMillis()
|
// date.getTime() - calStart.getTimeInMillis()
|
||||||
// as the difference in milliseconds between 00:00 and 04:00
|
// as the difference in milliseconds between 00:00 and 04:00
|
||||||
@ -81,10 +90,12 @@ public class HSSFDateUtil
|
|||||||
) / ( double ) DAY_MILLISECONDS;
|
) / ( double ) DAY_MILLISECONDS;
|
||||||
calStart = dayStart(calStart);
|
calStart = dayStart(calStart);
|
||||||
|
|
||||||
double value = fraction + absoluteDay(calStart);
|
double value = fraction + absoluteDay(calStart, use1904windowing);
|
||||||
|
|
||||||
if (value >= 60) {
|
if (!use1904windowing && value >= 60) {
|
||||||
value += 1;
|
value++;
|
||||||
|
} else if (use1904windowing) {
|
||||||
|
value--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
@ -92,20 +103,25 @@ public class HSSFDateUtil
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a excel date, converts it into a Date.
|
* Given an Excel date with using 1900 date windowing, and
|
||||||
* Assumes 1900 date windowing.
|
* converts it to a java.util.Date.
|
||||||
*
|
*
|
||||||
* @param date the Excel Date
|
* NOTE: If the default <code>TimeZone</code> in Java uses Daylight
|
||||||
|
* Saving Time then the conversion back to an Excel date may not give
|
||||||
|
* the same value, that is the comparison
|
||||||
|
* <CODE>excelDate == getExcelDate(getJavaDate(excelDate,false))</CODE>
|
||||||
|
* is not always true. For example if default timezone is
|
||||||
|
* <code>Europe/Copenhagen</code>, on 2004-03-28 the minute after
|
||||||
|
* 01:59 CET is 03:00 CEST, if the excel date represents a time between
|
||||||
|
* 02:00 and 03:00 then it is converted to past 03:00 summer time
|
||||||
*
|
*
|
||||||
* @return Java representation of a date (null if error)
|
* @param date The Excel date.
|
||||||
* @see #getJavaDate(double,boolean)
|
* @return Java representation of the date, or null if date is not a valid Excel date
|
||||||
|
* @see java.util.TimeZone
|
||||||
*/
|
*/
|
||||||
|
public static Date getJavaDate(double date) {
|
||||||
public static Date getJavaDate(double date)
|
return getJavaDate(date, false);
|
||||||
{
|
|
||||||
return getJavaDate(date,false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given an Excel date with either 1900 or 1904 date windowing,
|
* Given an Excel date with either 1900 or 1904 date windowing,
|
||||||
* converts it to a java.util.Date.
|
* converts it to a java.util.Date.
|
||||||
@ -142,7 +158,7 @@ public class HSSFDateUtil
|
|||||||
GregorianCalendar calendar = new GregorianCalendar(startYear,0,
|
GregorianCalendar calendar = new GregorianCalendar(startYear,0,
|
||||||
wholeDays + dayAdjust);
|
wholeDays + dayAdjust);
|
||||||
int millisecondsInDay = (int)((date - Math.floor(date)) *
|
int millisecondsInDay = (int)((date - Math.floor(date)) *
|
||||||
(double) DAY_MILLISECONDS + 0.5);
|
DAY_MILLISECONDS + 0.5);
|
||||||
calendar.set(GregorianCalendar.MILLISECOND, millisecondsInDay);
|
calendar.set(GregorianCalendar.MILLISECOND, millisecondsInDay);
|
||||||
return calendar.getTime();
|
return calendar.getTime();
|
||||||
}
|
}
|
||||||
@ -238,7 +254,7 @@ public class HSSFDateUtil
|
|||||||
* Check if a cell contains a date
|
* Check if a cell contains a date
|
||||||
* Since dates are stored internally in Excel as double values
|
* Since dates are stored internally in Excel as double values
|
||||||
* we infer it is a date if it is formatted as such.
|
* we infer it is a date if it is formatted as such.
|
||||||
* @see #isADateFormat(int,string)
|
* @see #isADateFormat(int, String)
|
||||||
* @see #isInternalDateFormat(int)
|
* @see #isInternalDateFormat(int)
|
||||||
*/
|
*/
|
||||||
public static boolean isCellDateFormatted(HSSFCell cell) {
|
public static boolean isCellDateFormatted(HSSFCell cell) {
|
||||||
@ -259,7 +275,7 @@ public class HSSFDateUtil
|
|||||||
* excel date formats.
|
* excel date formats.
|
||||||
* As Excel stores a great many of its dates in "non-internal"
|
* As Excel stores a great many of its dates in "non-internal"
|
||||||
* date formats, you will not normally want to use this method.
|
* date formats, you will not normally want to use this method.
|
||||||
* @see #isADateFormat(int,string)
|
* @see #isADateFormat(int,String)
|
||||||
* @see #isInternalDateFormat(int)
|
* @see #isInternalDateFormat(int)
|
||||||
*/
|
*/
|
||||||
public static boolean isCellInternalDateFormatted(HSSFCell cell) {
|
public static boolean isCellInternalDateFormatted(HSSFCell cell) {
|
||||||
@ -296,10 +312,10 @@ public class HSSFDateUtil
|
|||||||
* @exception IllegalArgumentException if date is invalid
|
* @exception IllegalArgumentException if date is invalid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private static int absoluteDay(Calendar cal)
|
static int absoluteDay(Calendar cal, boolean use1904windowing)
|
||||||
{
|
{
|
||||||
return cal.get(Calendar.DAY_OF_YEAR)
|
return cal.get(Calendar.DAY_OF_YEAR)
|
||||||
+ daysInPriorYears(cal.get(Calendar.YEAR));
|
+ daysInPriorYears(cal.get(Calendar.YEAR), use1904windowing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -307,14 +323,14 @@ public class HSSFDateUtil
|
|||||||
*
|
*
|
||||||
* @return days number of days in years prior to yr.
|
* @return days number of days in years prior to yr.
|
||||||
* @param yr a year (1900 < yr < 4000)
|
* @param yr a year (1900 < yr < 4000)
|
||||||
|
* @param use1904windowing
|
||||||
* @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, boolean use1904windowing)
|
||||||
{
|
{
|
||||||
if (yr < 1900) {
|
if ((!use1904windowing && yr < 1900) || (use1904windowing && yr < 1900)) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException("'year' must be 1900 or greater");
|
||||||
"'year' must be 1900 or greater");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int yr1 = yr - 1;
|
int yr1 = yr - 1;
|
||||||
@ -323,7 +339,7 @@ public class HSSFDateUtil
|
|||||||
+ yr1 / 400 // plus years divisible by 400
|
+ yr1 / 400 // plus years divisible by 400
|
||||||
- 460; // leap days in previous 1900 years
|
- 460; // leap days in previous 1900 years
|
||||||
|
|
||||||
return 365 * (yr - 1900) + leapDays;
|
return 365 * (yr - (use1904windowing ? 1904 : 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
|
||||||
|
@ -283,7 +283,7 @@ public class XLS2CSVmra implements HSSFListener {
|
|||||||
format = format.replaceAll("\\\\-","-");
|
format = format.replaceAll("\\\\-","-");
|
||||||
|
|
||||||
// Format as a date
|
// Format as a date
|
||||||
Date d = HSSFDateUtil.getJavaDate(value);
|
Date d = HSSFDateUtil.getJavaDate(value, false);
|
||||||
DateFormat df = new SimpleDateFormat(format);
|
DateFormat df = new SimpleDateFormat(format);
|
||||||
return df.format(d);
|
return df.format(d);
|
||||||
} else {
|
} else {
|
||||||
|
@ -70,7 +70,7 @@ public class Date extends NumericFunction {
|
|||||||
c.set(year, month, day, 0, 0, 0);
|
c.set(year, month, day, 0, 0, 0);
|
||||||
c.set(Calendar.MILLISECOND, 0);
|
c.set(Calendar.MILLISECOND, 0);
|
||||||
|
|
||||||
return new NumberEval(HSSFDateUtil.getExcelDate(c.getTime()));
|
return new NumberEval(HSSFDateUtil.getExcelDate(c.getTime(), false)); // XXX fix 1900/1904 problem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ srcCellRow, srcCellCol);
|
|||||||
if (ve instanceof NumericValueEval) {
|
if (ve instanceof NumericValueEval) {
|
||||||
NumericValueEval ne = (NumericValueEval) ve;
|
NumericValueEval ne = (NumericValueEval) ve;
|
||||||
if (HSSFDateUtil.isValidExcelDate(ne.getNumberValue())) {
|
if (HSSFDateUtil.isValidExcelDate(ne.getNumberValue())) {
|
||||||
java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue());
|
java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue(), false); // XXX fix 1900/1904 problem
|
||||||
java.util.Calendar c = java.util.Calendar.getInstance();
|
java.util.Calendar c = java.util.Calendar.getInstance();
|
||||||
c.setTime(d);
|
c.setTime(d);
|
||||||
retval = new NumberEval(c.get(java.util.Calendar.DAY_OF_MONTH));
|
retval = new NumberEval(c.get(java.util.Calendar.DAY_OF_MONTH));
|
||||||
|
@ -50,7 +50,7 @@ public class Month extends NumericFunction {
|
|||||||
if (ve instanceof NumericValueEval) {
|
if (ve instanceof NumericValueEval) {
|
||||||
NumericValueEval ne = (NumericValueEval) ve;
|
NumericValueEval ne = (NumericValueEval) ve;
|
||||||
if (HSSFDateUtil.isValidExcelDate(ne.getNumberValue())) {
|
if (HSSFDateUtil.isValidExcelDate(ne.getNumberValue())) {
|
||||||
java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue());
|
java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue(), false); // XXX fix 1900/1904 problem
|
||||||
retval = new NumberEval(d.getMonth()+1);
|
retval = new NumberEval(d.getMonth()+1);
|
||||||
} else {
|
} else {
|
||||||
retval = ErrorEval.NUM_ERROR;
|
retval = ErrorEval.NUM_ERROR;
|
||||||
|
@ -51,7 +51,7 @@ public class Year extends NumericFunction {
|
|||||||
if (ve instanceof NumericValueEval) {
|
if (ve instanceof NumericValueEval) {
|
||||||
NumericValueEval ne = (NumericValueEval) ve;
|
NumericValueEval ne = (NumericValueEval) ve;
|
||||||
if (HSSFDateUtil.isValidExcelDate(ne.getNumberValue())) {
|
if (HSSFDateUtil.isValidExcelDate(ne.getNumberValue())) {
|
||||||
java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue());
|
java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue(), false); // XXX fix 1900/1904 problem
|
||||||
retval = new NumberEval(d.getYear()+1900);
|
retval = new NumberEval(d.getYear()+1900);
|
||||||
} else {
|
} else {
|
||||||
retval = ErrorEval.NUM_ERROR;
|
retval = ErrorEval.NUM_ERROR;
|
||||||
|
@ -44,6 +44,7 @@ import java.util.GregorianCalendar;
|
|||||||
* paticular datatypes, etc.
|
* paticular datatypes, etc.
|
||||||
* @author Andrew C. Oliver (andy at superlinksoftware dot com)
|
* @author Andrew C. Oliver (andy at superlinksoftware dot com)
|
||||||
* @author Dan Sherman (dsherman at isisph.com)
|
* @author Dan Sherman (dsherman at isisph.com)
|
||||||
|
* @author Alex Jacoby (ajacoby at gmail.com)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class TestHSSFCell
|
public class TestHSSFCell
|
||||||
@ -107,41 +108,105 @@ extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks that the recognition of files using 1904 date windowing
|
* Checks that the recognition of files using 1904 date windowing
|
||||||
* is working properly. Conversion of the date is also an issue,
|
* is working properly. Conversion of the date is also an issue,
|
||||||
* but there's a separate unit test for that.
|
* but there's a separate unit test for that.
|
||||||
*/
|
*/
|
||||||
public void testDateWindowing() throws Exception {
|
public void testDateWindowingRead() throws Exception {
|
||||||
GregorianCalendar cal = new GregorianCalendar(2000,0,1); // Jan. 1, 2000
|
GregorianCalendar cal = new GregorianCalendar(2000,0,1); // Jan. 1, 2000
|
||||||
Date date = cal.getTime();
|
Date date = cal.getTime();
|
||||||
String path = System.getProperty("HSSF.testdata.path");
|
String path = System.getProperty("HSSF.testdata.path");
|
||||||
|
|
||||||
// first check a file with 1900 Date Windowing
|
// first check a file with 1900 Date Windowing
|
||||||
String filename = path + "/1900DateWindowing.xls";
|
String filename = path + "/1900DateWindowing.xls";
|
||||||
FileInputStream stream = new FileInputStream(filename);
|
FileInputStream stream = new FileInputStream(filename);
|
||||||
POIFSFileSystem fs = new POIFSFileSystem(stream);
|
POIFSFileSystem fs = new POIFSFileSystem(stream);
|
||||||
HSSFWorkbook workbook = new HSSFWorkbook(fs);
|
HSSFWorkbook workbook = new HSSFWorkbook(fs);
|
||||||
HSSFSheet sheet = workbook.getSheetAt(0);
|
HSSFSheet sheet = workbook.getSheetAt(0);
|
||||||
|
|
||||||
assertEquals("Date from file using 1900 Date Windowing",
|
assertEquals("Date from file using 1900 Date Windowing",
|
||||||
date.getTime(),
|
date.getTime(),
|
||||||
sheet.getRow(0).getCell((short)0)
|
sheet.getRow(0).getCell((short)0)
|
||||||
.getDateCellValue().getTime());
|
.getDateCellValue().getTime());
|
||||||
stream.close();
|
stream.close();
|
||||||
|
|
||||||
// now check a file with 1904 Date Windowing
|
// now check a file with 1904 Date Windowing
|
||||||
filename = path + "/1904DateWindowing.xls";
|
filename = path + "/1904DateWindowing.xls";
|
||||||
stream = new FileInputStream(filename);
|
stream = new FileInputStream(filename);
|
||||||
fs = new POIFSFileSystem(stream);
|
fs = new POIFSFileSystem(stream);
|
||||||
workbook = new HSSFWorkbook(fs);
|
workbook = new HSSFWorkbook(fs);
|
||||||
sheet = workbook.getSheetAt(0);
|
sheet = workbook.getSheetAt(0);
|
||||||
|
|
||||||
assertEquals("Date from file using 1904 Date Windowing",
|
assertEquals("Date from file using 1904 Date Windowing",
|
||||||
date.getTime(),
|
date.getTime(),
|
||||||
sheet.getRow(0).getCell((short)0)
|
sheet.getRow(0).getCell((short)0)
|
||||||
.getDateCellValue().getTime());
|
.getDateCellValue().getTime());
|
||||||
stream.close();
|
stream.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that dates are properly written to both types of files:
|
||||||
|
* those with 1900 and 1904 date windowing. Note that if the
|
||||||
|
* previous test ({@link #testDateWindowingRead}) fails, the
|
||||||
|
* results of this test are meaningless.
|
||||||
|
*/
|
||||||
|
public void testDateWindowingWrite() throws Exception {
|
||||||
|
GregorianCalendar cal = new GregorianCalendar(2000,0,1); // Jan. 1, 2000
|
||||||
|
Date date = cal.getTime();
|
||||||
|
String path = System.getProperty("HSSF.testdata.path");
|
||||||
|
|
||||||
|
// first check a file with 1900 Date Windowing
|
||||||
|
String filename = path + "/1900DateWindowing.xls";
|
||||||
|
writeCell(filename, 0, (short) 1, date);
|
||||||
|
assertEquals("Date from file using 1900 Date Windowing",
|
||||||
|
date.getTime(),
|
||||||
|
readCell(filename, 0, (short) 1).getTime());
|
||||||
|
|
||||||
|
// now check a file with 1904 Date Windowing
|
||||||
|
filename = path + "/1904DateWindowing.xls";
|
||||||
|
writeCell(filename, 0, (short) 1, date);
|
||||||
|
assertEquals("Date from file using 1900 Date Windowing",
|
||||||
|
date.getTime(),
|
||||||
|
readCell(filename, 0, (short) 1).getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets cell value and writes file.
|
||||||
|
*/
|
||||||
|
private void writeCell(String filename,
|
||||||
|
int rowIdx, short colIdx, Date date) throws Exception {
|
||||||
|
FileInputStream stream = new FileInputStream(filename);
|
||||||
|
POIFSFileSystem fs = new POIFSFileSystem(stream);
|
||||||
|
HSSFWorkbook workbook = new HSSFWorkbook(fs);
|
||||||
|
HSSFSheet sheet = workbook.getSheetAt(0);
|
||||||
|
HSSFRow row = sheet.getRow(rowIdx);
|
||||||
|
HSSFCell cell = row.getCell(colIdx);
|
||||||
|
|
||||||
|
if (cell == null) {
|
||||||
|
cell = row.createCell(colIdx);
|
||||||
|
}
|
||||||
|
cell.setCellValue(date);
|
||||||
|
|
||||||
|
// Write the file
|
||||||
|
stream.close();
|
||||||
|
FileOutputStream oStream = new FileOutputStream(filename);
|
||||||
|
workbook.write(oStream);
|
||||||
|
oStream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads cell value from file.
|
||||||
|
*/
|
||||||
|
private Date readCell(String filename,
|
||||||
|
int rowIdx, short colIdx) throws Exception {
|
||||||
|
FileInputStream stream = new FileInputStream(filename);
|
||||||
|
POIFSFileSystem fs = new POIFSFileSystem(stream);
|
||||||
|
HSSFWorkbook workbook = new HSSFWorkbook(fs);
|
||||||
|
HSSFSheet sheet = workbook.getSheetAt(0);
|
||||||
|
HSSFRow row = sheet.getRow(rowIdx);
|
||||||
|
HSSFCell cell = row.getCell(colIdx);
|
||||||
|
return cell.getDateCellValue();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that the active cell can be correctly read and set
|
* Tests that the active cell can be correctly read and set
|
||||||
|
@ -36,6 +36,8 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
|||||||
*
|
*
|
||||||
* @author Dan Sherman (dsherman at isisph.com)
|
* @author Dan Sherman (dsherman at isisph.com)
|
||||||
* @author Hack Kampbjorn (hak at 2mba.dk)
|
* @author Hack Kampbjorn (hak at 2mba.dk)
|
||||||
|
* @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
|
||||||
|
* @author Alex Jacoby (ajacoby at gmail.com)
|
||||||
* @version %I%, %G%
|
* @version %I%, %G%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -47,6 +49,8 @@ public class TestHSSFDateUtil
|
|||||||
public static final int CALENDAR_FEBRUARY = 1;
|
public static final int CALENDAR_FEBRUARY = 1;
|
||||||
public static final int CALENDAR_MARCH = 2;
|
public static final int CALENDAR_MARCH = 2;
|
||||||
public static final int CALENDAR_APRIL = 3;
|
public static final int CALENDAR_APRIL = 3;
|
||||||
|
public static final int CALENDAR_JULY = 6;
|
||||||
|
public static final int CALENDAR_OCTOBER = 9;
|
||||||
|
|
||||||
public TestHSSFDateUtil(String s)
|
public TestHSSFDateUtil(String s)
|
||||||
{
|
{
|
||||||
@ -67,10 +71,10 @@ public class TestHSSFDateUtil
|
|||||||
GregorianCalendar date = new GregorianCalendar(2002, 0, 1,
|
GregorianCalendar date = new GregorianCalendar(2002, 0, 1,
|
||||||
hour, 1, 1);
|
hour, 1, 1);
|
||||||
double excelDate =
|
double excelDate =
|
||||||
HSSFDateUtil.getExcelDate(date.getTime());
|
HSSFDateUtil.getExcelDate(date.getTime(), false);
|
||||||
|
|
||||||
assertEquals("Checking hour = " + hour, date.getTime().getTime(),
|
assertEquals("Checking hour = " + hour, date.getTime().getTime(),
|
||||||
HSSFDateUtil.getJavaDate(excelDate).getTime());
|
HSSFDateUtil.getJavaDate(excelDate, false).getTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
// check 1900 and 1904 date windowing conversions
|
// check 1900 and 1904 date windowing conversions
|
||||||
@ -99,7 +103,7 @@ public class TestHSSFDateUtil
|
|||||||
public void testExcelConversionOnDSTStart() {
|
public void testExcelConversionOnDSTStart() {
|
||||||
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
|
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
|
||||||
TimeZone.setDefault(cet);
|
TimeZone.setDefault(cet);
|
||||||
Calendar cal = new GregorianCalendar(2004, Calendar.MARCH, 28);
|
Calendar cal = new GregorianCalendar(2004, CALENDAR_MARCH, 28);
|
||||||
for (int hour = 0; hour < 24; hour++) {
|
for (int hour = 0; hour < 24; hour++) {
|
||||||
|
|
||||||
// Skip 02:00 CET as that is the Daylight change time
|
// Skip 02:00 CET as that is the Daylight change time
|
||||||
@ -110,7 +114,7 @@ public class TestHSSFDateUtil
|
|||||||
|
|
||||||
cal.set(Calendar.HOUR_OF_DAY, hour);
|
cal.set(Calendar.HOUR_OF_DAY, hour);
|
||||||
Date javaDate = cal.getTime();
|
Date javaDate = cal.getTime();
|
||||||
double excelDate = HSSFDateUtil.getExcelDate(javaDate);
|
double excelDate = HSSFDateUtil.getExcelDate(javaDate, false);
|
||||||
double difference = excelDate - Math.floor(excelDate);
|
double difference = excelDate - Math.floor(excelDate);
|
||||||
int differenceInHours = (int) (difference * 24 * 60 + 0.5) / 60;
|
int differenceInHours = (int) (difference * 24 * 60 + 0.5) / 60;
|
||||||
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
|
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
|
||||||
@ -118,7 +122,7 @@ public class TestHSSFDateUtil
|
|||||||
differenceInHours);
|
differenceInHours);
|
||||||
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
|
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
|
||||||
javaDate.getTime(),
|
javaDate.getTime(),
|
||||||
HSSFDateUtil.getJavaDate(excelDate).getTime());
|
HSSFDateUtil.getJavaDate(excelDate, false).getTime());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,8 +133,8 @@ public class TestHSSFDateUtil
|
|||||||
public void testJavaConversionOnDSTStart() {
|
public void testJavaConversionOnDSTStart() {
|
||||||
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
|
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
|
||||||
TimeZone.setDefault(cet);
|
TimeZone.setDefault(cet);
|
||||||
Calendar cal = new GregorianCalendar(2004, Calendar.MARCH, 28);
|
Calendar cal = new GregorianCalendar(2004, CALENDAR_MARCH, 28);
|
||||||
double excelDate = HSSFDateUtil.getExcelDate(cal.getTime());
|
double excelDate = HSSFDateUtil.getExcelDate(cal.getTime(), false);
|
||||||
double oneHour = 1.0 / 24;
|
double oneHour = 1.0 / 24;
|
||||||
double oneMinute = oneHour / 60;
|
double oneMinute = oneHour / 60;
|
||||||
for (int hour = 0; hour < 24; hour++, excelDate += oneHour) {
|
for (int hour = 0; hour < 24; hour++, excelDate += oneHour) {
|
||||||
@ -142,10 +146,10 @@ public class TestHSSFDateUtil
|
|||||||
}
|
}
|
||||||
|
|
||||||
cal.set(Calendar.HOUR_OF_DAY, hour);
|
cal.set(Calendar.HOUR_OF_DAY, hour);
|
||||||
Date javaDate = HSSFDateUtil.getJavaDate(excelDate);
|
Date javaDate = HSSFDateUtil.getJavaDate(excelDate, false);
|
||||||
assertEquals("Checking " + hour + " hours on Daylight Saving Time start date",
|
assertEquals("Checking " + hour + " hours on Daylight Saving Time start date",
|
||||||
excelDate,
|
excelDate,
|
||||||
HSSFDateUtil.getExcelDate(javaDate), oneMinute);
|
HSSFDateUtil.getExcelDate(javaDate, false), oneMinute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,11 +160,11 @@ public class TestHSSFDateUtil
|
|||||||
public void testExcelConversionOnDSTEnd() {
|
public void testExcelConversionOnDSTEnd() {
|
||||||
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
|
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
|
||||||
TimeZone.setDefault(cet);
|
TimeZone.setDefault(cet);
|
||||||
Calendar cal = new GregorianCalendar(2004, Calendar.OCTOBER, 31);
|
Calendar cal = new GregorianCalendar(2004, CALENDAR_OCTOBER, 31);
|
||||||
for (int hour = 0; hour < 24; hour++) {
|
for (int hour = 0; hour < 24; hour++) {
|
||||||
cal.set(Calendar.HOUR_OF_DAY, hour);
|
cal.set(Calendar.HOUR_OF_DAY, hour);
|
||||||
Date javaDate = cal.getTime();
|
Date javaDate = cal.getTime();
|
||||||
double excelDate = HSSFDateUtil.getExcelDate(javaDate);
|
double excelDate = HSSFDateUtil.getExcelDate(javaDate, false);
|
||||||
double difference = excelDate - Math.floor(excelDate);
|
double difference = excelDate - Math.floor(excelDate);
|
||||||
int differenceInHours = (int) (difference * 24 * 60 + 0.5) / 60;
|
int differenceInHours = (int) (difference * 24 * 60 + 0.5) / 60;
|
||||||
assertEquals("Checking " + hour + " hour on Daylight Saving Time end date",
|
assertEquals("Checking " + hour + " hour on Daylight Saving Time end date",
|
||||||
@ -168,7 +172,7 @@ public class TestHSSFDateUtil
|
|||||||
differenceInHours);
|
differenceInHours);
|
||||||
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
|
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
|
||||||
javaDate.getTime(),
|
javaDate.getTime(),
|
||||||
HSSFDateUtil.getJavaDate(excelDate).getTime());
|
HSSFDateUtil.getJavaDate(excelDate, false).getTime());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,16 +183,16 @@ public class TestHSSFDateUtil
|
|||||||
public void testJavaConversionOnDSTEnd() {
|
public void testJavaConversionOnDSTEnd() {
|
||||||
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
|
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
|
||||||
TimeZone.setDefault(cet);
|
TimeZone.setDefault(cet);
|
||||||
Calendar cal = new GregorianCalendar(2004, Calendar.OCTOBER, 31);
|
Calendar cal = new GregorianCalendar(2004, CALENDAR_OCTOBER, 31);
|
||||||
double excelDate = HSSFDateUtil.getExcelDate(cal.getTime());
|
double excelDate = HSSFDateUtil.getExcelDate(cal.getTime(), false);
|
||||||
double oneHour = 1.0 / 24;
|
double oneHour = 1.0 / 24;
|
||||||
double oneMinute = oneHour / 60;
|
double oneMinute = oneHour / 60;
|
||||||
for (int hour = 0; hour < 24; hour++, excelDate += oneHour) {
|
for (int hour = 0; hour < 24; hour++, excelDate += oneHour) {
|
||||||
cal.set(Calendar.HOUR_OF_DAY, hour);
|
cal.set(Calendar.HOUR_OF_DAY, hour);
|
||||||
Date javaDate = HSSFDateUtil.getJavaDate(excelDate);
|
Date javaDate = HSSFDateUtil.getJavaDate(excelDate, false);
|
||||||
assertEquals("Checking " + hour + " hours on Daylight Saving Time start date",
|
assertEquals("Checking " + hour + " hours on Daylight Saving Time start date",
|
||||||
excelDate,
|
excelDate,
|
||||||
HSSFDateUtil.getExcelDate(javaDate), oneMinute);
|
HSSFDateUtil.getExcelDate(javaDate, false), oneMinute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,23 +319,36 @@ public class TestHSSFDateUtil
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testDateBug_2Excel() {
|
public void testDateBug_2Excel() {
|
||||||
assertEquals(59.0, HSSFDateUtil.getExcelDate(createDate(1900, CALENDAR_FEBRUARY, 28)), 0.00001);
|
assertEquals(59.0, HSSFDateUtil.getExcelDate(createDate(1900, CALENDAR_FEBRUARY, 28), false), 0.00001);
|
||||||
assertEquals(61.0, HSSFDateUtil.getExcelDate(createDate(1900, CALENDAR_MARCH, 1)), 0.00001);
|
assertEquals(61.0, HSSFDateUtil.getExcelDate(createDate(1900, CALENDAR_MARCH, 1), false), 0.00001);
|
||||||
|
|
||||||
assertEquals(37315.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_FEBRUARY, 28)), 0.00001);
|
assertEquals(37315.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_FEBRUARY, 28), false), 0.00001);
|
||||||
assertEquals(37316.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_MARCH, 1)), 0.00001);
|
assertEquals(37316.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_MARCH, 1), false), 0.00001);
|
||||||
assertEquals(37257.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_JANUARY, 1)), 0.00001);
|
assertEquals(37257.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_JANUARY, 1), false), 0.00001);
|
||||||
assertEquals(38074.00, HSSFDateUtil.getExcelDate(createDate(2004, CALENDAR_MARCH, 28)), 0.00001);
|
assertEquals(38074.00, HSSFDateUtil.getExcelDate(createDate(2004, CALENDAR_MARCH, 28), false), 0.00001);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDateBug_2Java() {
|
public void testDateBug_2Java() {
|
||||||
assertEquals(createDate(1900, Calendar.FEBRUARY, 28), HSSFDateUtil.getJavaDate(59.0));
|
assertEquals(createDate(1900, CALENDAR_FEBRUARY, 28), HSSFDateUtil.getJavaDate(59.0, false));
|
||||||
assertEquals(createDate(1900, Calendar.MARCH, 1), HSSFDateUtil.getJavaDate(61.0));
|
assertEquals(createDate(1900, CALENDAR_MARCH, 1), HSSFDateUtil.getJavaDate(61.0, false));
|
||||||
|
|
||||||
assertEquals(createDate(2002, Calendar.FEBRUARY, 28), HSSFDateUtil.getJavaDate(37315.00));
|
assertEquals(createDate(2002, CALENDAR_FEBRUARY, 28), HSSFDateUtil.getJavaDate(37315.00, false));
|
||||||
assertEquals(createDate(2002, Calendar.MARCH, 1), HSSFDateUtil.getJavaDate(37316.00));
|
assertEquals(createDate(2002, CALENDAR_MARCH, 1), HSSFDateUtil.getJavaDate(37316.00, false));
|
||||||
assertEquals(createDate(2002, Calendar.JANUARY, 1), HSSFDateUtil.getJavaDate(37257.00));
|
assertEquals(createDate(2002, CALENDAR_JANUARY, 1), HSSFDateUtil.getJavaDate(37257.00, false));
|
||||||
assertEquals(createDate(2004, Calendar.MARCH, 28), HSSFDateUtil.getJavaDate(38074.00));
|
assertEquals(createDate(2004, CALENDAR_MARCH, 28), HSSFDateUtil.getJavaDate(38074.00, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDate1904() {
|
||||||
|
assertEquals(createDate(1904, CALENDAR_JANUARY, 2), HSSFDateUtil.getJavaDate(1.0, true));
|
||||||
|
assertEquals(createDate(1904, CALENDAR_JANUARY, 1), HSSFDateUtil.getJavaDate(0.0, true));
|
||||||
|
assertEquals(0.0, HSSFDateUtil.getExcelDate(createDate(1904, CALENDAR_JANUARY, 1), true), 0.00001);
|
||||||
|
assertEquals(1.0, HSSFDateUtil.getExcelDate(createDate(1904, CALENDAR_JANUARY, 2), true), 0.00001);
|
||||||
|
|
||||||
|
assertEquals(createDate(1998, CALENDAR_JULY, 5), HSSFDateUtil.getJavaDate(35981, false));
|
||||||
|
assertEquals(createDate(1998, CALENDAR_JULY, 5), HSSFDateUtil.getJavaDate(34519, true));
|
||||||
|
|
||||||
|
assertEquals(35981.0, HSSFDateUtil.getExcelDate(createDate(1998, CALENDAR_JULY, 5), false), 0.00001);
|
||||||
|
assertEquals(34519.0, HSSFDateUtil.getExcelDate(createDate(1998, CALENDAR_JULY, 5), true), 0.00001);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Date createDate(int year, int month, int day) {
|
private Date createDate(int year, int month, int day) {
|
||||||
@ -341,10 +358,21 @@ public class TestHSSFDateUtil
|
|||||||
return c.getTime();
|
return c.getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if HSSFDateUtil.getAbsoluteDay works as advertised.
|
||||||
|
*/
|
||||||
|
public void testAbsoluteDay() {
|
||||||
|
// 1 Jan 1900 is 1 day after 31 Dec 1899
|
||||||
|
GregorianCalendar calendar = new GregorianCalendar(1900, 0, 1);
|
||||||
|
assertEquals("Checking absolute day (1 Jan 1900)", 1, HSSFDateUtil.absoluteDay(calendar, false));
|
||||||
|
// 1 Jan 1901 is 366 days after 31 Dec 1899
|
||||||
|
calendar = new GregorianCalendar(1901, 0, 1);
|
||||||
|
assertEquals("Checking absolute day (1 Jan 1901)", 366, HSSFDateUtil.absoluteDay(calendar, false));
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ public class TestReadWriteChart
|
|||||||
//System.out.println("first assertion for date");
|
//System.out.println("first assertion for date");
|
||||||
assertEquals(new GregorianCalendar(2000, 0, 1, 10, 51, 2).getTime(),
|
assertEquals(new GregorianCalendar(2000, 0, 1, 10, 51, 2).getTime(),
|
||||||
HSSFDateUtil
|
HSSFDateUtil
|
||||||
.getJavaDate(firstCell.getNumericCellValue()));
|
.getJavaDate(firstCell.getNumericCellValue(), false));
|
||||||
HSSFRow row = sheet.createRow(( short ) 15);
|
HSSFRow row = sheet.createRow(( short ) 15);
|
||||||
HSSFCell cell = row.createCell(( short ) 1);
|
HSSFCell cell = row.createCell(( short ) 1);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user