001/* 002 * ObjectLab, http://www.objectlab.co.uk/open is sponsoring the ObjectLab Kit. 003 * 004 * Based in London, we are world leaders in the design and development 005 * of bespoke applications for the securities financing markets. 006 * 007 * <a href="http://www.objectlab.co.uk/open">Click here to learn more</a> 008 * ___ _ _ _ _ _ 009 * / _ \| |__ (_) ___ ___| |_| | __ _| |__ 010 * | | | | '_ \| |/ _ \/ __| __| | / _` | '_ \ 011 * | |_| | |_) | | __/ (__| |_| |__| (_| | |_) | 012 * \___/|_.__// |\___|\___|\__|_____\__,_|_.__/ 013 * |__/ 014 * 015 * www.ObjectLab.co.uk 016 * 017 * $Id$ 018 * 019 * Copyright 2006 the original author or authors. 020 * 021 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 022 * use this file except in compliance with the License. You may obtain a copy of 023 * the License at 024 * 025 * http://www.apache.org/licenses/LICENSE-2.0 026 * 027 * Unless required by applicable law or agreed to in writing, software 028 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 029 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 030 * License for the specific language governing permissions and limitations under 031 * the License. 032 */ 033package net.objectlab.kit.datecalc.common; 034 035import java.util.Calendar; 036import java.util.Date; 037import java.util.GregorianCalendar; 038 039/** 040 * Convert Excel Date to Jdk <code>Date</code> or <code>Calendar</code>. 041 * 042 * @author Benoit Xhenseval 043 * 044 */ 045public final class ExcelDateUtil { 046 private static final double HALF_MILLISEC = 0.5; 047 048 private static final int EXCEL_FUDGE_19000229 = 61; 049 050 private static final int EXCEL_WINDOWING_1904 = 1904; 051 052 private static final int EXCEL_BASE_YEAR = 1900; 053 054 private static final long DAY_MILLISECONDS = 24 * 60 * 60 * 1000L; 055 056 private ExcelDateUtil() { 057 } 058 059 /** 060 * Given an Excel date with either 1900 or 1904 date windowing, converts it 061 * to a java.util.Date. 062 * 063 * @param excelDate 064 * The Excel date. 065 * @param use1904windowing 066 * true if date uses 1904 windowing, or false if using 1900 date 067 * windowing. 068 * @return Java representation of the date without any time. 069 * 070 * @see java.util.TimeZone 071 */ 072 public static Calendar getJavaCalendar(final double excelDate, final boolean use1904windowing) { 073 if (isValidExcelDate(excelDate)) { 074 int startYear = EXCEL_BASE_YEAR; 075 int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which 076 // it isn't 077 final int wholeDays = (int) Math.floor(excelDate); 078 if (use1904windowing) { 079 startYear = EXCEL_WINDOWING_1904; 080 dayAdjust = 1; // 1904 date windowing uses 1/2/1904 as the 081 // first day 082 } else if (wholeDays < EXCEL_FUDGE_19000229) { 083 // Date is prior to 3/1/1900, so adjust because Excel thinks 084 // 2/29/1900 exists 085 // If Excel date == 2/29/1900, will become 3/1/1900 in Java 086 // representation 087 dayAdjust = 0; 088 } 089 final GregorianCalendar calendar = new GregorianCalendar(startYear, 0, wholeDays + dayAdjust); 090 final int millisecondsInDay = (int) ((excelDate - Math.floor(excelDate)) * DAY_MILLISECONDS + HALF_MILLISEC); 091 calendar.set(Calendar.MILLISECOND, millisecondsInDay); 092 return calendar; 093 } else { 094 return null; 095 } 096 097 } 098 099 // ----------------------------------------------------------------------- 100 // 101 // ObjectLab, world leaders in the design and development of bespoke 102 // applications for the securities financing markets. 103 // www.ObjectLab.co.uk 104 // 105 // ----------------------------------------------------------------------- 106 107 /** 108 * Given an Excel date with either 1900 or 1904 date windowing, converts it 109 * to a java.util.Date. 110 * 111 * @param excelDate 112 * The Excel date. 113 * @param use1904windowing 114 * true if date uses 1904 windowing, or false if using 1900 date 115 * windowing. 116 * @return Java representation of the date without any time. 117 * 118 * @see java.util.TimeZone 119 */ 120 public static Date getJavaDateOnly(final double excelDate, final boolean use1904windowing) { 121 final Calendar javaCalendar = getJavaCalendar(excelDate, use1904windowing); 122 if (javaCalendar == null) { 123 return null; 124 } 125 return Utils.blastTime(javaCalendar).getTime(); 126 } 127 128 /** 129 * Given an Excel date with either 1900 or 1904 date windowing, converts it 130 * to a java.util.Date. 131 * 132 * NOTE: If the default <code>TimeZone</code> in Java uses Daylight Saving 133 * Time then the conversion back to an Excel date may not give the same 134 * value, that is the comparison <CODE>excelDate == 135 * getExcelDate(getJavaDate(excelDate,false))</CODE> is not always true. 136 * For example if default timezone is <code>Europe/Copenhagen</code>, on 137 * 2004-03-28 the minute after 01:59 CET is 03:00 CEST, if the excel date 138 * represents a time between 02:00 and 03:00 then it is converted to past 139 * 03:00 summer time 140 * 141 * @param excelDate 142 * The Excel date. 143 * @param use1904windowing 144 * true if date uses 1904 windowing, or false if using 1900 date 145 * windowing. 146 * @return Java representation of the date, or null if date is not a valid 147 * Excel date 148 * @see java.util.TimeZone 149 */ 150 public static Date getJavaDate(final double excelDate, final boolean use1904windowing) { 151 final Calendar cal = getJavaCalendar(excelDate, use1904windowing); 152 return cal == null ? null : cal.getTime(); 153 } 154 155 /** 156 * Given a double, checks if it is a valid Excel date. 157 * 158 * @return true if valid 159 * @param excelDate 160 * the double value 161 */ 162 public static boolean isValidExcelDate(final double excelDate) { 163 return excelDate > -Double.MIN_VALUE; 164 } 165} 166 167/* 168 * ObjectLab, http://www.objectlab.co.uk/open is sponsoring the ObjectLab Kit. 169 * 170 * Based in London, we are world leaders in the design and development 171 * of bespoke applications for the securities financing markets. 172 * 173 * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a> 174 * ___ _ _ _ _ _ 175 * / _ \| |__ (_) ___ ___| |_| | __ _| |__ 176 * | | | | '_ \| |/ _ \/ __| __| | / _` | '_ \ 177 * | |_| | |_) | | __/ (__| |_| |__| (_| | |_) | 178 * \___/|_.__// |\___|\___|\__|_____\__,_|_.__/ 179 * |__/ 180 * 181 * www.ObjectLab.co.uk 182 */