001    /*
002     * Created on Jan 22, 2011
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
005     * the License. You may obtain a copy of the License at
006     * 
007     * http://www.apache.org/licenses/LICENSE-2.0
008     * 
009     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
010     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
011     * specific language governing permissions and limitations under the License.
012     * 
013     * Copyright @2011 the original author or authors.
014     */
015    package org.fest.util;
016    
017    import java.text.DateFormat;
018    import java.text.ParseException;
019    import java.text.SimpleDateFormat;
020    import java.util.Calendar;
021    import java.util.Date;
022    
023    /**
024     * Utility methods related to dates.
025     * 
026     * @author Joel Costigliola
027     */
028    public class Dates {
029    
030      /**
031       * ISO 8601 date format (yyyy-MM-dd), example : <code>2003-04-23</code>
032       */
033      public static final DateFormat ISO_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
034    
035      /**
036       * ISO 8601 date-time format (yyyy-MM-dd'T'HH:mm:ss), example : <code>2003-04-26T13:01:02</code>
037       */
038      public static final DateFormat ISO_DATE_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
039    
040      /**
041       * ISO 8601 date-time format with millisecond (yyyy-MM-dd'T'HH:mm:ss.SSS), example : <code>2003-04-26T03:01:02.999</code>
042       */
043      public static final DateFormat ISO_DATE_TIME_FORMAT_WITH_MS = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
044      
045      /**
046       * Formats the given date using the ISO 8601 date-time format (yyyy-MM-dd'T'HH:mm:ss).<br>
047       * Method in synchronized because SimpleDateFormat is not thread safe (sigh).
048       * <p>
049       * Returns null if given the date is null.
050       * @param date the date to format.
051       * @return the formatted date or null if given the date was null.
052       */
053      public static synchronized String formatAsDatetime(Date date) {
054        return date == null ? null : ISO_DATE_TIME_FORMAT.format(date);
055      }
056    
057      /**
058       * Formats the given date using the ISO 8601 date-time format with millisecond (yyyy-MM-dd'T'HH:mm:ss:SSS).<br>
059       * Method in synchronized because SimpleDateFormat is not thread safe (sigh).
060       * <p>
061       * Returns null if given the date is null.
062       * @param date the date to format.
063       * @return the formatted date or null if given the date was null.
064       */
065      public static synchronized String formatAsDatetimeWithMs(Date date) {
066        return date == null ? null : ISO_DATE_TIME_FORMAT_WITH_MS.format(date);
067      }
068    
069      /**
070       * Formats the date of the given calendar using the ISO 8601 date-time format (yyyy-MM-dd'T'HH:mm:ss).<br>
071       * Method is thread safe.
072       * <p>
073       * Returns null if the given calendar is null.
074       * @param calendar the calendar to format.
075       * @return the formatted calendar or null if the given calendar was null.
076       */
077      public static String formatAsDatetime(Calendar calendar) {
078        return calendar == null ? null : formatAsDatetime(calendar.getTime());
079      }
080    
081      /**
082       * Utility method to parse a Date following {@link #ISO_DATE_FORMAT}, returns null if the given String is null.
083       * @param dateAsString the string to parse as a Date following {@link #ISO_DATE_FORMAT}
084       * @return the corrresponding Date or null if the given String is null.
085       * @throws RuntimeException encapsulating ParseException if the string can't be parsed as a Date
086       */
087      public static Date parse(String dateAsString) {
088        try {
089          return dateAsString == null ? null : ISO_DATE_FORMAT.parse(dateAsString);
090        } catch (ParseException e) {
091          throw new RuntimeException(e);
092        }
093      }
094    
095      /**
096       * Utility method to parse a Date following {@link #ISO_DATE_TIME_FORMAT}, returns null if the given String is null.
097       * @param dateAsString the string to parse as a Date following {@link #ISO_DATE_TIME_FORMAT}
098       * @return the corrresponding Date with time details or null if the given String is null.
099       * @throws RuntimeException encapsulating ParseException if the string can't be parsed as a Date
100       */
101      public static Date parseDatetime(String dateAsString) {
102        try {
103          return dateAsString == null ? null : ISO_DATE_TIME_FORMAT.parse(dateAsString);
104        } catch (ParseException e) {
105          throw new RuntimeException(e);
106        }
107      }
108      
109      /**
110       * Converts the given Date to Calendar, returns null if the given Date is null.
111       * @param date the date to convert to a Calendar.
112       * @return the Calendar corresponding to the given Date or null if the given Date is null.
113       */
114      public static Calendar toCalendar(Date date) {
115        if (date == null) { return null; }
116        Calendar calendar = Calendar.getInstance();
117        calendar.setTime(date);
118        return calendar;
119      }
120    
121      /**
122       * Extracts the year of the given Date.
123       * @param date the date to extract the year from - must not be null.
124       * @return the year of the given Date
125       * @throws NullPointerException if given Date is null
126       */
127      public static int yearOf(Date date) {
128        return toCalendar(date).get(Calendar.YEAR);
129      }
130    
131      /**
132       * Dates Extracts the month of the given Date <b>starting at 1</b> (January=1, February=2, ...).
133       * @param date the date to extract the month from - must not be null.
134       * @return the month of the given Date <b>starting at 1</b> (January=1, February=2, ...)
135       * @throws NullPointerException if given Date is null
136       */
137      public static int monthOf(Date date) {
138        return toCalendar(date).get(Calendar.MONTH) + 1; // based 1 month (January=1)
139      }
140    
141      /**
142       * Dates Extracts the day of month of the given Date.
143       * @param date the date to extract the day of month from - must not be null.
144       * @return the day of month of the given Date
145       * @throws NullPointerException if given Date is null
146       */
147      public static int dayOfMonthOf(Date date) {
148        return toCalendar(date).get(Calendar.DAY_OF_MONTH);
149      }
150    
151      /**
152       * Extracts the day of week of the given Date, returned value follows {@link Calendar#DAY_OF_WEEK} .
153       * @param date the date to extract the day of week from - must not be null.
154       * @return the day of week of the given Date
155       * @throws NullPointerException if given Date is null
156       */
157      public static int dayOfWeekOf(Date date) {
158        return toCalendar(date).get(Calendar.DAY_OF_WEEK);
159      }
160    
161      /**
162       * Extracts the hour of day if the given Date (24-hour clock).
163       * @param date the date to extract the hour of day from - must not be null.
164       * @return the hour of day of the given Date (24-hour clock)
165       * @throws NullPointerException if given Date is null
166       */
167      public static int hourOfDay(Date date) {
168        return toCalendar(date).get(Calendar.HOUR_OF_DAY);
169      }
170    
171      /**
172       * Dates Extracts the minute of the given Date.
173       * @param date the date to extract the minute from - must not be null.
174       * @return the minute of the given Date
175       * @throws NullPointerException if given Date is null
176       */
177      public static int minuteOf(Date date) {
178        return toCalendar(date).get(Calendar.MINUTE);
179      }
180    
181      /**
182       * Extracts the second of the given Date.
183       * @param date the date to extract the second from - must not be null.
184       * @return the second of the given Date
185       * @throws NullPointerException if given Date is null
186       */
187      public static int secondOf(Date date) {
188        return toCalendar(date).get(Calendar.SECOND);
189      }
190    
191      /**
192       * Extracts the millisecond of the given Date.
193       * @param date the date to extract the millisecond from - must not be null.
194       * @return the millisecond of the given Date
195       * @throws NullPointerException if given Date is null
196       */
197      public static int millisecondOf(Date date) {
198        return toCalendar(date).get(Calendar.MILLISECOND);
199      }
200    
201      /**
202       * Returns a copy of the given date without the time part (which is set to 00:00:00), for example :<br>
203       * <code>truncateTime(2008-12-29T23:45:12)</code> will give <code>2008-12-29T00:00:00</code>.
204       * <p>
205       * Returns null if the given Date is null.
206       * @param date we want to get the day part (the parameter is read only).
207       * @return the truncated date.
208       */
209      public static Date truncateTime(Date date) {
210        if (date == null) { return null; }
211        Calendar cal = toCalendar(date);
212        cal.set(Calendar.HOUR_OF_DAY, 0);
213        cal.set(Calendar.MINUTE, 0);
214        cal.set(Calendar.SECOND, 0);
215        cal.set(Calendar.MILLISECOND, 0);
216        return cal.getTime();
217      }
218    
219      public static Date today() {
220        return new Date();
221      }
222      
223      public static Date yesterday() {
224        Calendar cal = Calendar.getInstance();
225        cal.add(Calendar.DAY_OF_MONTH, -1);
226        return cal.getTime();
227      }
228      
229      public static Date tomorrow() {
230        Calendar cal = Calendar.getInstance();
231        cal.add(Calendar.DAY_OF_MONTH, 1);
232        return cal.getTime();
233      }
234    }