/*
* ObjectLab, http://www.objectlab.co.uk/open is sponsoring the ObjectLab Kit.
*
* Based in London, we are world leaders in the design and development
* of bespoke applications for the securities financing markets.
*
* <a href="http://www.objectlab.co.uk/open">Click here to learn more</a>
* ___ _ _ _ _ _
* / _ \| |__ (_) ___ ___| |_| | __ _| |__
* | | | | '_ \| |/ _ \/ __| __| | / _` | '_ \
* | |_| | |_) | | __/ (__| |_| |__| (_| | |_) |
* \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
* |__/
*
* www.ObjectLab.co.uk
*
* $Id$
*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package net.objectlab.kit.datecalc.common;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
/**
* Convert Excel Date to Jdk <code>Date</code> or <code>Calendar</code>.
*
* @author Benoit Xhenseval
*
*/
public final class ExcelDateUtil {
private static final double HALF_MILLISEC = 0.5;
private static final int EXCEL_FUDGE_19000229 = 61;
private static final int EXCEL_WINDOWING_1904 = 1904;
private static final int EXCEL_BASE_YEAR = 1900;
private static final long DAY_MILLISECONDS = 24 * 60 * 60 * 1000;
private ExcelDateUtil() {
}
/**
* Given an Excel date with either 1900 or 1904 date windowing, converts it
* to a java.util.Date.
*
* @param excelDate
* The Excel date.
* @param use1904windowing
* true if date uses 1904 windowing, or false if using 1900 date
* windowing.
* @return Java representation of the date without any time.
*
* @see java.util.TimeZone
*/
public static Calendar getJavaCalendar(final double excelDate, final boolean use1904windowing) {
if (isValidExcelDate(excelDate)) {
int startYear = EXCEL_BASE_YEAR;
int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which
// it isn't
final int wholeDays = (int) Math.floor(excelDate);
if (use1904windowing) {
startYear = EXCEL_WINDOWING_1904;
dayAdjust = 1; // 1904 date windowing uses 1/2/1904 as the
// first day
} else if (wholeDays < EXCEL_FUDGE_19000229) {
// 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;
}
final GregorianCalendar calendar = new GregorianCalendar(startYear, 0, wholeDays + dayAdjust);
final int millisecondsInDay = (int) ((excelDate - Math.floor(excelDate)) * DAY_MILLISECONDS + HALF_MILLISEC);
calendar.set(Calendar.MILLISECOND, millisecondsInDay);
return calendar;
} else {
return null;
}
}
// -----------------------------------------------------------------------
//
// ObjectLab, world leaders in the design and development of bespoke
// applications for the securities financing markets.
// www.ObjectLab.co.uk
//
// -----------------------------------------------------------------------
/**
* Given an Excel date with either 1900 or 1904 date windowing, converts it
* to a java.util.Date.
*
* @param excelDate
* The Excel date.
* @param use1904windowing
* true if date uses 1904 windowing, or false if using 1900 date
* windowing.
* @return Java representation of the date without any time.
*
* @see java.util.TimeZone
*/
public static Date getJavaDateOnly(final double excelDate, final boolean use1904windowing) {
final Calendar javaCalendar = getJavaCalendar(excelDate, use1904windowing);
if (javaCalendar == null) {
return null;
}
return Utils.blastTime(javaCalendar).getTime();
}
/**
* Given an Excel date with either 1900 or 1904 date windowing, 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 excelDate
* 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
* @see java.util.TimeZone
*/
public static Date getJavaDate(final double excelDate, final boolean use1904windowing) {
final Calendar cal = getJavaCalendar(excelDate, use1904windowing);
return cal == null ? null : cal.getTime();
}
/**
* Given a double, checks if it is a valid Excel date.
*
* @return true if valid
* @param excelDate
* the double value
*/
public static boolean isValidExcelDate(final double excelDate) {
return excelDate > -Double.MIN_VALUE;
}
}
/*
* ObjectLab, http://www.objectlab.co.uk/open is sponsoring the ObjectLab Kit.
*
* Based in London, we are world leaders in the design and development
* of bespoke applications for the securities financing markets.
*
* <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a>
* ___ _ _ _ _ _
* / _ \| |__ (_) ___ ___| |_| | __ _| |__
* | | | | '_ \| |/ _ \/ __| __| | / _` | '_ \
* | |_| | |_) | | __/ (__| |_| |__| (_| | |_) |
* \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
* |__/
*
* www.ObjectLab.co.uk
*/