diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index d96617f5c..bd5e74d84 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 53092 - allow specifying of a TimeZone to DateUtil.getJavaDate(), for when it is known that a file comes from a different (known) timezone to the current machine 53043 - don't duplicate hyperlink relationships when saving XSSF file 53101 - fixed evaluation of SUM over cell range > 255 49529 - avoid exception when cloning sheets with no drawing records and initialized drawing patriarch diff --git a/src/java/org/apache/poi/ss/usermodel/DateUtil.java b/src/java/org/apache/poi/ss/usermodel/DateUtil.java index cf445f9fa..9d1af834d 100644 --- a/src/java/org/apache/poi/ss/usermodel/DateUtil.java +++ b/src/java/org/apache/poi/ss/usermodel/DateUtil.java @@ -21,6 +21,7 @@ package org.apache.poi.ss.usermodel; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; +import java.util.TimeZone; import java.util.regex.Pattern; /** @@ -124,6 +125,22 @@ public class DateUtil { return value; } + /** + * Given an Excel date with using 1900 date windowing, and + * converts it to a java.util.Date. + * + * 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 tz The TimeZone to evaluate the date in + * @return Java representation of the date, or null if date is not a valid Excel date + */ + public static Date getJavaDate(double date, TimeZone tz) { + return getJavaDate(date, false, tz); + } /** * Given an Excel date with using 1900 date windowing, and * converts it to a java.util.Date. @@ -142,7 +159,38 @@ public class DateUtil { * @see java.util.TimeZone */ public static Date getJavaDate(double date) { - return getJavaDate(date, false); + return getJavaDate(date, (TimeZone)null); + } + + /** + * Given an Excel date with either 1900 or 1904 date windowing, + * converts it to a java.util.Date. + * + * 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 tz The TimeZone to evaluate the date in + * @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 Date getJavaDate(double date, boolean use1904windowing, TimeZone tz) { + if (!isValidExcelDate(date)) { + return null; + } + Calendar calendar; + if (tz != null) + calendar = new GregorianCalendar(tz); + else + calendar = new GregorianCalendar(); // using default time-zone + + int wholeDays = (int)Math.floor(date); + int millisecondsInDay = (int)((date - wholeDays) * DAY_MILLISECONDS + 0.5); + setCalendar(calendar, wholeDays, millisecondsInDay, use1904windowing); + return calendar.getTime(); } /** * Given an Excel date with either 1900 or 1904 date windowing, @@ -164,14 +212,7 @@ public class DateUtil { * @see java.util.TimeZone */ public static Date getJavaDate(double date, boolean use1904windowing) { - if (!isValidExcelDate(date)) { - return null; - } - int wholeDays = (int)Math.floor(date); - int millisecondsInDay = (int)((date - wholeDays) * DAY_MILLISECONDS + 0.5); - Calendar calendar = new GregorianCalendar(); // using default time-zone - setCalendar(calendar, wholeDays, millisecondsInDay, use1904windowing); - return calendar.getTime(); + return getJavaDate(date, use1904windowing, (TimeZone)null); } public static void setCalendar(Calendar calendar, int wholeDays, int millisecondsInDay, boolean use1904windowing) { diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java index bc87fe76a..32f3fe65f 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java @@ -202,6 +202,25 @@ public final class TestHSSFDateUtil extends TestCase { // 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"); + TimeZone.setDefault(cet); + + // 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); } /**