mirror of
https://github.com/apache/poi.git
synced 2025-03-05 00:19:07 +00:00
63779 Add support for the new Java date/time API added in Java 8
Deprecate HSSFDateUtil Closes #160 on Github git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1868198 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
97c21e31b1
commit
b10f94cc75
@ -31,6 +31,7 @@ import org.apache.poi.ss.formula.ptg.NumberPtg;
|
||||
import org.apache.poi.ss.formula.ptg.Ptg;
|
||||
import org.apache.poi.ss.formula.ptg.StringPtg;
|
||||
import org.apache.poi.ss.usermodel.DataValidationConstraint;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.util.LocaleUtil;
|
||||
|
||||
/**
|
||||
@ -242,7 +243,7 @@ public class DVConstraint implements DataValidationConstraint {
|
||||
if (timeStr == null) {
|
||||
return null;
|
||||
}
|
||||
return Double.valueOf(HSSFDateUtil.convertTime(timeStr));
|
||||
return Double.valueOf(DateUtil.convertTime(timeStr));
|
||||
}
|
||||
/**
|
||||
* @param dateFormat pass <code>null</code> for default YYYYMMDD
|
||||
@ -254,7 +255,7 @@ public class DVConstraint implements DataValidationConstraint {
|
||||
}
|
||||
Date dateVal;
|
||||
if (dateFormat == null) {
|
||||
dateVal = HSSFDateUtil.parseYYYYMMDDDate(dateStr);
|
||||
dateVal = DateUtil.parseYYYYMMDDDate(dateStr);
|
||||
} else {
|
||||
try {
|
||||
dateVal = dateFormat.parse(dateStr);
|
||||
@ -263,7 +264,7 @@ public class DVConstraint implements DataValidationConstraint {
|
||||
+ "' using specified format '" + dateFormat + "'", e);
|
||||
}
|
||||
}
|
||||
return Double.valueOf(HSSFDateUtil.getExcelDate(dateVal));
|
||||
return Double.valueOf(DateUtil.getExcelDate(dateVal));
|
||||
}
|
||||
|
||||
public static DVConstraint createCustomFormulaConstraint(String formula) {
|
||||
|
@ -18,6 +18,7 @@
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
@ -47,6 +48,7 @@ import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.CellValue;
|
||||
import org.apache.poi.ss.usermodel.Comment;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.ss.usermodel.FormulaError;
|
||||
import org.apache.poi.ss.usermodel.Hyperlink;
|
||||
import org.apache.poi.ss.usermodel.RichTextString;
|
||||
@ -453,11 +455,22 @@ public class HSSFCell extends CellBase {
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>In HSSF, only the number of days is stored. The fractional part is ignored.</p>
|
||||
* @see HSSFDateUtil
|
||||
* @see DateUtil
|
||||
* @see org.apache.poi.ss.usermodel.DateUtil
|
||||
*/
|
||||
protected void setCellValueImpl(Date value) {
|
||||
setCellValue(HSSFDateUtil.getExcelDate(value, _book.getWorkbook().isUsing1904DateWindowing()));
|
||||
setCellValue(DateUtil.getExcelDate(value, _book.getWorkbook().isUsing1904DateWindowing()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>In HSSF, only the number of days is stored. The fractional part is ignored.</p>
|
||||
* @see DateUtil
|
||||
* @see org.apache.poi.ss.usermodel.DateUtil
|
||||
*/
|
||||
protected void setCellValueImpl(LocalDateTime value) {
|
||||
setCellValue(DateUtil.getExcelDate(value, _book.getWorkbook().isUsing1904DateWindowing()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -465,7 +478,7 @@ public class HSSFCell extends CellBase {
|
||||
*/
|
||||
@Override
|
||||
protected void setCellValueImpl(Calendar value) {
|
||||
setCellValue( HSSFDateUtil.getExcelDate(value, _book.getWorkbook().isUsing1904DateWindowing()) );
|
||||
setCellValue( DateUtil.getExcelDate(value, _book.getWorkbook().isUsing1904DateWindowing()) );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -679,9 +692,28 @@ public class HSSFCell extends CellBase {
|
||||
}
|
||||
double value = getNumericCellValue();
|
||||
if (_book.getWorkbook().isUsing1904DateWindowing()) {
|
||||
return HSSFDateUtil.getJavaDate(value, true);
|
||||
return DateUtil.getJavaDate(value, true);
|
||||
}
|
||||
return HSSFDateUtil.getJavaDate(value, false);
|
||||
return DateUtil.getJavaDate(value, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the cell as a LocalDateTime.
|
||||
* For strings we throw an exception.
|
||||
* For blank cells we return a null.
|
||||
* See {@link HSSFDataFormatter} for formatting
|
||||
* this date into a string similar to how excel does.
|
||||
*/
|
||||
public LocalDateTime getLocalDateTimeCellValue() {
|
||||
|
||||
if (_cellType == CellType.BLANK) {
|
||||
return null;
|
||||
}
|
||||
double value = getNumericCellValue();
|
||||
if (_book.getWorkbook().isUsing1904DateWindowing()) {
|
||||
return DateUtil.getLocalDateTime(value, true);
|
||||
}
|
||||
return DateUtil.getLocalDateTime(value, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -853,7 +885,7 @@ public class HSSFCell extends CellBase {
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected formula result type (" + _cellType + ")");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -899,7 +931,7 @@ public class HSSFCell extends CellBase {
|
||||
/**
|
||||
* <p>Set the style for the cell. The style should be an HSSFCellStyle created/retreived from
|
||||
* the HSSFWorkbook.</p>
|
||||
*
|
||||
*
|
||||
* <p>To change the style of a cell without affecting other cells that use the same style,
|
||||
* use {@link org.apache.poi.ss.util.CellUtil#setCellStyleProperties(org.apache.poi.ss.usermodel.Cell, java.util.Map)}</p>
|
||||
*
|
||||
@ -1001,7 +1033,7 @@ public class HSSFCell extends CellBase {
|
||||
return getCellFormula();
|
||||
case NUMERIC:
|
||||
//TODO apply the dataformat for this cell
|
||||
if (HSSFDateUtil.isCellDateFormatted(this)) {
|
||||
if (DateUtil.isCellDateFormatted(this)) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", LocaleUtil.getUserLocale());
|
||||
sdf.setTimeZone(LocaleUtil.getUserTimeZone());
|
||||
return sdf.format(getDateCellValue());
|
||||
|
@ -30,8 +30,10 @@ import org.apache.poi.ss.usermodel.DateUtil;
|
||||
|
||||
/**
|
||||
* Contains methods for dealing with Excel dates.
|
||||
* @deprecated Use {@link DateUtil} instead
|
||||
*/
|
||||
public class HSSFDateUtil extends DateUtil {
|
||||
@Deprecated
|
||||
public final class HSSFDateUtil extends DateUtil {
|
||||
protected static int absoluteDay(Calendar cal, boolean use1904windowing) {
|
||||
return DateUtil.absoluteDay(cal, use1904windowing);
|
||||
}
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
@ -178,6 +180,42 @@ public interface Cell {
|
||||
*/
|
||||
void setCellValue(Date value);
|
||||
|
||||
/**
|
||||
* <p>Converts the supplied date to its equivalent Excel numeric value and sets
|
||||
* that into the cell.</p>
|
||||
*
|
||||
* <p><b>Note</b> - There is actually no 'DATE' cell type in Excel. In many
|
||||
* cases (when entering date values), Excel automatically adjusts the
|
||||
* <i>cell style</i> to some date format, creating the illusion that the cell
|
||||
* data type is now something besides {@link CellType#NUMERIC}. POI
|
||||
* does not attempt to replicate this behaviour. To make a numeric cell
|
||||
* display as a date, use {@link #setCellStyle(CellStyle)} etc.</p>
|
||||
*
|
||||
* @param value the numeric value to set this cell to. For formulas we'll set the
|
||||
* precalculated value, for numerics we'll set its value. For other types we
|
||||
* will change the cell to a numerics cell and set its value.
|
||||
*/
|
||||
void setCellValue(LocalDateTime value);
|
||||
|
||||
/**
|
||||
* <p>Converts the supplied date to its equivalent Excel numeric value and sets
|
||||
* that into the cell.</p>
|
||||
*
|
||||
* <p><b>Note</b> - There is actually no 'DATE' cell type in Excel. In many
|
||||
* cases (when entering date values), Excel automatically adjusts the
|
||||
* <i>cell style</i> to some date format, creating the illusion that the cell
|
||||
* data type is now something besides {@link CellType#NUMERIC}. POI
|
||||
* does not attempt to replicate this behaviour. To make a numeric cell
|
||||
* display as a date, use {@link #setCellStyle(CellStyle)} etc.</p>
|
||||
*
|
||||
* @param value the numeric value to set this cell to. For formulas we'll set the
|
||||
* precalculated value, for numerics we'll set its value. For other types we
|
||||
* will change the cell to a numerics cell and set its value.
|
||||
*/
|
||||
default void setCellValue(LocalDate value) {
|
||||
setCellValue(value.atStartOfDay());
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Set a date value for the cell. Excel treats dates as numeric so you will need to format the cell as
|
||||
* a date.</p>
|
||||
@ -279,6 +317,18 @@ public interface Cell {
|
||||
*/
|
||||
Date getDateCellValue();
|
||||
|
||||
/**
|
||||
* Get the value of the cell as a LocalDateTime.
|
||||
* <p>
|
||||
* For strings we throw an exception. For blank cells we return a null.
|
||||
* </p>
|
||||
* @return the value of the cell as a LocalDateTime
|
||||
* @throws IllegalStateException if the cell type returned by {@link #getCellType()} is {@link CellType#STRING}
|
||||
* @exception NumberFormatException if the cell value isn't a parsable <code>double</code>.
|
||||
* @see DataFormatter for formatting this date into a string similar to how excel does.
|
||||
*/
|
||||
LocalDateTime getLocalDateTimeCellValue();
|
||||
|
||||
/**
|
||||
* Get the value of the cell as a XSSFRichTextString
|
||||
* <p>
|
||||
|
@ -24,6 +24,7 @@ import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.apache.poi.util.Removal;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
@ -228,6 +229,15 @@ public abstract class CellBase implements Cell {
|
||||
setCellValueImpl(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCellValue(LocalDateTime value) {
|
||||
if(value == null) {
|
||||
setBlank();
|
||||
return;
|
||||
}
|
||||
setCellValueImpl(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation-specific way to set a date value.
|
||||
* <code>value</code> is guaranteed to be non-null.
|
||||
@ -237,6 +247,15 @@ public abstract class CellBase implements Cell {
|
||||
*/
|
||||
protected abstract void setCellValueImpl(Date value);
|
||||
|
||||
/**
|
||||
* Implementation-specific way to set a date value.
|
||||
* <code>value</code> is guaranteed to be non-null.
|
||||
* The implementation is expected to adjust the cell type accordingly, so that after this call
|
||||
* getCellType() or getCachedFormulaResultType() would return {@link CellType#NUMERIC}.
|
||||
* @param value the new date to set
|
||||
*/
|
||||
protected abstract void setCellValueImpl(LocalDateTime value);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
@ -18,7 +18,11 @@
|
||||
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
import org.apache.poi.ss.formula.ConditionalFormattingEvaluator;
|
||||
import org.apache.poi.util.LocaleUtil;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
@ -31,13 +35,11 @@ import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.poi.ss.formula.ConditionalFormattingEvaluator;
|
||||
import org.apache.poi.util.LocaleUtil;
|
||||
|
||||
/**
|
||||
* Contains methods for dealing with Excel dates.
|
||||
*/
|
||||
public class DateUtil {
|
||||
// FIXME this should be changed to private and the class marked final once HSSFDateUtil can be removed
|
||||
protected DateUtil() {
|
||||
// no instances of this class
|
||||
}
|
||||
@ -74,6 +76,88 @@ public class DateUtil {
|
||||
.parseDefaulting(ChronoField.YEAR_OF_ERA, LocaleUtil.getLocaleCalendar().get(Calendar.YEAR))
|
||||
.toFormatter();
|
||||
|
||||
/**
|
||||
* Convert a Java Date (at UTC) to LocalDateTime.
|
||||
* @param date the date
|
||||
* @return LocalDateTime instance
|
||||
*/
|
||||
public static LocalDateTime toLocalDateTime(Date date) {
|
||||
return date.toInstant()
|
||||
.atZone(TimeZone.getTimeZone("UTC").toZoneId()) // java.util.Date uses UTC
|
||||
.toLocalDateTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a Java Calendar (at UTC) to LocalDateTime.
|
||||
* @param date the date
|
||||
* @return LocalDateTime instance
|
||||
*/
|
||||
public static LocalDateTime toLocalDateTime(Calendar date) {
|
||||
return date.toInstant()
|
||||
.atZone(TimeZone.getTimeZone("UTC").toZoneId()) // java.util.Date uses UTC
|
||||
.toLocalDateTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a LocalDate, 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
|
||||
*/
|
||||
public static double getExcelDate(LocalDate date) {
|
||||
return getExcelDate(date, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a LocalDate, 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(LocalDate date, boolean use1904windowing) {
|
||||
int year = date.getYear();
|
||||
int dayOfYear = date.getDayOfYear();
|
||||
int hour = 0;
|
||||
int minute = 0;
|
||||
int second = 0;
|
||||
int milliSecond = 0;
|
||||
|
||||
return internalGetExcelDate(year, dayOfYear, hour, minute, second, milliSecond, use1904windowing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a LocalDateTime, 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
|
||||
*/
|
||||
public static double getExcelDate(LocalDateTime date) {
|
||||
return getExcelDate(date, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a LocalDateTime, 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(LocalDateTime date, boolean use1904windowing) {
|
||||
int year = date.getYear();
|
||||
int dayOfYear = date.getDayOfYear();
|
||||
int hour = date.getHour();
|
||||
int minute = date.getMinute();
|
||||
int second = date.getSecond();
|
||||
int milliSecond = date.getNano()/1_000_000;
|
||||
|
||||
return internalGetExcelDate(year, dayOfYear, hour, minute, second, milliSecond, use1904windowing);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,6 +168,7 @@ public class DateUtil {
|
||||
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.
|
||||
@ -94,9 +179,17 @@ public class DateUtil {
|
||||
*/
|
||||
public static double getExcelDate(Date date, boolean use1904windowing) {
|
||||
Calendar calStart = LocaleUtil.getLocaleCalendar();
|
||||
calStart.setTime(date); // If date includes hours, minutes, and seconds, set them to 0
|
||||
return internalGetExcelDate(calStart, use1904windowing);
|
||||
calStart.setTime(date);
|
||||
int year = calStart.get(Calendar.YEAR);
|
||||
int dayOfYear = calStart.get(Calendar.DAY_OF_YEAR);
|
||||
int hour = calStart.get(Calendar.HOUR_OF_DAY);
|
||||
int minute = calStart.get(Calendar.MINUTE);
|
||||
int second = calStart.get(Calendar.SECOND);
|
||||
int milliSecond = calStart.get(Calendar.MILLISECOND);
|
||||
|
||||
return internalGetExcelDate(year, dayOfYear, hour, minute, second, milliSecond, use1904windowing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a Date in the form of a Calendar, converts it into a double
|
||||
* representing its internal Excel representation, which is the
|
||||
@ -108,15 +201,23 @@ public class DateUtil {
|
||||
* @param use1904windowing Should 1900 or 1904 date windowing be used?
|
||||
*/
|
||||
public static double getExcelDate(Calendar date, boolean use1904windowing) {
|
||||
// Don't alter the supplied Calendar as we do our work
|
||||
return internalGetExcelDate( (Calendar)date.clone(), use1904windowing );
|
||||
int year = date.get(Calendar.YEAR);
|
||||
int dayOfYear = date.get(Calendar.DAY_OF_YEAR);
|
||||
int hour = date.get(Calendar.HOUR_OF_DAY);
|
||||
int minute = date.get(Calendar.MINUTE);
|
||||
int second = date.get(Calendar.SECOND);
|
||||
int milliSecond = date.get(Calendar.MILLISECOND);
|
||||
|
||||
return internalGetExcelDate(year, dayOfYear, hour, minute, second, milliSecond, use1904windowing);
|
||||
}
|
||||
private static double internalGetExcelDate(Calendar date, boolean use1904windowing) {
|
||||
if ((!use1904windowing && date.get(Calendar.YEAR) < 1900) ||
|
||||
(use1904windowing && date.get(Calendar.YEAR) < 1904))
|
||||
|
||||
private static double internalGetExcelDate(int year, int dayOfYear, int hour, int minute, int second, int milliSecond, boolean use1904windowing) {
|
||||
if ((!use1904windowing && year < 1900) ||
|
||||
(use1904windowing && year < 1904))
|
||||
{
|
||||
return BAD_DATE;
|
||||
}
|
||||
|
||||
// Because of daylight time saving we cannot use
|
||||
// date.getTime() - calStart.getTimeInMillis()
|
||||
// as the difference in milliseconds between 00:00 and 04:00
|
||||
@ -124,14 +225,13 @@ public class DateUtil {
|
||||
// be 4 hours.
|
||||
// E.g. 2004-03-28 04:00 CEST - 2004-03-28 00:00 CET is 3 hours
|
||||
// and 2004-10-31 04:00 CET - 2004-10-31 00:00 CEST is 5 hours
|
||||
double fraction = (((date.get(Calendar.HOUR_OF_DAY) * 60.0
|
||||
+ date.get(Calendar.MINUTE)
|
||||
) * 60.0 + date.get(Calendar.SECOND)
|
||||
) * 1000.0 + date.get(Calendar.MILLISECOND)
|
||||
double fraction = (((hour * 60.0
|
||||
+ minute
|
||||
) * 60.0 + second
|
||||
) * 1000.0 + milliSecond
|
||||
) / DAY_MILLISECONDS;
|
||||
Calendar calStart = dayStart(date);
|
||||
|
||||
double value = fraction + absoluteDay(calStart, use1904windowing);
|
||||
double value = fraction + absoluteDay(year, dayOfYear, use1904windowing);
|
||||
|
||||
if (!use1904windowing && value >= 60) {
|
||||
value++;
|
||||
@ -241,6 +341,86 @@ public class DateUtil {
|
||||
public static Date getJavaDate(double date, boolean use1904windowing) {
|
||||
return getJavaDate(date, use1904windowing, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an Excel date with using 1900 date windowing, and
|
||||
* converts it to a java.time.LocalDateTime.
|
||||
*
|
||||
* 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(getLocalDateTime(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
|
||||
*
|
||||
* @param date The Excel date.
|
||||
* @return Java representation of the date, or null if date is not a valid Excel date
|
||||
* @see java.util.TimeZone
|
||||
*/
|
||||
public static LocalDateTime getLocalDateTime(double date) {
|
||||
return getLocalDateTime(date, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an Excel date with either 1900 or 1904 date windowing,
|
||||
* converts it to a java.time.LocalDateTime.
|
||||
*
|
||||
* Excel Dates and Times are stored without any timezone
|
||||
* information. If you know (through other means) that your file
|
||||
* uses a different TimeZone to the system default, you can use
|
||||
* this version of the getJavaDate() method to handle it.
|
||||
*
|
||||
* @param date The Excel date.
|
||||
* @param use1904windowing true if date uses 1904 windowing,
|
||||
* or false if using 1900 date windowing.
|
||||
* @return Java representation of the date, or null if date is not a valid Excel date
|
||||
*/
|
||||
public static LocalDateTime getLocalDateTime(double date, boolean use1904windowing) {
|
||||
return getLocalDateTime(date, use1904windowing, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an Excel date with either 1900 or 1904 date windowing,
|
||||
* converts it to a java.time.LocalDateTime.
|
||||
*
|
||||
* Excel Dates and Times are stored without any timezone
|
||||
* information. If you know (through other means) that your file
|
||||
* uses a different TimeZone to the system default, you can use
|
||||
* this version of the getJavaDate() method to handle it.
|
||||
*
|
||||
* @param date The Excel date.
|
||||
* @param use1904windowing true if date uses 1904 windowing,
|
||||
* or false if using 1900 date windowing.
|
||||
* @param roundSeconds round to closest second
|
||||
* @return Java representation of the date, or null if date is not a valid Excel date
|
||||
*/
|
||||
public static LocalDateTime getLocalDateTime(double date, boolean use1904windowing, boolean roundSeconds) {
|
||||
if (!isValidExcelDate(date)) {
|
||||
return null;
|
||||
}
|
||||
int wholeDays = (int)Math.floor(date);
|
||||
int millisecondsInDay = (int)((date - wholeDays) * DAY_MILLISECONDS + 0.5);
|
||||
|
||||
int startYear = 1900;
|
||||
int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which it isn't
|
||||
if (use1904windowing) {
|
||||
startYear = 1904;
|
||||
dayAdjust = 1; // 1904 date windowing uses 1/2/1904 as the first day
|
||||
}
|
||||
else if (wholeDays < 61) {
|
||||
// Date is prior to 3/1/1900, so adjust because Excel thinks 2/29/1900 exists
|
||||
// If Excel date == 2/29/1900, will become 3/1/1900 in Java representation
|
||||
dayAdjust = 0;
|
||||
}
|
||||
|
||||
LocalDateTime ldt = LocalDateTime.of(startYear, 1, 1, 0, 0);
|
||||
ldt = ldt.plusDays(wholeDays+dayAdjust-1);
|
||||
ldt = ldt.plusNanos(millisecondsInDay*1_000_000L);
|
||||
|
||||
return ldt;
|
||||
}
|
||||
|
||||
public static void setCalendar(Calendar calendar, int wholeDays,
|
||||
int millisecondsInDay, boolean use1904windowing, boolean roundSeconds) {
|
||||
@ -616,10 +796,33 @@ public class DateUtil {
|
||||
*/
|
||||
protected static int absoluteDay(Calendar cal, boolean use1904windowing)
|
||||
{
|
||||
return cal.get(Calendar.DAY_OF_YEAR)
|
||||
+ daysInPriorYears(cal.get(Calendar.YEAR), use1904windowing);
|
||||
return absoluteDay(cal.get(Calendar.YEAR), cal.get(Calendar.DAY_OF_YEAR), use1904windowing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a LocalDateTime, return the number of days since 1900/12/31.
|
||||
*
|
||||
* @return days number of days since 1900/12/31
|
||||
* @param date the Date
|
||||
* @exception IllegalArgumentException if date is invalid
|
||||
*/
|
||||
protected static int absoluteDay(LocalDateTime date, boolean use1904windowing)
|
||||
{
|
||||
return absoluteDay(date.getYear(), date.getDayOfYear(), use1904windowing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a year and day of year, return the number of days since 1900/12/31.
|
||||
*
|
||||
* @return days number of days since 1900/12/31
|
||||
* @param dayOfYear the day of the year
|
||||
* @param year the year
|
||||
* @exception IllegalArgumentException if date is invalid
|
||||
*/
|
||||
private static int absoluteDay(int year, int dayOfYear, boolean use1904windowing) {
|
||||
return dayOfYear + daysInPriorYears(year, use1904windowing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of days in prior years since 1900
|
||||
*
|
||||
@ -629,7 +832,7 @@ public class DateUtil {
|
||||
* @exception IllegalArgumentException if year is outside of range.
|
||||
*/
|
||||
|
||||
private static int daysInPriorYears(int yr, boolean use1904windowing)
|
||||
static int daysInPriorYears(int yr, boolean use1904windowing)
|
||||
{
|
||||
if ((!use1904windowing && yr < 1900) || (use1904windowing && yr < 1904)) {
|
||||
throw new IllegalArgumentException("'year' must be 1900 or greater");
|
||||
|
@ -19,6 +19,7 @@ package org.apache.poi.xssf.streaming;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
@ -185,7 +186,15 @@ public class SXSSFCell extends CellBase {
|
||||
setCellValue(DateUtil.getExcelDate(value, date1904));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void setCellValueImpl(LocalDateTime value) {
|
||||
boolean date1904 = getSheet().getWorkbook().isDate1904();
|
||||
setCellValue(DateUtil.getExcelDate(value, date1904));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@ -367,6 +376,27 @@ public class SXSSFCell extends CellBase {
|
||||
return DateUtil.getJavaDate(value, date1904);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the cell as a LocalDateTime.
|
||||
* <p>
|
||||
* For strings we throw an exception. For blank cells we return a null.
|
||||
* </p>
|
||||
* @return the value of the cell as a date
|
||||
* @throws IllegalStateException if the cell type returned by {@link #getCellType()} is CellType.STRING
|
||||
* @exception NumberFormatException if the cell value isn't a parsable <code>double</code>.
|
||||
* @see org.apache.poi.ss.usermodel.DataFormatter for formatting this date into a string similar to how excel does.
|
||||
*/
|
||||
@Override
|
||||
public LocalDateTime getLocalDateTimeCellValue() {
|
||||
if (getCellType() == CellType.BLANK) {
|
||||
return null;
|
||||
}
|
||||
|
||||
double value = getNumericCellValue();
|
||||
boolean date1904 = getSheet().getWorkbook().isDate1904();
|
||||
return DateUtil.getLocalDateTime(value, date1904);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the cell as a XSSFRichTextString
|
||||
* <p>
|
||||
|
@ -19,6 +19,7 @@ package org.apache.poi.xssf.usermodel;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
@ -762,6 +763,27 @@ public final class XSSFCell extends CellBase {
|
||||
return DateUtil.getJavaDate(value, date1904);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the cell as a LocalDateTime.
|
||||
* <p>
|
||||
* For strings we throw an exception. For blank cells we return a null.
|
||||
* </p>
|
||||
* @return the value of the cell as a LocalDateTime
|
||||
* @throws IllegalStateException if the cell type returned by {@link #getCellType()} is {@link CellType#STRING}
|
||||
* @exception NumberFormatException if the cell value isn't a parsable <code>double</code>.
|
||||
* @see DataFormatter for formatting this date into a string similar to how excel does.
|
||||
*/
|
||||
@Override
|
||||
public LocalDateTime getLocalDateTimeCellValue() {
|
||||
if (getCellType() == CellType.BLANK) {
|
||||
return null;
|
||||
}
|
||||
|
||||
double value = getNumericCellValue();
|
||||
boolean date1904 = getSheet().getWorkbook().isDate1904();
|
||||
return DateUtil.getLocalDateTime(value, date1904);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@ -771,6 +793,15 @@ public final class XSSFCell extends CellBase {
|
||||
setCellValue(DateUtil.getExcelDate(value, date1904));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void setCellValueImpl(LocalDateTime value) {
|
||||
boolean date1904 = getSheet().getWorkbook().isDate1904();
|
||||
setCellValue(DateUtil.getExcelDate(value, date1904));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
@ -28,6 +28,7 @@ import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
@ -439,7 +440,7 @@ public final class TestCellStyle extends TestCase {
|
||||
Cell cell = row.getCell(idxCell);
|
||||
cell.getCellStyle().getDataFormatString();
|
||||
if (cell.getCellType() == CellType.NUMERIC) {
|
||||
boolean isDate = HSSFDateUtil.isCellDateFormatted(cell);
|
||||
boolean isDate = DateUtil.isCellDateFormatted(cell);
|
||||
if (idxCell > 0 && isDate) {
|
||||
fail("cell " + idxCell + " is not a date: " + idxCell);
|
||||
}
|
||||
|
@ -729,7 +729,7 @@ public final class TestFormulas {
|
||||
c.setCellStyle(cellStyle);
|
||||
|
||||
// assertEquals("Checking hour = " + hour, date.getTime().getTime(),
|
||||
// HSSFDateUtil.getJavaDate(excelDate).getTime());
|
||||
// DateUtil.getJavaDate(excelDate).getTime());
|
||||
|
||||
for (int k=1; k < 100; k++) {
|
||||
r=s.createRow(k);
|
||||
|
@ -17,25 +17,12 @@
|
||||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import static java.util.Calendar.AUGUST;
|
||||
import static java.util.Calendar.FEBRUARY;
|
||||
import static java.util.Calendar.JANUARY;
|
||||
import static java.util.Calendar.JULY;
|
||||
import static java.util.Calendar.MARCH;
|
||||
import static java.util.Calendar.MAY;
|
||||
import static java.util.Calendar.OCTOBER;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
@ -63,289 +50,6 @@ public class TestHSSFDateUtil {
|
||||
public static void resetTimeZone() {
|
||||
LocaleUtil.setUserTimeZone(userTimeZone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the date conversion functions in the HSSFDateUtil class.
|
||||
*/
|
||||
@Test
|
||||
public void dateConversion() {
|
||||
|
||||
// Iteratating over the hours exposes any rounding issues.
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(2002,JANUARY,1,0,1,1);
|
||||
for (int hour = 0; hour < 23; hour++) {
|
||||
double excelDate = HSSFDateUtil.getExcelDate(cal.getTime(), false);
|
||||
|
||||
assertEquals("Checking hour = " + hour, cal.getTime().getTime(),
|
||||
HSSFDateUtil.getJavaDate(excelDate, false).getTime());
|
||||
|
||||
cal.add(Calendar.HOUR_OF_DAY, 1);
|
||||
}
|
||||
|
||||
// check 1900 and 1904 date windowing conversions
|
||||
double excelDate = 36526.0;
|
||||
// with 1900 windowing, excelDate is Jan. 1, 2000
|
||||
// with 1904 windowing, excelDate is Jan. 2, 2004
|
||||
cal.set(2000,JANUARY,1,0,0,0); // Jan. 1, 2000
|
||||
Date dateIf1900 = cal.getTime();
|
||||
cal.add(Calendar.YEAR,4); // now Jan. 1, 2004
|
||||
cal.add(Calendar.DATE,1); // now Jan. 2, 2004
|
||||
Date dateIf1904 = cal.getTime();
|
||||
// 1900 windowing
|
||||
assertEquals("Checking 1900 Date Windowing",
|
||||
dateIf1900.getTime(),
|
||||
HSSFDateUtil.getJavaDate(excelDate,false).getTime());
|
||||
// 1904 windowing
|
||||
assertEquals("Checking 1904 Date Windowing",
|
||||
dateIf1904.getTime(),
|
||||
HSSFDateUtil.getJavaDate(excelDate,true).getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the conversion of a java.util.date to Excel on a day when
|
||||
* Daylight Saving Time starts.
|
||||
*/
|
||||
@Test
|
||||
public void excelConversionOnDSTStart() {
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(2004,MARCH,28,0,0,0);
|
||||
for (int hour = 0; hour < 24; hour++) {
|
||||
|
||||
// Skip 02:00 CET as that is the Daylight change time
|
||||
// and Java converts it automatically to 03:00 CEST
|
||||
if (hour == 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cal.set(Calendar.HOUR_OF_DAY, hour);
|
||||
Date javaDate = cal.getTime();
|
||||
|
||||
|
||||
double excelDate = HSSFDateUtil.getExcelDate(javaDate, false);
|
||||
double difference = excelDate - Math.floor(excelDate);
|
||||
int differenceInHours = (int) (difference * 24 * 60 + 0.5) / 60;
|
||||
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
|
||||
hour,
|
||||
differenceInHours);
|
||||
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
|
||||
javaDate.getTime(),
|
||||
HSSFDateUtil.getJavaDate(excelDate, false).getTime());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the conversion of an Excel date to a java.util.date on a day when
|
||||
* Daylight Saving Time starts.
|
||||
*/
|
||||
@Test
|
||||
public void javaConversionOnDSTStart() {
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(2004,MARCH,28,0,0,0);
|
||||
double excelDate = HSSFDateUtil.getExcelDate(cal.getTime(), false);
|
||||
double oneHour = 1.0 / 24;
|
||||
double oneMinute = oneHour / 60;
|
||||
for (int hour = 0; hour < 24; hour++, excelDate += oneHour) {
|
||||
|
||||
// Skip 02:00 CET as that is the Daylight change time
|
||||
// and Java converts it automatically to 03:00 CEST
|
||||
if (hour == 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cal.set(Calendar.HOUR_OF_DAY, hour);
|
||||
Date javaDate = HSSFDateUtil.getJavaDate(excelDate, false);
|
||||
double actDate = HSSFDateUtil.getExcelDate(javaDate, false);
|
||||
assertEquals("Checking " + hour + " hours on Daylight Saving Time start date",
|
||||
excelDate, actDate, oneMinute);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the conversion of a java.util.Date to Excel on a day when
|
||||
* Daylight Saving Time ends.
|
||||
*/
|
||||
@Test
|
||||
public void excelConversionOnDSTEnd() {
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(2004,OCTOBER,31,0,0,0);
|
||||
for (int hour = 0; hour < 24; hour++) {
|
||||
cal.set(Calendar.HOUR_OF_DAY, hour);
|
||||
Date javaDate = cal.getTime();
|
||||
double excelDate = HSSFDateUtil.getExcelDate(javaDate, false);
|
||||
double difference = excelDate - Math.floor(excelDate);
|
||||
int differenceInHours = (int) (difference * 24 * 60 + 0.5) / 60;
|
||||
assertEquals("Checking " + hour + " hour on Daylight Saving Time end date",
|
||||
hour,
|
||||
differenceInHours);
|
||||
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
|
||||
javaDate.getTime(),
|
||||
HSSFDateUtil.getJavaDate(excelDate, false).getTime());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the conversion of an Excel date to java.util.Date on a day when
|
||||
* Daylight Saving Time ends.
|
||||
*/
|
||||
@Test
|
||||
public void javaConversionOnDSTEnd() {
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(2004,OCTOBER,31,0,0,0);
|
||||
double excelDate = HSSFDateUtil.getExcelDate(cal.getTime(), false);
|
||||
double oneHour = 1.0 / 24;
|
||||
double oneMinute = oneHour / 60;
|
||||
for (int hour = 0; hour < 24; hour++, excelDate += oneHour) {
|
||||
cal.set(Calendar.HOUR_OF_DAY, hour);
|
||||
Date javaDate = HSSFDateUtil.getJavaDate(excelDate, false);
|
||||
assertEquals("Checking " + hour + " hours on Daylight Saving Time start date",
|
||||
excelDate,
|
||||
HSSFDateUtil.getExcelDate(javaDate, false), oneMinute);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that we deal with time-zones properly
|
||||
*/
|
||||
@Test
|
||||
public void calendarConversion() {
|
||||
TimeZone userTZ = LocaleUtil.getUserTimeZone();
|
||||
LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
|
||||
try {
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(2002,JANUARY,1,12,1,1);
|
||||
Date expected = cal.getTime();
|
||||
|
||||
// Iterating over the hours exposes any rounding issues.
|
||||
for (int hour = -12; hour <= 12; hour++)
|
||||
{
|
||||
String id = "GMT" + (hour < 0 ? "" : "+") + hour + ":00";
|
||||
cal.setTimeZone(TimeZone.getTimeZone(id));
|
||||
cal.set(Calendar.HOUR_OF_DAY, 12);
|
||||
double excelDate = HSSFDateUtil.getExcelDate(cal, false);
|
||||
Date javaDate = HSSFDateUtil.getJavaDate(excelDate);
|
||||
|
||||
// Should match despite time-zone
|
||||
assertEquals("Checking timezone " + id, expected.getTime(), javaDate.getTime());
|
||||
}
|
||||
|
||||
// Check that the timezone aware getter works correctly
|
||||
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
|
||||
TimeZone ldn = TimeZone.getTimeZone("Europe/London");
|
||||
|
||||
// 12:45 on 27th April 2012
|
||||
double excelDate = 41026.53125;
|
||||
|
||||
// Same, no change
|
||||
assertEquals(
|
||||
HSSFDateUtil.getJavaDate(excelDate, false).getTime(),
|
||||
HSSFDateUtil.getJavaDate(excelDate, false, cet).getTime()
|
||||
);
|
||||
|
||||
// London vs Copenhagen, should differ by an hour
|
||||
Date cetDate = HSSFDateUtil.getJavaDate(excelDate, false);
|
||||
Date ldnDate = HSSFDateUtil.getJavaDate(excelDate, false, ldn);
|
||||
assertEquals(ldnDate.getTime() - cetDate.getTime(), 60*60*1000);
|
||||
} finally {
|
||||
LocaleUtil.setUserTimeZone(userTZ);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that we correctly detect date formats as such
|
||||
*/
|
||||
@Test
|
||||
public void identifyDateFormats() {
|
||||
// First up, try with a few built in date formats
|
||||
short[] builtins = new short[] { 0x0e, 0x0f, 0x10, 0x16, 0x2d, 0x2e };
|
||||
for (short builtin : builtins) {
|
||||
String formatStr = HSSFDataFormat.getBuiltinFormat(builtin);
|
||||
assertTrue( HSSFDateUtil.isInternalDateFormat(builtin) );
|
||||
assertTrue( HSSFDateUtil.isADateFormat(builtin,formatStr) );
|
||||
}
|
||||
|
||||
// Now try a few built-in non date formats
|
||||
builtins = new short[] { 0x01, 0x02, 0x17, 0x1f, 0x30 };
|
||||
for (short builtin : builtins) {
|
||||
String formatStr = HSSFDataFormat.getBuiltinFormat(builtin);
|
||||
assertFalse( HSSFDateUtil.isInternalDateFormat(builtin) );
|
||||
assertFalse( HSSFDateUtil.isADateFormat(builtin,formatStr) );
|
||||
}
|
||||
|
||||
// Now for some non-internal ones
|
||||
// These come after the real ones
|
||||
int numBuiltins = HSSFDataFormat.getNumberOfBuiltinBuiltinFormats();
|
||||
assertTrue(numBuiltins < 60);
|
||||
short formatId = 60;
|
||||
assertFalse( HSSFDateUtil.isInternalDateFormat(formatId) );
|
||||
|
||||
// Valid ones first
|
||||
String[] formats = new String[] {
|
||||
"yyyy-mm-dd", "yyyy/mm/dd", "yy/mm/dd", "yy/mmm/dd",
|
||||
"dd/mm/yy", "dd/mm/yyyy", "dd/mmm/yy",
|
||||
"dd-mm-yy", "dd-mm-yyyy",
|
||||
"DD-MM-YY", "DD-mm-YYYY",
|
||||
"dd\\-mm\\-yy", // Sometimes escaped
|
||||
"dd.mm.yyyy", "dd\\.mm\\.yyyy",
|
||||
"dd\\ mm\\.yyyy AM", "dd\\ mm\\.yyyy pm",
|
||||
"dd\\ mm\\.yyyy\\-dd", "[h]:mm:ss",
|
||||
"mm/dd/yy", "\"mm\"/\"dd\"/\"yy\"",
|
||||
"m\\/d\\/yyyy",
|
||||
|
||||
// These crazy ones are valid
|
||||
"yyyy-mm-dd;@", "yyyy/mm/dd;@",
|
||||
"dd-mm-yy;@", "dd-mm-yyyy;@",
|
||||
// These even crazier ones are also valid
|
||||
// (who knows what they mean though...)
|
||||
"[$-F800]dddd\\,\\ mmm\\ dd\\,\\ yyyy",
|
||||
"[$-F900]ddd/mm/yyy",
|
||||
// These ones specify colours, who knew that was allowed?
|
||||
"[BLACK]dddd/mm/yy",
|
||||
"[yeLLow]yyyy-mm-dd"
|
||||
};
|
||||
for (String format : formats) {
|
||||
assertTrue(
|
||||
format + " is a date format",
|
||||
HSSFDateUtil.isADateFormat(formatId, format)
|
||||
);
|
||||
}
|
||||
|
||||
// Then time based ones too
|
||||
formats = new String[] {
|
||||
"yyyy-mm-dd hh:mm:ss", "yyyy/mm/dd HH:MM:SS",
|
||||
"mm/dd HH:MM", "yy/mmm/dd SS",
|
||||
"mm/dd HH:MM AM", "mm/dd HH:MM am",
|
||||
"mm/dd HH:MM PM", "mm/dd HH:MM pm",
|
||||
"m/d/yy h:mm AM/PM",
|
||||
"hh:mm:ss", "hh:mm:ss.0", "mm:ss.0",
|
||||
//support elapsed time [h],[m],[s]
|
||||
"[hh]", "[mm]", "[ss]", "[SS]", "[red][hh]"
|
||||
};
|
||||
for (String format : formats) {
|
||||
assertTrue(
|
||||
format + " is a datetime format",
|
||||
HSSFDateUtil.isADateFormat(formatId, format)
|
||||
);
|
||||
}
|
||||
|
||||
// Then invalid ones
|
||||
formats = new String[] {
|
||||
"yyyy*mm*dd",
|
||||
"0.0", "0.000",
|
||||
"0%", "0.0%",
|
||||
"[]Foo", "[BLACK]0.00%",
|
||||
"[ms]", "[Mh]",
|
||||
"", null
|
||||
};
|
||||
for (String format : formats) {
|
||||
assertFalse(
|
||||
format + " is not a date or datetime format",
|
||||
HSSFDateUtil.isADateFormat(formatId, format)
|
||||
);
|
||||
}
|
||||
|
||||
// And these are ones we probably shouldn't allow,
|
||||
// but would need a better regexp
|
||||
formats = new String[] {
|
||||
"yyyy:mm:dd",
|
||||
};
|
||||
for (String format : formats) {
|
||||
// assertFalse( HSSFDateUtil.isADateFormat(formatId, formats[i]) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that against a real, test file, we still do everything
|
||||
@ -374,217 +78,42 @@ public class TestHSSFDateUtil {
|
||||
style = cell.getCellStyle();
|
||||
assertEquals(aug_10_2007, cell.getNumericCellValue(), 0.0001);
|
||||
assertEquals("d-mmm-yy", style.getDataFormatString());
|
||||
assertTrue(HSSFDateUtil.isInternalDateFormat(style.getDataFormat()));
|
||||
assertTrue(HSSFDateUtil.isADateFormat(style.getDataFormat(), style.getDataFormatString()));
|
||||
assertTrue(HSSFDateUtil.isCellDateFormatted(cell));
|
||||
assertTrue(DateUtil.isInternalDateFormat(style.getDataFormat()));
|
||||
assertTrue(DateUtil.isADateFormat(style.getDataFormat(), style.getDataFormatString()));
|
||||
assertTrue(DateUtil.isCellDateFormatted(cell));
|
||||
|
||||
row = sheet.getRow(1);
|
||||
cell = row.getCell(1);
|
||||
style = cell.getCellStyle();
|
||||
assertEquals(aug_10_2007, cell.getNumericCellValue(), 0.0001);
|
||||
assertFalse(HSSFDateUtil.isInternalDateFormat(cell.getCellStyle().getDataFormat()));
|
||||
assertTrue(HSSFDateUtil.isADateFormat(style.getDataFormat(), style.getDataFormatString()));
|
||||
assertTrue(HSSFDateUtil.isCellDateFormatted(cell));
|
||||
assertFalse(DateUtil.isInternalDateFormat(cell.getCellStyle().getDataFormat()));
|
||||
assertTrue(DateUtil.isADateFormat(style.getDataFormat(), style.getDataFormatString()));
|
||||
assertTrue(DateUtil.isCellDateFormatted(cell));
|
||||
|
||||
row = sheet.getRow(2);
|
||||
cell = row.getCell(1);
|
||||
style = cell.getCellStyle();
|
||||
assertEquals(aug_10_2007, cell.getNumericCellValue(), 0.0001);
|
||||
assertTrue(HSSFDateUtil.isInternalDateFormat(cell.getCellStyle().getDataFormat()));
|
||||
assertTrue(HSSFDateUtil.isADateFormat(style.getDataFormat(), style.getDataFormatString()));
|
||||
assertTrue(HSSFDateUtil.isCellDateFormatted(cell));
|
||||
assertTrue(DateUtil.isInternalDateFormat(cell.getCellStyle().getDataFormat()));
|
||||
assertTrue(DateUtil.isADateFormat(style.getDataFormat(), style.getDataFormatString()));
|
||||
assertTrue(DateUtil.isCellDateFormatted(cell));
|
||||
|
||||
row = sheet.getRow(3);
|
||||
cell = row.getCell(1);
|
||||
style = cell.getCellStyle();
|
||||
assertEquals(aug_10_2007, cell.getNumericCellValue(), 0.0001);
|
||||
assertFalse(HSSFDateUtil.isInternalDateFormat(cell.getCellStyle().getDataFormat()));
|
||||
assertTrue(HSSFDateUtil.isADateFormat(style.getDataFormat(), style.getDataFormatString()));
|
||||
assertTrue(HSSFDateUtil.isCellDateFormatted(cell));
|
||||
assertFalse(DateUtil.isInternalDateFormat(cell.getCellStyle().getDataFormat()));
|
||||
assertTrue(DateUtil.isADateFormat(style.getDataFormat(), style.getDataFormatString()));
|
||||
assertTrue(DateUtil.isCellDateFormatted(cell));
|
||||
|
||||
row = sheet.getRow(4);
|
||||
cell = row.getCell(1);
|
||||
style = cell.getCellStyle();
|
||||
assertEquals(aug_10_2007, cell.getNumericCellValue(), 0.0001);
|
||||
assertFalse(HSSFDateUtil.isInternalDateFormat(cell.getCellStyle().getDataFormat()));
|
||||
assertTrue(HSSFDateUtil.isADateFormat(style.getDataFormat(), style.getDataFormatString()));
|
||||
assertTrue(HSSFDateUtil.isCellDateFormatted(cell));
|
||||
|
||||
assertFalse(DateUtil.isInternalDateFormat(cell.getCellStyle().getDataFormat()));
|
||||
assertTrue(DateUtil.isADateFormat(style.getDataFormat(), style.getDataFormatString()));
|
||||
assertTrue(DateUtil.isCellDateFormatted(cell));
|
||||
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void excelDateBorderCases() throws ParseException {
|
||||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd", Locale.ROOT);
|
||||
df.setTimeZone(LocaleUtil.getUserTimeZone());
|
||||
|
||||
assertEquals(1.0, DateUtil.getExcelDate(df.parse("1900-01-01")), 0.00001);
|
||||
assertEquals(31.0, DateUtil.getExcelDate(df.parse("1900-01-31")), 0.00001);
|
||||
assertEquals(32.0, DateUtil.getExcelDate(df.parse("1900-02-01")), 0.00001);
|
||||
assertEquals(/* BAD_DATE! */ -1.0, DateUtil.getExcelDate(df.parse("1899-12-31")), 0.00001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dateBug_2Excel() {
|
||||
assertEquals(59.0, HSSFDateUtil.getExcelDate(createDate(1900, FEBRUARY, 28), false), 0.00001);
|
||||
assertEquals(61.0, HSSFDateUtil.getExcelDate(createDate(1900, MARCH, 1), false), 0.00001);
|
||||
|
||||
assertEquals(37315.00, HSSFDateUtil.getExcelDate(createDate(2002, FEBRUARY, 28), false), 0.00001);
|
||||
assertEquals(37316.00, HSSFDateUtil.getExcelDate(createDate(2002, MARCH, 1), false), 0.00001);
|
||||
assertEquals(37257.00, HSSFDateUtil.getExcelDate(createDate(2002, JANUARY, 1), false), 0.00001);
|
||||
assertEquals(38074.00, HSSFDateUtil.getExcelDate(createDate(2004, MARCH, 28), false), 0.00001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dateBug_2Java() {
|
||||
assertEquals(createDate(1900, FEBRUARY, 28), HSSFDateUtil.getJavaDate(59.0, false));
|
||||
assertEquals(createDate(1900, MARCH, 1), HSSFDateUtil.getJavaDate(61.0, false));
|
||||
|
||||
assertEquals(createDate(2002, FEBRUARY, 28), HSSFDateUtil.getJavaDate(37315.00, false));
|
||||
assertEquals(createDate(2002, MARCH, 1), HSSFDateUtil.getJavaDate(37316.00, false));
|
||||
assertEquals(createDate(2002, JANUARY, 1), HSSFDateUtil.getJavaDate(37257.00, false));
|
||||
assertEquals(createDate(2004, MARCH, 28), HSSFDateUtil.getJavaDate(38074.00, false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void date1904() {
|
||||
assertEquals(createDate(1904, JANUARY, 2), HSSFDateUtil.getJavaDate(1.0, true));
|
||||
assertEquals(createDate(1904, JANUARY, 1), HSSFDateUtil.getJavaDate(0.0, true));
|
||||
assertEquals(0.0, HSSFDateUtil.getExcelDate(createDate(1904, JANUARY, 1), true), 0.00001);
|
||||
assertEquals(1.0, HSSFDateUtil.getExcelDate(createDate(1904, JANUARY, 2), true), 0.00001);
|
||||
|
||||
assertEquals(createDate(1998, JULY, 5), HSSFDateUtil.getJavaDate(35981, false));
|
||||
assertEquals(createDate(1998, JULY, 5), HSSFDateUtil.getJavaDate(34519, true));
|
||||
|
||||
assertEquals(35981.0, HSSFDateUtil.getExcelDate(createDate(1998, JULY, 5), false), 0.00001);
|
||||
assertEquals(34519.0, HSSFDateUtil.getExcelDate(createDate(1998, JULY, 5), true), 0.00001);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param month zero based
|
||||
* @param day one based
|
||||
*/
|
||||
private static Date createDate(int year, int month, int day) {
|
||||
return createDate(year, month, day, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param month zero based
|
||||
* @param day one based
|
||||
*/
|
||||
private static Date createDate(int year, int month, int day, int hour, int minute, int second) {
|
||||
Calendar c = LocaleUtil.getLocaleCalendar(year, month, day, hour, minute, second);
|
||||
return c.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if HSSFDateUtil.getAbsoluteDay works as advertised.
|
||||
*/
|
||||
@Test
|
||||
public void absoluteDay() {
|
||||
// 1 Jan 1900 is 1 day after 31 Dec 1899
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(1900,JANUARY,1,0,0,0);
|
||||
assertEquals("Checking absolute day (1 Jan 1900)", 1, HSSFDateUtil.absoluteDay(cal, false));
|
||||
// 1 Jan 1901 is 366 days after 31 Dec 1899
|
||||
cal.set(1901,JANUARY,1,0,0,0);
|
||||
assertEquals("Checking absolute day (1 Jan 1901)", 366, HSSFDateUtil.absoluteDay(cal, false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void absoluteDayYearTooLow() {
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(1899,JANUARY,1,0,0,0);
|
||||
try {
|
||||
HSSFDateUtil.absoluteDay(cal, false);
|
||||
fail("Should fail here");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected here
|
||||
}
|
||||
|
||||
try {
|
||||
cal.set(1903,JANUARY,1,0,0,0);
|
||||
HSSFDateUtil.absoluteDay(cal, true);
|
||||
fail("Should fail here");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected here
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertTime() {
|
||||
|
||||
final double delta = 1E-7; // a couple of digits more accuracy than strictly required
|
||||
assertEquals(0.5, HSSFDateUtil.convertTime("12:00"), delta);
|
||||
assertEquals(2.0/3, HSSFDateUtil.convertTime("16:00"), delta);
|
||||
assertEquals(0.0000116, HSSFDateUtil.convertTime("0:00:01"), delta);
|
||||
assertEquals(0.7330440, HSSFDateUtil.convertTime("17:35:35"), delta);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseDate() {
|
||||
assertEquals(createDate(2008, AUGUST, 3), HSSFDateUtil.parseYYYYMMDDDate("2008/08/03"));
|
||||
assertEquals(createDate(1994, MAY, 1), HSSFDateUtil.parseYYYYMMDDDate("1994/05/01"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that date values *with* a fractional portion get the right time of day
|
||||
*/
|
||||
@Test
|
||||
public void convertDateTime() {
|
||||
// Excel day 30000 is date 18-Feb-1982
|
||||
// 0.7 corresponds to time 16:48:00
|
||||
Date actual = HSSFDateUtil.getJavaDate(30000.7);
|
||||
Date expected = createDate(1982, 1, 18, 16, 48, 0);
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* User reported a datetime issue in POI-2.5:
|
||||
* Setting Cell's value to Jan 1, 1900 without a time doesn't return the same value set to
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void bug19172() throws IOException
|
||||
{
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||
HSSFSheet sheet = workbook.createSheet();
|
||||
HSSFCell cell = sheet.createRow(0).createCell(0);
|
||||
|
||||
// A pseudo special Excel dates
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(1900, JANUARY, 1);
|
||||
|
||||
Date valueToTest = cal.getTime();
|
||||
|
||||
cell.setCellValue(valueToTest);
|
||||
|
||||
Date returnedValue = cell.getDateCellValue();
|
||||
|
||||
assertEquals(valueToTest.getTime(), returnedValue.getTime());
|
||||
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* DateUtil.isCellFormatted(Cell) should not true for a numeric cell
|
||||
* that's formatted as ".0000"
|
||||
*/
|
||||
@Test
|
||||
public void bug54557() throws Exception {
|
||||
final String format = ".0000";
|
||||
boolean isDateFormat = HSSFDateUtil.isADateFormat(165, format);
|
||||
|
||||
assertEquals(false, isDateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bug56269() throws Exception {
|
||||
double excelFraction = 41642.45833321759d;
|
||||
Calendar calNoRound = HSSFDateUtil.getJavaCalendar(excelFraction, false);
|
||||
assertEquals(10, calNoRound.get(Calendar.HOUR));
|
||||
assertEquals(59, calNoRound.get(Calendar.MINUTE));
|
||||
assertEquals(59, calNoRound.get(Calendar.SECOND));
|
||||
Calendar calRound = HSSFDateUtil.getJavaCalendar(excelFraction, false, null, true);
|
||||
assertEquals(11, calRound.get(Calendar.HOUR));
|
||||
assertEquals(0, calRound.get(Calendar.MINUTE));
|
||||
assertEquals(0, calRound.get(Calendar.SECOND));
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import org.apache.poi.hssf.model.InternalSheet;
|
||||
import org.apache.poi.hssf.record.BOFRecord;
|
||||
import org.apache.poi.hssf.record.EOFRecord;
|
||||
import org.apache.poi.hssf.record.RecordBase;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.util.LocaleUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -49,7 +50,7 @@ public final class TestReadWriteChart {
|
||||
|
||||
//System.out.println("first assertion for date");
|
||||
Calendar calExp = LocaleUtil.getLocaleCalendar(2000, 0, 1, 10, 51, 2);
|
||||
Date dateAct = HSSFDateUtil.getJavaDate(firstCell.getNumericCellValue(), false);
|
||||
Date dateAct = DateUtil.getJavaDate(firstCell.getNumericCellValue(), false);
|
||||
assertEquals(calExp.getTime(), dateAct);
|
||||
HSSFRow row = sheet.createRow(15);
|
||||
HSSFCell cell = row.createCell(1);
|
||||
|
@ -26,13 +26,13 @@ import java.util.Iterator;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
|
||||
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
|
||||
import org.apache.poi.hssf.usermodel.HSSFRow;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.formula.eval.EvaluationException;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.util.LocaleUtil;
|
||||
import org.junit.Test;
|
||||
@ -97,7 +97,7 @@ public final class TestYearFracCalculatorFromSpreadsheet {
|
||||
int month = getIntCell(row, yearColumn + 1);
|
||||
int day = getIntCell(row, yearColumn + 2);
|
||||
Calendar c = LocaleUtil.getLocaleCalendar(year, month-1, day);
|
||||
return HSSFDateUtil.getExcelDate(c.getTime());
|
||||
return DateUtil.getExcelDate(c.getTime());
|
||||
}
|
||||
|
||||
private static int getIntCell(HSSFRow row, int colIx) {
|
||||
|
@ -24,10 +24,10 @@ import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
|
||||
import org.apache.poi.ss.formula.eval.BoolEval;
|
||||
import org.apache.poi.ss.formula.eval.NumberEval;
|
||||
import org.apache.poi.ss.formula.eval.ValueEval;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.util.LocaleUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -160,6 +160,6 @@ public final class TestDays360 {
|
||||
}
|
||||
|
||||
private static NumberEval convert(Date d) {
|
||||
return new NumberEval(HSSFDateUtil.getExcelDate(d));
|
||||
return new NumberEval(DateUtil.getExcelDate(d));
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,8 @@ import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
@ -113,6 +115,26 @@ public abstract class BaseTestCell {
|
||||
assertProhibitedValueAccess(cell, CellType.BOOLEAN, CellType.STRING,
|
||||
CellType.FORMULA, CellType.ERROR);
|
||||
|
||||
cell.setCellErrorValue(FormulaError.NA.getCode());
|
||||
assertEquals(FormulaError.NA.getCode(), cell.getErrorCellValue());
|
||||
assertEquals(CellType.ERROR, cell.getCellType());
|
||||
assertProhibitedValueAccess(cell, CellType.NUMERIC, CellType.BOOLEAN,
|
||||
CellType.FORMULA, CellType.STRING);
|
||||
|
||||
LocalDateTime ldt = DateUtil.toLocalDateTime(c);
|
||||
cell.setCellValue(ldt);
|
||||
assertEquals(ldt, cell.getLocalDateTimeCellValue());
|
||||
assertEquals(CellType.NUMERIC, cell.getCellType());
|
||||
assertProhibitedValueAccess(cell, CellType.BOOLEAN, CellType.STRING,
|
||||
CellType.FORMULA, CellType.ERROR);
|
||||
|
||||
LocalDate ld = ldt.toLocalDate();
|
||||
cell.setCellValue(ld);
|
||||
assertEquals(ld, cell.getLocalDateTimeCellValue().toLocalDate());
|
||||
assertEquals(CellType.NUMERIC, cell.getCellType());
|
||||
assertProhibitedValueAccess(cell, CellType.BOOLEAN, CellType.STRING,
|
||||
CellType.FORMULA, CellType.ERROR);
|
||||
|
||||
cell.setCellErrorValue(FormulaError.NA.getCode());
|
||||
assertEquals(FormulaError.NA.getCode(), cell.getErrorCellValue());
|
||||
assertEquals(CellType.ERROR, cell.getCellType());
|
||||
|
@ -17,18 +17,43 @@
|
||||
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static java.util.Calendar.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.hssf.model.InternalWorkbook;
|
||||
import org.apache.poi.hssf.usermodel.*;
|
||||
import org.apache.poi.util.LocaleUtil;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TestDateUtil {
|
||||
|
||||
static TimeZone userTimeZone;
|
||||
|
||||
@BeforeClass
|
||||
public static void setCEST() {
|
||||
userTimeZone = LocaleUtil.getUserTimeZone();
|
||||
LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CEST"));
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void resetTimeZone() {
|
||||
LocaleUtil.setUserTimeZone(userTimeZone);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getJavaDate_InvalidValue() {
|
||||
double dateValue = -1;
|
||||
@ -93,6 +118,32 @@ public class TestDateUtil {
|
||||
assertEquals(expCal, actCal[2]);
|
||||
assertEquals(expCal, actCal[3]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLocalDateTime_InvalidValue() {
|
||||
double dateValue = -1;
|
||||
TimeZone tz = LocaleUtil.getUserTimeZone();
|
||||
boolean use1904windowing = false;
|
||||
boolean roundSeconds = false;
|
||||
|
||||
assertEquals(null, DateUtil.getLocalDateTime(dateValue));
|
||||
assertEquals(null, DateUtil.getLocalDateTime(dateValue, use1904windowing));
|
||||
assertEquals(null, DateUtil.getLocalDateTime(dateValue, use1904windowing, roundSeconds));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLocalDateTime_ValidValue() {
|
||||
double dateValue = 0;
|
||||
boolean use1904windowing = false;
|
||||
boolean roundSeconds = false;
|
||||
|
||||
// note that the Date and Calendar examples use a zero day of month which is invalid in LocalDateTime
|
||||
LocalDateTime date = LocalDateTime.of(1899, 12, 31, 0, 0);
|
||||
|
||||
assertEquals(date, DateUtil.getLocalDateTime(dateValue));
|
||||
assertEquals(date, DateUtil.getLocalDateTime(dateValue, use1904windowing));
|
||||
assertEquals(date, DateUtil.getLocalDateTime(dateValue, use1904windowing, roundSeconds));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isADateFormat() {
|
||||
@ -123,4 +174,571 @@ public class TestDateUtil {
|
||||
// Cell show "2016年12月8日"
|
||||
assertTrue(DateUtil.isADateFormat(178, "[DBNum3][$-804]yyyy\"\u5e74\"m\"\u6708\"d\"\u65e5\";@"));
|
||||
}
|
||||
/**
|
||||
* Checks the date conversion functions in the DateUtil class.
|
||||
*/
|
||||
@Test
|
||||
public void dateConversion() {
|
||||
|
||||
// Iteratating over the hours exposes any rounding issues.
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(2002,JANUARY,1,0,1,1);
|
||||
for (int hour = 0; hour < 24; hour++) {
|
||||
double excelDate = DateUtil.getExcelDate(cal.getTime(), false);
|
||||
|
||||
assertEquals("getJavaDate: Checking hour = " + hour, cal.getTime().getTime(),
|
||||
DateUtil.getJavaDate(excelDate, false).getTime());
|
||||
|
||||
LocalDateTime ldt = LocalDateTime.ofInstant(cal.toInstant(), cal.getTimeZone().toZoneId());
|
||||
assertEquals("getLocalDateTime: Checking hour = " + hour, ldt,
|
||||
DateUtil.getLocalDateTime(excelDate, false));
|
||||
|
||||
cal.add(Calendar.HOUR_OF_DAY, 1);
|
||||
}
|
||||
|
||||
// check 1900 and 1904 date windowing conversions
|
||||
double excelDate = 36526.0;
|
||||
// with 1900 windowing, excelDate is Jan. 1, 2000
|
||||
// with 1904 windowing, excelDate is Jan. 2, 2004
|
||||
cal.set(2000,JANUARY,1,0,0,0); // Jan. 1, 2000
|
||||
Date dateIf1900 = cal.getTime();
|
||||
cal.add(Calendar.YEAR,4); // now Jan. 1, 2004
|
||||
cal.add(Calendar.DATE,1); // now Jan. 2, 2004
|
||||
Date dateIf1904 = cal.getTime();
|
||||
// 1900 windowing
|
||||
assertEquals("Checking 1900 Date Windowing",
|
||||
dateIf1900.getTime(),
|
||||
DateUtil.getJavaDate(excelDate,false).getTime());
|
||||
// 1904 windowing
|
||||
assertEquals("Checking 1904 Date Windowing",
|
||||
dateIf1904.getTime(),
|
||||
DateUtil.getJavaDate(excelDate,true).getTime());
|
||||
// 1900 windowing (LocalDateTime)
|
||||
assertEquals("Checking 1900 Date Windowing",
|
||||
LocalDateTime.of(2000,1,1,0,0),
|
||||
DateUtil.getLocalDateTime(excelDate,false));
|
||||
// 1904 windowing (LocalDateTime)
|
||||
assertEquals("Checking 1904 Date Windowing",
|
||||
LocalDateTime.of(2004,1,2,0,0),
|
||||
DateUtil.getLocalDateTime(excelDate,true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the conversion of a java.util.date to Excel on a day when
|
||||
* Daylight Saving Time starts.
|
||||
*/
|
||||
@Test
|
||||
public void excelConversionOnDSTStart() {
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(2004,MARCH,28,0,0,0);
|
||||
for (int hour = 0; hour < 24; hour++) {
|
||||
|
||||
// Skip 02:00 CET as that is the Daylight change time
|
||||
// and Java converts it automatically to 03:00 CEST
|
||||
if (hour == 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cal.set(Calendar.HOUR_OF_DAY, hour);
|
||||
Date javaDate = cal.getTime();
|
||||
double excelDate = DateUtil.getExcelDate(javaDate, false);
|
||||
double difference = excelDate - Math.floor(excelDate);
|
||||
int differenceInHours = (int) (difference * 24 * 60 + 0.5) / 60;
|
||||
|
||||
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
|
||||
hour,
|
||||
differenceInHours);
|
||||
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
|
||||
javaDate.getTime(),
|
||||
DateUtil.getJavaDate(excelDate, false).getTime());
|
||||
|
||||
// perform the same checks with LocalDateTime
|
||||
LocalDateTime localDate = LocalDateTime.of(2004,3,28,hour,0,0);
|
||||
double excelLocalDate = DateUtil.getExcelDate(localDate, false);
|
||||
double differenceLocalDate = excelLocalDate - Math.floor(excelLocalDate);
|
||||
int differenceLocalDateInHours = (int) (differenceLocalDate * 24 * 60 + 0.5) / 60;
|
||||
|
||||
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date (LocalDateTime)",
|
||||
hour,
|
||||
differenceLocalDateInHours);
|
||||
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date (LocalDateTime)",
|
||||
localDate,
|
||||
DateUtil.getLocalDateTime(excelLocalDate, false));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the conversion of an Excel date to a java.util.date on a day when
|
||||
* Daylight Saving Time starts.
|
||||
*/
|
||||
@Test
|
||||
public void javaConversionOnDSTStart() {
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(2004,MARCH,28,0,0,0);
|
||||
double excelDate = DateUtil.getExcelDate(cal.getTime(), false);
|
||||
double oneHour = 1.0 / 24;
|
||||
double oneMinute = oneHour / 60;
|
||||
for (int hour = 0; hour < 24; hour++, excelDate += oneHour) {
|
||||
|
||||
// Skip 02:00 CET as that is the Daylight change time
|
||||
// and Java converts it automatically to 03:00 CEST
|
||||
if (hour == 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cal.set(Calendar.HOUR_OF_DAY, hour);
|
||||
Date javaDate = DateUtil.getJavaDate(excelDate, false);
|
||||
double actDate = DateUtil.getExcelDate(javaDate, false);
|
||||
assertEquals("Checking " + hour + " hours on Daylight Saving Time start date",
|
||||
excelDate, actDate, oneMinute);
|
||||
|
||||
// perform the same check with LocalDateTime
|
||||
cal.set(Calendar.HOUR_OF_DAY, hour);
|
||||
LocalDateTime localDate = DateUtil.getLocalDateTime(excelDate, false);
|
||||
double actLocalDate = DateUtil.getExcelDate(localDate, false);
|
||||
assertEquals("Checking " + hour + " hours on Daylight Saving Time start date (LocalDateTime)",
|
||||
excelDate, actLocalDate, oneMinute);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the conversion of a java.util.Date to Excel on a day when
|
||||
* Daylight Saving Time ends.
|
||||
*/
|
||||
@Test
|
||||
public void excelConversionOnDSTEnd() {
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(2004,OCTOBER,31,0,0,0);
|
||||
for (int hour = 0; hour < 24; hour++) {
|
||||
cal.set(Calendar.HOUR_OF_DAY, hour);
|
||||
Date javaDate = cal.getTime();
|
||||
double excelDate = DateUtil.getExcelDate(javaDate, false);
|
||||
double difference = excelDate - Math.floor(excelDate);
|
||||
int differenceInHours = (int) (difference * 24 * 60 + 0.5) / 60;
|
||||
assertEquals("Checking " + hour + " hour on Daylight Saving Time end date",
|
||||
hour,
|
||||
differenceInHours);
|
||||
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
|
||||
javaDate.getTime(),
|
||||
DateUtil.getJavaDate(excelDate, false).getTime());
|
||||
|
||||
// perform the same checks using LocalDateTime
|
||||
LocalDateTime localDate = LocalDateTime.of(2004,10,31,hour,0,0);
|
||||
double excelLocalDate = DateUtil.getExcelDate(localDate, false);
|
||||
double differenceLocalDate = excelLocalDate - Math.floor(excelLocalDate);
|
||||
int differenceLocalDateInHours = (int) (difference * 24 * 60 + 0.5) / 60;
|
||||
assertEquals("Checking " + hour + " hour on Daylight Saving Time end date (LocalDateTime)",
|
||||
hour,
|
||||
differenceLocalDateInHours);
|
||||
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date (LocalDateTime)",
|
||||
localDate,
|
||||
DateUtil.getLocalDateTime(excelLocalDate, false));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the conversion of an Excel date to java.util.Date on a day when
|
||||
* Daylight Saving Time ends.
|
||||
*/
|
||||
@Test
|
||||
public void javaConversionOnDSTEnd() {
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(2004,OCTOBER,31,0,0,0);
|
||||
double excelDate = DateUtil.getExcelDate(cal.getTime(), false);
|
||||
double oneHour = 1.0 / 24;
|
||||
double oneMinute = oneHour / 60;
|
||||
for (int hour = 0; hour < 24; hour++, excelDate += oneHour) {
|
||||
cal.set(Calendar.HOUR_OF_DAY, hour);
|
||||
Date javaDate = DateUtil.getJavaDate(excelDate, false);
|
||||
assertEquals("Checking " + hour + " hours on Daylight Saving Time start date",
|
||||
excelDate,
|
||||
DateUtil.getExcelDate(javaDate, false), oneMinute);
|
||||
|
||||
// perform the same checks using LocalDateTime
|
||||
LocalDateTime localDate = DateUtil.getLocalDateTime(excelDate, false);
|
||||
assertEquals("Checking " + hour + " hours on Daylight Saving Time start date",
|
||||
excelDate,
|
||||
DateUtil.getExcelDate(localDate, false), oneMinute);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that we deal with time-zones properly
|
||||
*/
|
||||
@Test
|
||||
public void calendarConversion() {
|
||||
TimeZone userTZ = LocaleUtil.getUserTimeZone();
|
||||
LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
|
||||
try {
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(2002,JANUARY,1,12,1,1);
|
||||
Date expected = cal.getTime();
|
||||
|
||||
// Iterating over the hours exposes any rounding issues.
|
||||
for (int hour = -12; hour <= 12; hour++)
|
||||
{
|
||||
String id = "GMT" + (hour < 0 ? "" : "+") + hour + ":00";
|
||||
cal.setTimeZone(TimeZone.getTimeZone(id));
|
||||
cal.set(Calendar.HOUR_OF_DAY, 12);
|
||||
double excelDate = DateUtil.getExcelDate(cal, false);
|
||||
Date javaDate = DateUtil.getJavaDate(excelDate);
|
||||
|
||||
// Should match despite time-zone
|
||||
assertEquals("Checking timezone " + id, expected.getTime(), javaDate.getTime());
|
||||
}
|
||||
|
||||
// Check that the timezone aware getter works correctly
|
||||
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
|
||||
TimeZone ldn = TimeZone.getTimeZone("Europe/London");
|
||||
|
||||
// 12:45 on 27th April 2012
|
||||
double excelDate = 41026.53125;
|
||||
|
||||
// Same, no change
|
||||
assertEquals(
|
||||
DateUtil.getJavaDate(excelDate, false).getTime(),
|
||||
DateUtil.getJavaDate(excelDate, false, cet).getTime()
|
||||
);
|
||||
|
||||
// London vs Copenhagen, should differ by an hour
|
||||
Date cetDate = DateUtil.getJavaDate(excelDate, false);
|
||||
Date ldnDate = DateUtil.getJavaDate(excelDate, false, ldn);
|
||||
assertEquals(ldnDate.getTime() - cetDate.getTime(), 60*60*1000);
|
||||
} finally {
|
||||
LocaleUtil.setUserTimeZone(userTZ);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that we correctly detect date formats as such
|
||||
*/
|
||||
@Test
|
||||
public void identifyDateFormats() {
|
||||
// First up, try with a few built in date formats
|
||||
short[] builtins = new short[] { 0x0e, 0x0f, 0x10, 0x16, 0x2d, 0x2e };
|
||||
for (short builtin : builtins) {
|
||||
String formatStr = HSSFDataFormat.getBuiltinFormat(builtin);
|
||||
assertTrue( DateUtil.isInternalDateFormat(builtin) );
|
||||
assertTrue( DateUtil.isADateFormat(builtin,formatStr) );
|
||||
}
|
||||
|
||||
// Now try a few built-in non date formats
|
||||
builtins = new short[] { 0x01, 0x02, 0x17, 0x1f, 0x30 };
|
||||
for (short builtin : builtins) {
|
||||
String formatStr = HSSFDataFormat.getBuiltinFormat(builtin);
|
||||
assertFalse( DateUtil.isInternalDateFormat(builtin) );
|
||||
assertFalse( DateUtil.isADateFormat(builtin,formatStr) );
|
||||
}
|
||||
|
||||
// Now for some non-internal ones
|
||||
// These come after the real ones
|
||||
int numBuiltins = HSSFDataFormat.getNumberOfBuiltinBuiltinFormats();
|
||||
assertTrue(numBuiltins < 60);
|
||||
short formatId = 60;
|
||||
assertFalse( DateUtil.isInternalDateFormat(formatId) );
|
||||
|
||||
// Valid ones first
|
||||
String[] formats = new String[] {
|
||||
"yyyy-mm-dd", "yyyy/mm/dd", "yy/mm/dd", "yy/mmm/dd",
|
||||
"dd/mm/yy", "dd/mm/yyyy", "dd/mmm/yy",
|
||||
"dd-mm-yy", "dd-mm-yyyy",
|
||||
"DD-MM-YY", "DD-mm-YYYY",
|
||||
"dd\\-mm\\-yy", // Sometimes escaped
|
||||
"dd.mm.yyyy", "dd\\.mm\\.yyyy",
|
||||
"dd\\ mm\\.yyyy AM", "dd\\ mm\\.yyyy pm",
|
||||
"dd\\ mm\\.yyyy\\-dd", "[h]:mm:ss",
|
||||
"mm/dd/yy", "\"mm\"/\"dd\"/\"yy\"",
|
||||
"m\\/d\\/yyyy",
|
||||
|
||||
// These crazy ones are valid
|
||||
"yyyy-mm-dd;@", "yyyy/mm/dd;@",
|
||||
"dd-mm-yy;@", "dd-mm-yyyy;@",
|
||||
// These even crazier ones are also valid
|
||||
// (who knows what they mean though...)
|
||||
"[$-F800]dddd\\,\\ mmm\\ dd\\,\\ yyyy",
|
||||
"[$-F900]ddd/mm/yyy",
|
||||
// These ones specify colours, who knew that was allowed?
|
||||
"[BLACK]dddd/mm/yy",
|
||||
"[yeLLow]yyyy-mm-dd"
|
||||
};
|
||||
for (String format : formats) {
|
||||
assertTrue(
|
||||
format + " is a date format",
|
||||
DateUtil.isADateFormat(formatId, format)
|
||||
);
|
||||
}
|
||||
|
||||
// Then time based ones too
|
||||
formats = new String[] {
|
||||
"yyyy-mm-dd hh:mm:ss", "yyyy/mm/dd HH:MM:SS",
|
||||
"mm/dd HH:MM", "yy/mmm/dd SS",
|
||||
"mm/dd HH:MM AM", "mm/dd HH:MM am",
|
||||
"mm/dd HH:MM PM", "mm/dd HH:MM pm",
|
||||
"m/d/yy h:mm AM/PM",
|
||||
"hh:mm:ss", "hh:mm:ss.0", "mm:ss.0",
|
||||
//support elapsed time [h],[m],[s]
|
||||
"[hh]", "[mm]", "[ss]", "[SS]", "[red][hh]"
|
||||
};
|
||||
for (String format : formats) {
|
||||
assertTrue(
|
||||
format + " is a datetime format",
|
||||
DateUtil.isADateFormat(formatId, format)
|
||||
);
|
||||
}
|
||||
|
||||
// Then invalid ones
|
||||
formats = new String[] {
|
||||
"yyyy*mm*dd",
|
||||
"0.0", "0.000",
|
||||
"0%", "0.0%",
|
||||
"[]Foo", "[BLACK]0.00%",
|
||||
"[ms]", "[Mh]",
|
||||
"", null
|
||||
};
|
||||
for (String format : formats) {
|
||||
assertFalse(
|
||||
format + " is not a date or datetime format",
|
||||
DateUtil.isADateFormat(formatId, format)
|
||||
);
|
||||
}
|
||||
|
||||
// And these are ones we probably shouldn't allow,
|
||||
// but would need a better regexp
|
||||
formats = new String[] {
|
||||
"yyyy:mm:dd",
|
||||
};
|
||||
for (String format : formats) {
|
||||
// assertFalse( DateUtil.isADateFormat(formatId, formats[i]) );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void excelDateBorderCases() throws ParseException {
|
||||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd", Locale.ROOT);
|
||||
df.setTimeZone(LocaleUtil.getUserTimeZone());
|
||||
|
||||
Date date1 = df.parse("1900-01-01");
|
||||
assertEquals(1.0, DateUtil.getExcelDate(date1), 0.00001);
|
||||
assertEquals(1.0, DateUtil.getExcelDate(DateUtil.toLocalDateTime(date1)), 0.00001);
|
||||
Date date31 = df.parse("1900-01-31");
|
||||
assertEquals(31.0, DateUtil.getExcelDate(date31), 0.00001);
|
||||
assertEquals(31.0, DateUtil.getExcelDate(DateUtil.toLocalDateTime(date31)), 0.00001);
|
||||
Date date32 = df.parse("1900-02-01");
|
||||
assertEquals(32.0, DateUtil.getExcelDate(date32), 0.00001);
|
||||
assertEquals(32.0, DateUtil.getExcelDate(DateUtil.toLocalDateTime(date32)), 0.00001);
|
||||
Date dateMinus1 = df.parse("1899-12-31");
|
||||
assertEquals(/* BAD_DATE! */ -1.0, DateUtil.getExcelDate(dateMinus1), 0.00001);
|
||||
assertEquals(/* BAD_DATE! */ -1.0, DateUtil.getExcelDate(DateUtil.toLocalDateTime(dateMinus1)), 0.00001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dateBug_2Excel() {
|
||||
assertEquals(59.0, DateUtil.getExcelDate(createDate(1900, FEBRUARY, 28), false), 0.00001);
|
||||
assertEquals(61.0, DateUtil.getExcelDate(createDate(1900, MARCH, 1), false), 0.00001);
|
||||
|
||||
assertEquals(37315.00, DateUtil.getExcelDate(createDate(2002, FEBRUARY, 28), false), 0.00001);
|
||||
assertEquals(37316.00, DateUtil.getExcelDate(createDate(2002, MARCH, 1), false), 0.00001);
|
||||
assertEquals(37257.00, DateUtil.getExcelDate(createDate(2002, JANUARY, 1), false), 0.00001);
|
||||
assertEquals(38074.00, DateUtil.getExcelDate(createDate(2004, MARCH, 28), false), 0.00001);
|
||||
|
||||
// perform the same checks using LocalDateTime
|
||||
assertEquals(59.0, DateUtil.getExcelDate(LocalDateTime.of(1900, 2, 28, 0,0), false), 0.00001);
|
||||
assertEquals(61.0, DateUtil.getExcelDate(LocalDateTime.of(1900, 3, 1, 0,0), false), 0.00001);
|
||||
|
||||
assertEquals(37315.00, DateUtil.getExcelDate(LocalDateTime.of(2002, 2, 28, 0,0), false), 0.00001);
|
||||
assertEquals(37316.00, DateUtil.getExcelDate(LocalDateTime.of(2002, 3, 1, 0,0), false), 0.00001);
|
||||
assertEquals(37257.00, DateUtil.getExcelDate(LocalDateTime.of(2002, 1, 1, 0,0), false), 0.00001);
|
||||
assertEquals(38074.00, DateUtil.getExcelDate(LocalDateTime.of(2004, 3, 28, 0,0), false), 0.00001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dateBug_2Java() {
|
||||
assertEquals(createDate(1900, FEBRUARY, 28), DateUtil.getJavaDate(59.0, false));
|
||||
assertEquals(createDate(1900, MARCH, 1), DateUtil.getJavaDate(61.0, false));
|
||||
|
||||
assertEquals(createDate(2002, FEBRUARY, 28), DateUtil.getJavaDate(37315.00, false));
|
||||
assertEquals(createDate(2002, MARCH, 1), DateUtil.getJavaDate(37316.00, false));
|
||||
assertEquals(createDate(2002, JANUARY, 1), DateUtil.getJavaDate(37257.00, false));
|
||||
assertEquals(createDate(2004, MARCH, 28), DateUtil.getJavaDate(38074.00, false));
|
||||
|
||||
// perform the same checks using LocalDateTime
|
||||
assertEquals(LocalDateTime.of(1900, 2, 28, 0, 0), DateUtil.getLocalDateTime(59.0, false));
|
||||
assertEquals(LocalDateTime.of(1900, 3, 1, 0, 0), DateUtil.getLocalDateTime(61.0, false));
|
||||
|
||||
assertEquals(LocalDateTime.of(2002, 2, 28, 0, 0), DateUtil.getLocalDateTime(37315.00, false));
|
||||
assertEquals(LocalDateTime.of(2002, 3, 1, 0, 0), DateUtil.getLocalDateTime(37316.00, false));
|
||||
assertEquals(LocalDateTime.of(2002, 1, 1, 0, 0), DateUtil.getLocalDateTime(37257.00, false));
|
||||
assertEquals(LocalDateTime.of(2004, 3, 28, 0, 0), DateUtil.getLocalDateTime(38074.00, false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void date1904() {
|
||||
assertEquals(createDate(1904, JANUARY, 2), DateUtil.getJavaDate(1.0, true));
|
||||
assertEquals(createDate(1904, JANUARY, 1), DateUtil.getJavaDate(0.0, true));
|
||||
assertEquals(0.0, DateUtil.getExcelDate(createDate(1904, JANUARY, 1), true), 0.00001);
|
||||
assertEquals(1.0, DateUtil.getExcelDate(createDate(1904, JANUARY, 2), true), 0.00001);
|
||||
|
||||
assertEquals(createDate(1998, JULY, 5), DateUtil.getJavaDate(35981, false));
|
||||
assertEquals(createDate(1998, JULY, 5), DateUtil.getJavaDate(34519, true));
|
||||
|
||||
assertEquals(35981.0, DateUtil.getExcelDate(createDate(1998, JULY, 5), false), 0.00001);
|
||||
assertEquals(34519.0, DateUtil.getExcelDate(createDate(1998, JULY, 5), true), 0.00001);
|
||||
|
||||
// perform the same checks using LocalDateTime
|
||||
assertEquals(LocalDateTime.of(1904, 1, 2, 0, 0), DateUtil.getLocalDateTime(1.0, true));
|
||||
assertEquals(LocalDateTime.of(1904, 1, 1, 0, 0), DateUtil.getLocalDateTime(0.0, true));
|
||||
assertEquals(0.0, DateUtil.getExcelDate(LocalDateTime.of(1904, 1, 1, 0, 0), true), 0.00001);
|
||||
assertEquals(1.0, DateUtil.getExcelDate(LocalDateTime.of(1904, 1, 2, 0, 0), true), 0.00001);
|
||||
|
||||
assertEquals(LocalDateTime.of(1998, 7, 5, 0, 0), DateUtil.getLocalDateTime(35981, false));
|
||||
assertEquals(LocalDateTime.of(1998, 7, 5, 0, 0), DateUtil.getLocalDateTime(34519, true));
|
||||
|
||||
assertEquals(35981.0, DateUtil.getExcelDate(LocalDateTime.of(1998, 7, 5, 0, 0), false), 0.00001);
|
||||
assertEquals(34519.0, DateUtil.getExcelDate(LocalDateTime.of(1998, 7, 5, 0, 0), true), 0.00001);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param month zero based
|
||||
* @param day one based
|
||||
*/
|
||||
private static Date createDate(int year, int month, int day) {
|
||||
return createDate(year, month, day, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param month zero based
|
||||
* @param day one based
|
||||
*/
|
||||
private static Date createDate(int year, int month, int day, int hour, int minute, int second) {
|
||||
Calendar c = LocaleUtil.getLocaleCalendar(year, month, day, hour, minute, second);
|
||||
return c.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if DateUtil.getAbsoluteDay works as advertised.
|
||||
*/
|
||||
@Test
|
||||
public void absoluteDay() {
|
||||
// 1 Jan 1900 is 1 day after 31 Dec 1899
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(1900,JANUARY,1,0,0,0);
|
||||
assertEquals("Checking absolute day (1 Jan 1900)", 1, DateUtil.absoluteDay(cal, false));
|
||||
LocalDateTime ldt = LocalDateTime.of(1900,1,1,0,0,0);
|
||||
assertEquals("Checking absolute day (1 Jan 1900) (LocalDateTime)", 1, DateUtil.absoluteDay(ldt, false));
|
||||
// 1 Jan 1901 is 366 days after 31 Dec 1899
|
||||
ldt = LocalDateTime.of(1901,1,1,0,0,0);
|
||||
cal.set(1901,JANUARY,1,0,0,0);
|
||||
assertEquals("Checking absolute day (1 Jan 1901) (LocalDateTime)", 366, DateUtil.absoluteDay(ldt, false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void absoluteDayYearTooLow() {
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(1899,JANUARY,1,0,0,0);
|
||||
try {
|
||||
DateUtil.absoluteDay(cal, false);
|
||||
fail("Should fail here");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected here
|
||||
}
|
||||
|
||||
try {
|
||||
cal.set(1903,JANUARY,1,0,0,0);
|
||||
DateUtil.absoluteDay(cal, true);
|
||||
fail("Should fail here");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected here
|
||||
}
|
||||
|
||||
// same for LocalDateTime
|
||||
try {
|
||||
DateUtil.absoluteDay(LocalDateTime.of(1899,1,1,0,0,0), false);
|
||||
fail("Should fail here");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected here
|
||||
}
|
||||
|
||||
try {
|
||||
DateUtil.absoluteDay(LocalDateTime.of(1903,1,1,0,0,0), true);
|
||||
fail("Should fail here");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected here
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertTime() {
|
||||
|
||||
final double delta = 1E-7; // a couple of digits more accuracy than strictly required
|
||||
assertEquals(0.5, DateUtil.convertTime("12:00"), delta);
|
||||
assertEquals(2.0/3, DateUtil.convertTime("16:00"), delta);
|
||||
assertEquals(0.0000116, DateUtil.convertTime("0:00:01"), delta);
|
||||
assertEquals(0.7330440, DateUtil.convertTime("17:35:35"), delta);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseDate() {
|
||||
assertEquals(createDate(2008, AUGUST, 3), DateUtil.parseYYYYMMDDDate("2008/08/03"));
|
||||
assertEquals(createDate(1994, MAY, 1), DateUtil.parseYYYYMMDDDate("1994/05/01"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that date values *with* a fractional portion get the right time of day
|
||||
*/
|
||||
@Test
|
||||
public void convertDateTime() {
|
||||
// Excel day 30000 is date 18-Feb-1982
|
||||
// 0.7 corresponds to time 16:48:00
|
||||
Date actual = DateUtil.getJavaDate(30000.7);
|
||||
Date expected = createDate(1982, 1, 18, 16, 48, 0);
|
||||
assertEquals(expected, actual);
|
||||
|
||||
// note that months in Calendar are zero-based, in LocalDateTime one-based
|
||||
LocalDateTime actualLocalDate = DateUtil.getLocalDateTime(30000.7);
|
||||
LocalDateTime expectedLocalDate = LocalDateTime.of(1982, 2, 18, 16, 48, 0);
|
||||
assertEquals(expectedLocalDate, actualLocalDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* User reported a datetime issue in POI-2.5:
|
||||
* Setting Cell's value to Jan 1, 1900 without a time doesn't return the same value set to
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void bug19172() throws IOException
|
||||
{
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||
HSSFSheet sheet = workbook.createSheet();
|
||||
HSSFCell cell = sheet.createRow(0).createCell(0);
|
||||
|
||||
// A pseudo special Excel dates
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(1900, JANUARY, 1);
|
||||
|
||||
Date valueToTest = cal.getTime();
|
||||
|
||||
cell.setCellValue(valueToTest);
|
||||
|
||||
Date returnedValue = cell.getDateCellValue();
|
||||
|
||||
assertEquals(valueToTest.getTime(), returnedValue.getTime());
|
||||
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* DateUtil.isCellFormatted(Cell) should not true for a numeric cell
|
||||
* that's formatted as ".0000"
|
||||
*/
|
||||
@Test
|
||||
public void bug54557() throws Exception {
|
||||
final String format = ".0000";
|
||||
boolean isDateFormat = DateUtil.isADateFormat(165, format);
|
||||
|
||||
assertEquals(false, isDateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bug56269() throws Exception {
|
||||
double excelFraction = 41642.45833321759d;
|
||||
Calendar calNoRound = DateUtil.getJavaCalendar(excelFraction, false);
|
||||
assertEquals(10, calNoRound.get(Calendar.HOUR));
|
||||
assertEquals(59, calNoRound.get(Calendar.MINUTE));
|
||||
assertEquals(59, calNoRound.get(Calendar.SECOND));
|
||||
Calendar calRound = DateUtil.getJavaCalendar(excelFraction, false, null, true);
|
||||
assertEquals(11, calRound.get(Calendar.HOUR));
|
||||
assertEquals(0, calRound.get(Calendar.MINUTE));
|
||||
assertEquals(0, calRound.get(Calendar.SECOND));
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user