Given a Date, converts it into a double representing its internal Excel representation, which is the number of days since 1/1/1900. - Java java.util

Java examples for java.util:Date Format

Description

Given a Date, converts it into a double representing its internal Excel representation, which is the number of days since 1/1/1900.

Demo Code


//package com.java2s;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class Main {
    private static final int BAD_DATE = -1;
    private static final long DAY_MILLISECONDS = 24 * 60 * 60 * 1000;
    private static final double CAL_1900_ABSOLUTE = (double) absoluteDay(new GregorianCalendar(
            1900, Calendar.JANUARY, 1)) - 2.0;

    /**/*  w  ww  . j a  va2s.  c o  m*/
     * 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.
     *
     * @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(Date date) {
        Calendar calStart = new GregorianCalendar();

        calStart.setTime(date); // If date includes hours, minutes, and seconds, set them to 0
        if (calStart.get(Calendar.YEAR) < 1900) {
            return BAD_DATE;
        } 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);

            //TODO for dates below 1900-03-01(61), it will return value with +1 and for 1899-12-31(0) it will return -1.0
            return fraction + (double) absoluteDay(calStart)
                    - CAL_1900_ABSOLUTE;
        }
    }

    private static Calendar dayStart(final Calendar cal) {
        cal.get(Calendar.HOUR_OF_DAY); // force recalculation of internal fields
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        cal.get(Calendar.HOUR_OF_DAY); // force recalculation of internal fields
        return cal;
    }

    /**
     * Given a Calendar, return the number of days since 1600/12/31.
     *
     * @return days number of days since 1600/12/31
     * @param  cal the Calendar
     * @exception IllegalArgumentException if date is invalid
     */
    private static int absoluteDay(Calendar cal) {
        return cal.get(Calendar.DAY_OF_YEAR)
                + daysInPriorYears(cal.get(Calendar.YEAR));
    }

    /**
     * Return the number of days in prior years since 1601
     *
     * @return    days  number of days in years prior to yr.
     * @param     yr    a year (1600 < yr < 4000)
     * @exception IllegalArgumentException if year is outside of range.
     */
    private static int daysInPriorYears(int yr) {
        if (yr < 1601) {
            throw new IllegalArgumentException(
                    "'year' must be 1601 or greater");
        }
        int y = yr - 1601;
        int days = 365 * y // days in prior years
                + y / 4 // plus julian leap days in prior years
                - y / 100 // minus prior century years
                + y / 400; // plus years divisible by 400

        return days;
    }
}

Related Tutorials