Applied patch 27574
When setting a cell's value to the date 2004-03-28 08:00 it is presented as 07:00 in Excel. This only happens on the days when DST starts or ends. git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/branches/REL_2_BRANCH@353576 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
2943c5a8e5
commit
95f5211037
@ -33,6 +33,7 @@ import java.util.GregorianCalendar;
|
|||||||
* @author Michael Harhen
|
* @author Michael Harhen
|
||||||
* @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)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class HSSFDateUtil
|
public class HSSFDateUtil
|
||||||
@ -68,9 +69,19 @@ public class HSSFDateUtil
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Because of daylight time saving we cannot use
|
||||||
|
// date.getTime() - calStart.getTimeInMillis()
|
||||||
|
// as the difference in milliseconds between 00:00 and 04:00
|
||||||
|
// can be 3, 4 or 5 hours but Excel expects it to always
|
||||||
|
// 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 = (((calStart.get(Calendar.HOUR_OF_DAY) * 60
|
||||||
|
+ calStart.get(Calendar.MINUTE)
|
||||||
|
) * 60 + calStart.get(Calendar.SECOND)
|
||||||
|
) * 1000 + calStart.get(Calendar.MILLISECOND)
|
||||||
|
) / ( double ) DAY_MILLISECONDS;
|
||||||
calStart = dayStart(calStart);
|
calStart = dayStart(calStart);
|
||||||
double fraction = (date.getTime() - calStart.getTime().getTime())
|
|
||||||
/ ( double ) DAY_MILLISECONDS;
|
|
||||||
|
|
||||||
return fraction + ( double ) absoluteDay(calStart)
|
return fraction + ( double ) absoluteDay(calStart)
|
||||||
- CAL_1900_ABSOLUTE;
|
- CAL_1900_ABSOLUTE;
|
||||||
@ -96,10 +107,20 @@ public class HSSFDateUtil
|
|||||||
* 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.
|
||||||
*
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
* @param date The Excel date.
|
* @param date The Excel date.
|
||||||
* @param use1904windowing true if date uses 1904 windowing,
|
* @param use1904windowing true if date uses 1904 windowing,
|
||||||
* or false if using 1900 date windowing.
|
* or false if using 1900 date windowing.
|
||||||
* @return Java representation of the date, or null if date is not a valid Excel date
|
* @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, boolean use1904windowing) {
|
public static Date getJavaDate(double date, boolean use1904windowing) {
|
||||||
if (isValidExcelDate(date)) {
|
if (isValidExcelDate(date)) {
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
|
|
||||||
/* ====================================================================
|
/* ====================================================================
|
||||||
Copyright 2002-2004 Apache Software Foundation
|
Copyright 2002-2004 Apache Software Foundation
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
==================================================================== */
|
==================================================================== */
|
||||||
|
|
||||||
|
|
||||||
@ -21,7 +21,9 @@ package org.apache.poi.hssf.usermodel;
|
|||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class TestHSSFDateUtil
|
* Class TestHSSFDateUtil
|
||||||
@ -29,6 +31,7 @@ import java.util.GregorianCalendar;
|
|||||||
*
|
*
|
||||||
* @author
|
* @author
|
||||||
* @author Dan Sherman (dsherman at isisph.com)
|
* @author Dan Sherman (dsherman at isisph.com)
|
||||||
|
* @author Hack Kampbjorn (hak at 2mba.dk)
|
||||||
* @version %I%, %G%
|
* @version %I%, %G%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -78,4 +81,111 @@ public class TestHSSFDateUtil
|
|||||||
dateIf1904.getTime(),
|
dateIf1904.getTime(),
|
||||||
HSSFDateUtil.getJavaDate(excelDate,true).getTime());
|
HSSFDateUtil.getJavaDate(excelDate,true).getTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the conversion of a java.util.date to Excel on a day when
|
||||||
|
* Daylight Saving Time starts.
|
||||||
|
*/
|
||||||
|
public void testExcelConversionOnDSTStart() {
|
||||||
|
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
|
||||||
|
TimeZone.setDefault(cet);
|
||||||
|
Calendar cal = new GregorianCalendar(2004, Calendar.MARCH, 28);
|
||||||
|
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);
|
||||||
|
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).getTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the conversion of an Excel date to a java.util.date on a day when
|
||||||
|
* Daylight Saving Time starts.
|
||||||
|
*/
|
||||||
|
public void testJavaConversionOnDSTStart() {
|
||||||
|
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
|
||||||
|
TimeZone.setDefault(cet);
|
||||||
|
Calendar cal = new GregorianCalendar(2004, Calendar.MARCH, 28);
|
||||||
|
double excelDate = HSSFDateUtil.getExcelDate(cal.getTime());
|
||||||
|
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);
|
||||||
|
assertEquals("Checking " + hour + " hours on Daylight Saving Time start date",
|
||||||
|
excelDate,
|
||||||
|
HSSFDateUtil.getExcelDate(javaDate), oneMinute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the conversion of a java.util.Date to Excel on a day when
|
||||||
|
* Daylight Saving Time ends.
|
||||||
|
*/
|
||||||
|
public void testExcelConversionOnDSTEnd() {
|
||||||
|
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
|
||||||
|
TimeZone.setDefault(cet);
|
||||||
|
Calendar cal = new GregorianCalendar(2004, Calendar.OCTOBER, 31);
|
||||||
|
for (int hour = 0; hour < 24; hour++) {
|
||||||
|
cal.set(Calendar.HOUR_OF_DAY, hour);
|
||||||
|
Date javaDate = cal.getTime();
|
||||||
|
double excelDate = HSSFDateUtil.getExcelDate(javaDate);
|
||||||
|
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).getTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the conversion of an Excel date to java.util.Date on a day when
|
||||||
|
* Daylight Saving Time ends.
|
||||||
|
*/
|
||||||
|
public void testJavaConversionOnDSTEnd() {
|
||||||
|
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
|
||||||
|
TimeZone.setDefault(cet);
|
||||||
|
Calendar cal = new GregorianCalendar(2004, Calendar.OCTOBER, 31);
|
||||||
|
double excelDate = HSSFDateUtil.getExcelDate(cal.getTime());
|
||||||
|
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);
|
||||||
|
assertEquals("Checking " + hour + " hours on Daylight Saving Time start date",
|
||||||
|
excelDate,
|
||||||
|
HSSFDateUtil.getExcelDate(javaDate), oneMinute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String [] args) {
|
||||||
|
System.out
|
||||||
|
.println("Testing org.apache.poi.hssf.usermodel.TestHSSFDateUtil");
|
||||||
|
junit.textui.TestRunner.run(TestHSSFDateUtil.class);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user