001    /**
002     * =========================================
003     * LibFormula : a free Java formula library
004     * =========================================
005     *
006     * Project Info:  http://reporting.pentaho.org/libformula/
007     *
008     * (C) Copyright 2006-2007, by Pentaho Corporation and Contributors.
009     *
010     * This library is free software; you can redistribute it and/or modify it under the terms
011     * of the GNU Lesser General Public License as published by the Free Software Foundation;
012     * either version 2.1 of the License, or (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015     * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016     * See the GNU Lesser General Public License for more details.
017     *
018     * You should have received a copy of the GNU Lesser General Public License along with this
019     * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020     * Boston, MA 02111-1307, USA.
021     *
022     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023     * in the United States and other countries.]
024     *
025     *
026     * ------------
027     * $Id: DateUtil.java 4100 2007-11-26 21:04:25Z dkincade $
028     * ------------
029     * (C) Copyright 2006-2007, by Pentaho Corporation.
030     */
031    package org.jfree.formula.util;
032    
033    import java.math.BigDecimal;
034    import java.sql.Time;
035    import java.util.Calendar;
036    import java.util.Date;
037    import java.util.GregorianCalendar;
038    
039    import org.jfree.formula.DefaultLocalizationContext;
040    import org.jfree.formula.LocalizationContext;
041    import org.jfree.formula.typing.Type;
042    import org.jfree.formula.typing.coretypes.DateTimeType;
043    
044    /**
045     * 
046     * @author Cedric Pronzato
047     * 
048     */
049    public class DateUtil
050    {
051      private static final Date ISO8001_TIME = new GregorianCalendar().getTime();
052    
053      private DateUtil()
054      {
055      }
056    
057      /**
058       * Converts a <code>Date</code> value according to the requested
059       * <code>Type</code> to the proper <code>Date</code> subclasses (<code>java.sql.Time</code>,
060       * <code>java.sql.Date</code>) if needed. If the requested type is unknown,
061       * no conversion takes place and the input date is returned.
062       * 
063       * @param fromDate
064       *          The date to convert.
065       * @param toType
066       *          The requested type of date.
067       * @return The converted date.
068       */
069      public static Date normalizeDate(final Date fromDate, final Type toType)
070      {
071        return normalizeDate(fromDate, toType, true);
072      }
073    
074      public static Date normalizeDate(Date fromDate, final Type toType,
075          final boolean convertSerial)
076      {
077        if (fromDate == null || toType == null)
078        {
079          throw new IllegalArgumentException();
080        }
081    
082        if (convertSerial)
083        {
084          Number serial = toSerialDate(fromDate, null);
085          serial = normalizeDate(serial, toType);
086          fromDate = toJavaDate(serial, null);
087        }
088        // final GregorianCalendar gc = new GregorianCalendar();
089        // gc.setTime(fromDate);
090        // gc.set(GregorianCalendar.MILLISECOND, 0);
091        // fromDate = gc.getTime();
092        if (toType.isFlagSet(Type.TIME_TYPE))
093        {
094          return new Time(fromDate.getTime());
095        }
096        else if (toType.isFlagSet(Type.DATE_TYPE))
097        {
098          return new java.sql.Date(fromDate.getTime());
099        }
100        else if (toType.isFlagSet(Type.DATETIME_TYPE))
101        {
102          return new Date(fromDate.getTime());
103        }
104    
105        return fromDate;
106      }
107    
108      public static Number normalizeDate(final Number fromSerialDate, final Type toType)
109      {
110        if (fromSerialDate == null || toType == null)
111        {
112          throw new IllegalArgumentException();
113        }
114    
115        final BigDecimal o = new BigDecimal(fromSerialDate.doubleValue()).setScale(
116            10, BigDecimal.ROUND_UP);
117    
118        if (toType.isFlagSet(Type.TIME_TYPE))
119        {
120          return o.subtract(new BigDecimal(o.intValue()));
121          // only return the decimal part
122          // final Double d = new Double(fromSerialDate.doubleValue()
123          // - fromSerialDate.intValue());
124          // return d;
125        }
126        else if (toType.isFlagSet(Type.DATE_TYPE))
127        {
128          return new Integer(fromSerialDate.intValue());
129        }
130        // datetime (java.util.Date)
131        else
132        {
133          return o;
134        }
135      }
136    
137      public static Date toJavaDate(final Number serialDate, final LocalizationContext context)
138      {
139        final Date javaDate = HSSFDateUtil.getJavaDate(serialDate.doubleValue());
140        // check for null (error)
141        final long l = (javaDate.getTime() / 1000) * 1000;
142        // final GregorianCalendar gc = new GregorianCalendar(context.getTimeZone(),
143        // context.getLocale());
144        // gc.setTimeInMillis(serialDate.longValue() * MILLISECS_PER_DAY);
145        // return gc.getTime();
146        return new Date(l);
147      }
148    
149      public static Number toSerialDate(final Date date, final LocalizationContext context)
150      {
151        // final GregorianCalendar gc = new GregorianCalendar(context.getTimeZone(),
152        // context.getLocale());
153        // gc.setTime(date);
154        // final double fraction = (((gc.get(Calendar.HOUR_OF_DAY) * 60 + gc
155        // .get(Calendar.MINUTE)) * 60 + gc.get(Calendar.SECOND)) * 1000 + gc
156        // .get(Calendar.MILLISECOND))
157        // / (double) MILLISECS_PER_DAY;
158        // final long timeInMillis = date.getTime();
159        // final long days = timeInMillis / MILLISECS_PER_DAY;
160        // return new BigDecimal((double) (days) + fraction);
161        final double serial = HSSFDateUtil.getExcelDate(date);
162        return new Double(serial);
163      }
164    
165      public static Date now(final LocalizationContext context)
166      {
167        final GregorianCalendar gc = new GregorianCalendar(context.getTimeZone(),
168            context.getLocale());
169        gc.set(Calendar.MILLISECOND, 0);
170    
171        return gc.getTime();
172      }
173    
174      public static Date createDateTime(final int year, final int month, final int day, final int hour,
175          final int minute, final int second, final LocalizationContext context)
176      {
177        final GregorianCalendar gc = new GregorianCalendar(context.getTimeZone(),
178            context.getLocale());
179        gc.set(Calendar.DAY_OF_MONTH, day);
180        gc.set(Calendar.MONTH, month);
181        gc.set(Calendar.YEAR, year);
182        gc.set(Calendar.MILLISECOND, 0);
183        gc.set(Calendar.HOUR_OF_DAY, hour);
184        gc.set(Calendar.MINUTE, minute);
185        gc.set(Calendar.SECOND, second);
186        return gc.getTime();
187      }
188    
189      public static Time createTime(final int hour, final int minute, final int second,
190          final LocalizationContext context)
191      {
192        final GregorianCalendar gc = new GregorianCalendar(context.getTimeZone(),
193            context.getLocale());
194        gc.setTime(ISO8001_TIME);
195        gc.set(Calendar.MILLISECOND, 0);
196        gc.set(Calendar.HOUR_OF_DAY, hour);
197        gc.set(Calendar.MINUTE, minute);
198        gc.set(Calendar.SECOND, second);
199        return new Time(gc.getTime().getTime());
200      }
201    
202      public static java.sql.Date createDate(final int year, final int month, final int day,
203          final LocalizationContext context)
204      {
205        final GregorianCalendar gc = new GregorianCalendar(context.getTimeZone(),
206            context.getLocale());
207        gc.set(Calendar.DAY_OF_MONTH, day);
208        gc.set(Calendar.MONTH, month - 1);
209        gc.set(Calendar.YEAR, year);
210        gc.set(Calendar.MILLISECOND, 0);
211        gc.set(Calendar.HOUR_OF_DAY, 0);
212        gc.set(Calendar.MINUTE, 0);
213        gc.set(Calendar.SECOND, 0);
214        return new java.sql.Date(gc.getTime().getTime());
215      }
216    
217      public static Calendar createCalendar(final Date date, final LocalizationContext context)
218      {
219        final GregorianCalendar gc = new GregorianCalendar(context.getTimeZone(),
220            context.getLocale());
221        gc.setTime(date);
222        return gc;
223      }
224    
225    
226      public static void main(final String[] args)
227      {
228        final DefaultLocalizationContext context = new DefaultLocalizationContext();
229        final java.sql.Date createDate = createDate(2006, 05, 01, context);
230        final Number serial = toSerialDate(createDate, context);
231        System.out.println(createDate);
232        System.out.println(serial);
233        final Date toJavaDate = toJavaDate(serial, context);
234        System.out.println(normalizeDate(toJavaDate, DateTimeType.DATE_TYPE));
235        System.out.println(toJavaDate);
236        System.out.println(HSSFDateUtil.getJavaDate(serial.doubleValue()));
237      }
238      
239    }