View Javadoc
1   /*
2    * #%L
3    * Nuiton Utils
4    * %%
5    * Copyright (C) 2004 - 2010 CodeLutin
6    * %%
7    * This program is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU Lesser General Public License as 
9    * published by the Free Software Foundation, either version 3 of the 
10   * License, or (at your option) any later version.
11   * 
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Lesser Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Lesser Public 
18   * License along with this program.  If not, see
19   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
20   * #L%
21   */
22  
23  package org.nuiton.util;
24  
25  import java.text.DateFormat;
26  import java.text.DateFormatSymbols;
27  import java.text.ParseException;
28  import java.text.SimpleDateFormat;
29  import java.time.LocalDate;
30  import java.time.Period;
31  import java.time.ZoneId;
32  import java.util.Calendar;
33  import java.util.Date;
34  import java.util.Locale;
35  
36  /**
37   * Library for manipulating dates.
38   * <p>
39   * <b>Note: </b>
40   *
41   * @author fdesbois
42   * @since 1.4.1
43   */
44  public class DateUtil {
45  
46      public static final String DEFAULT_PATTERN = "dd/MM/yyyy";
47  
48      public static final String MONTH_PATTERN = "MM/yyyy";
49  
50      /**
51       * Format a date using the pattern in argument. The pattern is the same using
52       * for DateFormat object.
53       *
54       * @param date    the date to format
55       * @param pattern the pattern to use
56       * @return a String corresponding to the date formatted
57       * @see DateFormat
58       */
59      public static String formatDate(Date date, String pattern) {
60          SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
61          return simpleDateFormat.format(date);
62      }
63  
64      public static String formatDate(Date date, String pattern, Locale locale) {
65          SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern, locale);
66          return simpleDateFormat.format(date);
67      }
68  
69      /**
70       * Parse a date using the pattern in argument. The pattern is the same using
71       * for DateFormat object.
72       *
73       * @param date    the String to parse
74       * @param pattern the pattern to use
75       * @return a Date corresponding to the String argument parsed
76       * @throws ParseException for parsing errors
77       * @see DateFormat
78       */
79      public static Date parseDate(String date, String pattern) throws ParseException {
80          SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
81          Date result = simpleDateFormat.parse(date);
82          return result;
83      }
84  
85      /**
86       * Create a new date from day, month and year (French version).
87       * The month is the real month of the year and not the one which is stored
88       * in Calendar object.
89       *
90       * @param s  value of the seconds 1-60
91       * @param m  value of the minutes 1-60
92       * @param h  value of the hours 1-24
93       * @param dd value of the day 1-31
94       * @param mm value of the month 1-12
95       * @param yy value of the year 0-9999
96       * @return a new date
97       */
98      public static Date createDate(int s, int m, int h, int dd, int mm, int yy) {
99          Calendar calendar = Calendar.getInstance();
100         calendar.setTimeInMillis(0L);
101         calendar.set(Calendar.YEAR, yy);
102         calendar.set(Calendar.MONTH, mm - 1);
103         calendar.set(Calendar.DAY_OF_MONTH, dd);
104         calendar.set(Calendar.HOUR_OF_DAY, h);
105         calendar.set(Calendar.MINUTE, m);
106         calendar.set(Calendar.SECOND, s);
107         return calendar.getTime();
108     }
109 
110     /**
111      * Create a new date from day, month and year (French version).
112      * The month is the real month of the year and not the one which is stored
113      * in Calendar object. Time is set to 00:00:00.000
114      *
115      * @param dd value of the day 1-31
116      * @param mm value of the month 1-12
117      * @param yy value of the year 0-9999
118      * @return a new date
119      */
120     public static Date createDate(int dd, int mm, int yy) {
121         Calendar calendar = Calendar.getInstance();
122         calendar.set(Calendar.YEAR, yy);
123         calendar.set(Calendar.MONTH, mm - 1);
124         calendar.set(Calendar.DAY_OF_MONTH, dd);
125         return setMinTimeOfDay(calendar.getTime());
126     }
127 
128     /**
129      * Create a new date after the current date (today) with modification on day, month and year.
130      * You can use negative values on arguments to have a date before today.
131      *
132      * @param ddStep nb days you want to increase from the current date
133      * @param mmStep nb months you want to increase from the current date
134      * @param yyStep nb years you want to increase from the current date
135      * @return a new date from the current date increase by days, months and years.
136      */
137     public static Date createDateAfterToday(int ddStep, int mmStep, int yyStep) {
138         Calendar calendar = getDefaultCalendar(new Date());
139         calendar.add(Calendar.DAY_OF_MONTH, ddStep);
140         calendar.add(Calendar.MONTH, mmStep);
141         calendar.add(Calendar.YEAR, yyStep);
142         return calendar.getTime();
143     }
144 
145     /**
146      * Set the last day of month to the date in argument.
147      * The value depends on the month of the date. (30 april, 28 february, ...)
148      *
149      * @param date Date to modify
150      * @return the date with day of month modified
151      */
152     public static Date setLastDayOfMonth(Date date) {
153         Calendar calendar = getDefaultCalendar(date);
154         int maximum = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
155         calendar.set(Calendar.DAY_OF_MONTH, maximum);
156         Date lastDay = calendar.getTime();
157         return lastDay;
158     }
159 
160     /**
161      * Set the first day of month to the date in argument.
162      *
163      * @param date Date to modify
164      * @return the date with day of month modified
165      */
166     public static Date setFirstDayOfMonth(Date date) {
167         Calendar calendar = getDefaultCalendar(date);
168         calendar.set(Calendar.DAY_OF_MONTH, 1);
169         Date firstDay = calendar.getTime();
170         return firstDay;
171     }
172 
173     /**
174      * Set the last day of year to the date in argument.
175      *
176      * @param date Date to modify
177      * @return the date with day of year modified
178      */
179     public static Date setLastDayOfYear(Date date) {
180         Calendar calendar = getDefaultCalendar(date);
181         int maximum = calendar.getActualMaximum(Calendar.DAY_OF_YEAR);
182         calendar.set(Calendar.DAY_OF_YEAR, maximum);
183         Date lastDay = calendar.getTime();
184         return lastDay;
185     }
186 
187     /**
188      * Set the first day of year to the date in argument.
189      *
190      * @param date Date to modify
191      * @return the date with day of year modified
192      */
193     public static Date setFirstDayOfYear(Date date) {
194         Calendar calendar = getDefaultCalendar(date);
195         calendar.set(Calendar.DAY_OF_YEAR, 1);
196         Date firstDay = calendar.getTime();
197         return firstDay;
198     }
199 
200     /**
201      * Set the min time of the day : 00:00:00.000.
202      *
203      * @param date to modify
204      * @return Date with the time set to the minimum in the day
205      */
206     public static Date setMinTimeOfDay(Date date) {
207         Calendar calendar = getDefaultCalendar(date);
208         calendar.set(Calendar.AM_PM, Calendar.AM);
209         calendar.set(Calendar.HOUR, 0);
210         calendar.set(Calendar.MINUTE, 0);
211         calendar.set(Calendar.SECOND, 0);
212         calendar.set(Calendar.MILLISECOND, 0);
213         return calendar.getTime();
214     }
215 
216     /**
217      * Set the max time of the day. EUROPE : 23:59:59.999.
218      *
219      * @param date to modify
220      * @return Date with the time set to the maximum in the day
221      */
222     public static Date setMaxTimeOfDay(Date date) {
223         Calendar calendar = getDefaultCalendar(date);
224         calendar.set(Calendar.AM_PM, Calendar.PM);
225         calendar.set(Calendar.HOUR, 11);
226         calendar.set(Calendar.MINUTE, 59);
227         calendar.set(Calendar.SECOND, 59);
228         calendar.set(Calendar.MILLISECOND, 999);
229         return calendar.getTime();
230     }
231 
232     /**
233      * Check if the first date in argument is included between the two other
234      * dates. The argument myDate can be equals to beforeDate or afterDate to
235      * validate the includes.
236      *
237      * @param myDate     the date to test
238      * @param beforeDate the first date of the period to test
239      * @param afterDate  the second date of the period to test
240      * @return true if myDate is included between beforeDate and afterDate
241      */
242     public static boolean between(Date myDate, Date beforeDate, Date afterDate) {
243         if (myDate == null) {
244             return false;
245         }
246         boolean result = true;
247         result &= myDate.after(beforeDate) || myDate.compareTo(beforeDate) == 0;
248         result &= afterDate == null || myDate.before(afterDate) ||
249                 myDate.compareTo(afterDate) == 0;
250         return result;
251     }
252 
253     /**
254      * Check if the current date is between the two dates in argument.
255      *
256      * @param beforeDate the first date of the period
257      * @param afterDate  the second date of the period
258      * @return true if the current date is included between the two dates,
259      * false otherwise
260      * @see #between(Date, Date, Date)
261      */
262     public static boolean currentPeriod(Date beforeDate, Date afterDate) {
263         return between(new Date(), beforeDate, afterDate);
264     }
265 
266     /**
267      * Get the month value from a date (between 0 and 11).
268      *
269      * @param date the date to extract month
270      * @return the month value of the date
271      */
272     public static int getMonth(Date date) {
273         Calendar calendar = getDefaultCalendar(date);
274         return calendar.get(Calendar.MONTH);
275     }
276 
277     /**
278      * Do the difference between the two dates in argument. The result is a number
279      * of seconds between the two dates.
280      *
281      * @param beginDate first date
282      * @param endDate   second date
283      * @return a number of seconds between beginDate and endDate
284      */
285     public static int getDifferenceInSeconds(Date beginDate, Date endDate) {
286         long begin = beginDate.getTime();
287         long end = endDate.getTime();
288         return (int) Math.ceil((end - begin) / 1000);
289     }
290 
291     /**
292      * Do the difference between the two dates in argument. The result is a number
293      * of minutes between the two dates.
294      *
295      * @param beginDate first date
296      * @param endDate   second date
297      * @return a number of minutes between beginDate and endDate
298      */
299     public static int getDifferenceInMinutes(Date beginDate, Date endDate) {
300         long begin = beginDate.getTime();
301         long end = endDate.getTime();
302         // 60000 = 60 * 1000
303         return (int) Math.ceil((end - begin) / 60000);
304     }
305 
306     /**
307      * Do the difference between the two dates in argument. The result is a number
308      * of hours between the two dates.
309      *
310      * @param beginDate first date
311      * @param endDate   second date
312      * @return a number of hours between beginDate and endDate
313      */
314     public static int getDifferenceInHours(Date beginDate, Date endDate) {
315         long begin = beginDate.getTime();
316         long end = endDate.getTime();
317         // 3600000 = 60 * 60 * 1000
318         return (int) Math.ceil((end - begin) / 3600000);
319     }
320 
321     /**
322      * Do the difference between the two dates in argument. The result is a number
323      * of days between the two dates.
324      * Ex : 28/01/2009 and 08/02/2009 return 11.
325      *
326      * @param beginDate first date
327      * @param endDate   second date
328      * @return a number of days between beginDate and endDate
329      */
330     public static int getDifferenceInDays(Date beginDate, Date endDate) {
331 
332         LocalDate beginLocalDate = beginDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
333         LocalDate endLocalDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
334 
335         Period period = Period.between(beginLocalDate, endLocalDate);
336         int diff = period.getDays();
337 
338         return diff;
339     }
340 
341     /**
342      * Do the difference between the two dates in argument. The result is a number
343      * of months between the two dates.
344      * Ex : 01/01/2009 and 28/02/2009 return 2 months.
345      * Warning, if beginDate is inferior to endDate, the result will be 1 minimum
346      *
347      * @param beginDate first date
348      * @param endDate   second date
349      * @return a number of months between beginDate and endDate
350      */
351     public static int getDifferenceInMonths(Date beginDate, Date endDate) {
352         int count = 0;
353         Calendar fromCalendar = getDefaultCalendar(beginDate);
354         Calendar thruCalendar = getDefaultCalendar(endDate);
355 
356         while (fromCalendar.before(thruCalendar)) {
357             fromCalendar.add(Calendar.MONTH, 1);
358             count++;
359         }
360         return count;
361     }
362 
363     /**
364      * Get the age of a person born on the date in argument. The result is a number
365      * of years between the birth date and now.
366      * Ex : 01/01/2000 returns 11 years (now date is 26/10/2011).
367      *
368      * @param birthDate birth date
369      * @return a number of years between birthDate and now
370      */
371     public static int getAge(Date birthDate) {
372         int count = 0;
373         Calendar fromCalendar = getDefaultCalendar(birthDate);
374         Calendar thruCalendar = getDefaultCalendar(new Date());
375 
376         fromCalendar.add(Calendar.YEAR, 1);
377         while (fromCalendar.before(thruCalendar)) {
378             count++;
379             fromCalendar.add(Calendar.YEAR, 1);
380         }
381         return count;
382     }
383 
384     /**
385      * Get libelle of the month corresponding to the number given in argument.
386      *
387      * @param monthNumber between 1-12
388      * @param locale      Locale for language support
389      * @return a String corresponding to the libelle of the month
390      */
391     public static String getMonthLibelle(int monthNumber, Locale locale) {
392         return new DateFormatSymbols(locale).getMonths()[monthNumber - 1];
393     }
394 
395     /**
396      * Get libelle of the month corresponding to the number given in argument.
397      *
398      * @param monthNumber between 1-12
399      * @return a String corresponding to the libelle of the month
400      */
401     public static String getMonthLibelle(int monthNumber) {
402         return getMonthLibelle(monthNumber, Locale.getDefault());
403     }
404 
405     /**
406      * Get the date before today
407      *
408      * @param date concerned
409      * @return Date before today
410      */
411     public static Date getYesterday(Date date) {
412         Calendar cal = getDefaultCalendar(date);
413         if (cal.get(Calendar.MONTH) == Calendar.JANUARY && cal.get(Calendar.DAY_OF_MONTH) == 1) {
414             cal.roll(Calendar.YEAR, false);
415         }
416         if (cal.get(Calendar.DAY_OF_MONTH) == 1) {
417             cal.roll(Calendar.MONTH, false);
418         }
419         cal.roll(Calendar.DAY_OF_MONTH, false);
420         return cal.getTime();
421     }
422 
423     /**
424      * Get the calendar corresponding to the {@code date}. The default calendar
425      * will be returned (default time zone and locale).
426      *
427      * @param date used to set the calendar time
428      * @return the default calendar with time corresponding to the {@code date}
429      */
430     public static Calendar getDefaultCalendar(Date date) {
431         Calendar calendar = Calendar.getInstance();
432         calendar.setTime(date);
433         return calendar;
434     }
435 
436     /**
437      * Truncate a date to its week (to monday). It's equivalent to a call to
438      * {@link org.apache.commons.lang3.time.DateUtils#truncate(Date, int)}
439      * and giving {@link Calendar#DAY_OF_WEEK} argument, but such a call
440      * raise an exception showing that this field is not supported. This method
441      * allows you to bypass this limitation.
442      *
443      * @param date any date
444      * @return a date in the same week as given date, a monday. All field below
445      * (hours, secondes, ms) are zeroed.
446      */
447     public static Date truncateToDayOfWeek(Date date) {
448         Calendar calendar = Calendar.getInstance();
449         calendar.setTime(date);
450         calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
451         calendar.set(Calendar.HOUR_OF_DAY, 0);
452         calendar.set(Calendar.MINUTE, 0);
453         calendar.set(Calendar.SECOND, 0);
454         calendar.set(Calendar.MILLISECOND, 0);
455         return calendar.getTime();
456     }
457 
458 
459     /**
460      * Enleve les données des heures (hour, minute, second, milli = 0).
461      *
462      * @param date la date a modifier
463      * @return la date d'un jour
464      */
465     public static Date getDay(Date date) {
466         Calendar calendar = Calendar.getInstance();
467         calendar.setTime(date);
468         calendar.set(Calendar.MILLISECOND, 0);
469         calendar.set(Calendar.SECOND, 0);
470         calendar.set(Calendar.MINUTE, 0);
471         calendar.set(Calendar.HOUR_OF_DAY, 0);
472         date = calendar.getTime();
473         return date;
474     }
475 
476     /**
477      * Positionne une date sur la fin d'un jour
478      *
479      * @param date la date a modifier
480      * @return la date d'un jour
481      */
482     public static Date getEndOfDay(Date date) {
483         Calendar calendar = Calendar.getInstance();
484         calendar.setTime(date);
485         calendar.set(Calendar.MILLISECOND, 999);
486         calendar.set(Calendar.SECOND, 59);
487         calendar.set(Calendar.MINUTE, 59);
488         calendar.set(Calendar.HOUR_OF_DAY, 23);
489         date = calendar.getTime();
490         return date;
491     }
492 
493     /**
494      * Créer la date qui utilise le jour donné dans {@code day} et l'heure
495      * donnée dans {@code time}.
496      *
497      * @param day           le jour à utiliser
498      * @param time          l'heure a utiliser
499      * @param useSecond     FIXME
500      * @param useMiliSecond FIXME
501      * @return la date donnée avec l'heure courante
502      */
503     public static Date getDateAndTime(Date day, Date time, boolean useSecond, boolean useMiliSecond) {
504 
505         Calendar calendar = Calendar.getInstance();
506 
507         // recuperation de l'heure
508         calendar.setTime(time);
509         int h = calendar.get(Calendar.HOUR_OF_DAY);
510         int m = calendar.get(Calendar.MINUTE);
511         int s = useSecond ? calendar.get(Calendar.SECOND) : 0;
512         int ms = useMiliSecond ? calendar.get(Calendar.MILLISECOND) : 0;
513 
514         calendar.setTime(day);
515 
516         // appliquer l'heure
517         calendar.set(Calendar.HOUR_OF_DAY, h);
518         calendar.set(Calendar.MINUTE, m);
519         calendar.set(Calendar.SECOND, s);
520         calendar.set(Calendar.MILLISECOND, ms);
521 
522         return calendar.getTime();
523 
524     }
525 
526     /**
527      * Créer la date qui utilise uniquement l'heure
528      * donnée dans {@code dayTime}.
529      *
530      * @param dayTime       l'heure a utiliser
531      * @param useSecond     FIXME
532      * @param useMiliSecond FIXME
533      * @return la date donnée avec uniquement l'heure courante
534      */
535     public static Date getTime(Date dayTime, boolean useSecond, boolean useMiliSecond) {
536         Calendar calendar = Calendar.getInstance();
537 
538         // recuperation de l'heure
539         calendar.setTime(dayTime);
540         int h = calendar.get(Calendar.HOUR_OF_DAY);
541         int m = calendar.get(Calendar.MINUTE);
542         int s = calendar.get(Calendar.SECOND);
543         int ms = calendar.get(Calendar.MILLISECOND);
544 
545 
546         // on part d'une date vide
547         calendar.setTimeInMillis(0);
548 
549         // appliquer l'heure
550         calendar.set(Calendar.HOUR_OF_DAY, h);
551         calendar.set(Calendar.MINUTE, m);
552         if (useSecond) {
553             calendar.set(Calendar.SECOND, s);
554         }
555         if (useMiliSecond) {
556             calendar.set(Calendar.MILLISECOND, ms);
557         }
558 
559         return calendar.getTime();
560     }
561 }