]> source.dussan.org Git - poi.git/commitdiff
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=14375
authorAndrew C. Oliver <acoliver@apache.org>
Thu, 28 Nov 2002 19:32:52 +0000 (19:32 +0000)
committerAndrew C. Oliver <acoliver@apache.org>
Thu, 28 Nov 2002 19:32:52 +0000 (19:32 +0000)
PR:
Obtained from:
Submitted by:
Reviewed by:

git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@352931 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hssf/model/Workbook.java
src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java

index a07862b5b355651f36a0451fbd0f00f9d4c27aab..d7f30596876e3b005025481dc897db7394099c40 100644 (file)
@@ -89,6 +89,7 @@ import org.apache.poi.hssf.util.HSSFColor;
  * @author  Glen Stampoultzis (glens at apache.org)
  * @author  Sergei Kozello (sergeikozello at mail.ru)
  * @author  Luc Girardin (luc dot girardin at macrofocus dot com)
+ * @author  Dan Sherman (dsherman at isisph.com)
  * @see org.apache.poi.hssf.usermodel.HSSFWorkbook
  * @version 1.0-pre
  */
@@ -156,6 +157,8 @@ public class Workbook implements Model {
     0;   // holds the position of sup book
     private short              maxformatid  =
     -1;  // holds the max format id
+    private boolean            uses1904datewindowing  =
+    false;  // whether 1904 date windowing is being used
 
     private static POILogger   log         =
     POILogFactory.getLogger(Workbook.class);
@@ -249,6 +252,10 @@ public class Workbook implements Model {
                    retval.formats.add(rec);
                    retval.maxformatid = retval.maxformatid >= ((FormatRecord)rec).getIndexCode() ? retval.maxformatid : ((FormatRecord)rec).getIndexCode();
                    break;
+                case DateWindow1904Record.sid :
+                    log.log(DEBUG, "found datewindow1904 record at " + k);
+                    retval.uses1904datewindowing = ((DateWindow1904Record)rec).getWindowing() == 1;
+                    break;
 
                 default :
             }
@@ -1912,4 +1919,14 @@ public class Workbook implements Model {
     {
         return records;
     }
+
+    /**
+    * Whether date windowing is based on 1/2/1904 or 1/1/1900.
+    * Some versions of Excel (Mac) can save workbooks using 1904 date windowing.
+    *
+    * @return true if using 1904 date windowing
+    */
+    public boolean isUsing1904DateWindowing() {
+        return uses1904datewindowing;
+    }
 }
index b3aaf2dbbdce6c8832dc6b092d11ce682e88d5b5..2a38d6aa8edfcdd31281b541c58c2839d001d9fb 100644 (file)
@@ -94,6 +94,7 @@ import java.util.Calendar;
  * NOTE: the alpha won't be implementing formulas
  *
  * @author  Andrew C. Oliver (acoliver at apache dot org)
+ * @author  Dan Sherman (dsherman at isisph.com)
  * @version 1.0-pre
  */
 
@@ -783,7 +784,12 @@ public class HSSFCell
             throw new NumberFormatException(
                 "You cannot get a date value from an error cell");
         }
-        return HSSFDateUtil.getJavaDate(cellValue);
+        if (book.isUsing1904DateWindowing()) {
+            return HSSFDateUtil.getJavaDate(cellValue,true);
+        }
+        else {
+            return HSSFDateUtil.getJavaDate(cellValue,false);
+        }
     }
 
     /**
index fb26a7d972b0d2a2077bae704b609a2601aec5ec..9024e246f8bb298d264fdd514add74d0c406c1bc 100644 (file)
@@ -69,6 +69,7 @@ import java.util.GregorianCalendar;
  *
  * @author  Michael Harhen
  * @author  Glen Stampoultzis (glens at apache.org)
+ * @author  Dan Sherman (dsherman at isisph.com)
  */
 
 public class HSSFDateUtil
@@ -115,33 +116,54 @@ public class HSSFDateUtil
 
     /**
      * Given a excel date, converts it into a Date.
+     * Assumes 1900 date windowing.
      *
      * @param  date the Excel Date
      *
      * @return Java representation of a date (null if error)
+     * @see #getJavaDate(double,boolean)
      */
 
     public static Date getJavaDate(double date)
     {
-        if (isValidExcelDate(date))
-        {
-            int               wholeDaysSince1900 = ( int ) Math.floor(date);
-            GregorianCalendar calendar           = new GregorianCalendar(1900,
-                                                       0, wholeDaysSince1900
-                                                       - 1);
-            int               millisecondsInDay  =
-                ( int ) ((date - Math.floor(date))
-                         * ( double ) DAY_MILLISECONDS + 0.5);
-
+        return getJavaDate(date,false);
+    }
+    
+    /**
+     *  Given an Excel date with either 1900 or 1904 date windowing,
+     *  converts it to a java.util.Date.
+     *
+     *  @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 Date getJavaDate(double date, boolean use1904windowing) {
+        if (isValidExcelDate(date)) {
+            int startYear = 1900;
+            int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which it isn't
+            int wholeDays = (int)Math.floor(date);
+            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;
+            }
+            GregorianCalendar calendar = new GregorianCalendar(startYear,0,
+                                                     wholeDays + dayAdjust);
+            int millisecondsInDay = (int)((date - Math.floor(date)) * 
+                                          (double) DAY_MILLISECONDS + 0.5);
             calendar.set(GregorianCalendar.MILLISECOND, millisecondsInDay);
             return calendar.getTime();
         }
-        else
-        {
+        else {
             return null;
         }
     }
-    
+
     /**
      * given a format ID this will check whether the format represents
      * an internal date format or not. 
@@ -164,6 +186,18 @@ public class HSSFDateUtil
                 case 0x2d:
                 case 0x2e:
                 case 0x2f:
+                // Additional internal date formats found by inspection
+                // Using Excel v.X 10.1.0 (Mac)
+                case 0xa4:
+                case 0xa5:
+                case 0xa6:
+                case 0xa7:
+                case 0xa8:
+                case 0xa9:
+                case 0xaa:
+                case 0xab:
+                case 0xac:
+                case 0xad:
                     retval = true;
                     break;