Java Convert 'Excel Date Serial Number' to 'DateTime' [duplicate]

爱⌒轻易说出口 提交于 2021-02-07 09:26:28

问题


How convert 'excel date serial number'(i.e. 33257.415972222225) to DateTime(i.e. 19/01/1991 09:59:00) using Java?


回答1:


You can also have a look at the Source code of Apache POI, method DateUtils#getLocalDateTime(double date, boolean use1904windowing, boolean roundSeconds). This utility class offers more handy methods for working with Excel dates.




回答2:


Excel stores dates and times as a number representing the number of days since January 0, 1900, plus a fractional portion of a 24 hour day: ddddd.tttttt.
This is called serial date or serial date-time.

The linked documentation from Microsoft seems to be quite clear.

MS DATEVALUE function states:

Excel stores dates as sequential serial numbers so that they can be used in calculations. By default, January 1, 1900 is serial number 1, and January 1, 2008 is serial number 39448 because it is 39,447 days after January 1, 1900

Well, I'm going to check this statement:

LocalDate testDate = LocalDate.of(1900, Month.JANUARY, 1).plusDays(39447);
System.out.println(testDate);// prints 2008-01-02

39,447 days after January 1, 1900 it's indeed... January 2, 2008!

Why is that?

The fact that dates in Excel are represented by the number of days starting from an epoch (December 30, 1899 or January 1, 1900 or 1904...) is only a part of the story.

I found an ultimate answer here: Dates And Times In Excel (some god or Whoever may bless these guys).

The developers who implemented the date routines in Excel introduced deliberately a bug for compatibility with the same known issue from Lotus 1-2-3.

They treated the year 1900 as a leap year but it's not, so any date exceeding January 28, 1900 it's a day more than the actual date.

That's why Excel thinks that January 1, 2008 is represented by the number 39448: because it is 39,448 units after January 0, 1900 (yes, Excel thinks zero) - ie 39,447 days plus January 29, 1900.

Excel can also treat the date portion of a serial date as the number of days since January 0, 1904; this mode is called 1904-mode or 1904-system and it's used for compatibility with the Macintosh systems.

Since Excel dates don't carry any time-zone information - it's only a number - it's better to use Java classes like LocalDate/LocalDateTime to represent such values without a time-zone information.

Well, in pratice - for nowadays dates - one may figure Excel epoch starting from December 30, 1900 but it's not.


Excel demo - date format is dd/mm/yyyy hh:MM:ss

7
Dates are inserted as the number on the left


A class suitable for the required conversion:

public class SerialDate {

    //days from 1899-12-31 to Instant.EPOCH (1970-01-01T00:00:00Z)
    public static final long EPOCH = -25568L;
    
    private long serialDays;
    private double serialTime;
    private long epochDays;
    private long daySeconds;
    
    /**
     * @param date number of Excel-days since <i>January 0, 1899</i>
     */
    public SerialDate(long date) {
        serialDays = date;
        if (date > 59)//Lotus123 bug
            --date;
        epochDays = EPOCH + date;
    }
    
    /**
     * @param date number of days since <i>January 0, 1899</i> with a time fraction
     */
    public SerialDate(double date) {
        this((long)date);
        serialTime = date - serialDays;
        daySeconds = Math.round(serialTime * 24 * 60 * 60);
    }
    
    /**
     * @return days since 1970-01-01
     */
    public long toEpochDays() {
        return epochDays;
    }
    
    /**
     * @return seconds of the day for this SerialDate
     */
    public long toDaySeconds() {
        return daySeconds;
    }
    
    /**
     * @return a value suitable for an Excel date
     */
    public double getSerialDate() {
        return serialTime + serialDays;
    }
}

Usage example:

SerialDate sd = new SerialDate(33257.415972222225);
LocalDateTime dt = LocalDateTime.of(
        LocalDate.ofEpochDay(sd.toEpochDays()),
        LocalTime.ofSecondOfDay(sd.toDaySeconds()));
System.out.println(dt);//prints 1991-01-19T09:59


来源:https://stackoverflow.com/questions/53013156/java-convert-excel-date-serial-number-to-datetime

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!