View Javadoc

1   /*
2    *  File: JaretDate.java 
3    *  Copyright (c) 2004-2007  Peter Kliem (Peter.Kliem@jaret.de)
4    *  A commercial license is available, see http://www.jaret.de.
5    *
6    * All rights reserved. This program and the accompanying materials
7    * are made available under the terms of the Common Public License v1.0
8    * which accompanies this distribution, and is available at
9    * http://www.eclipse.org/legal/cpl-v10.html
10   */
11  package de.jaret.util.date;
12  
13  import java.util.Calendar;
14  import java.util.Date;
15  import java.util.GregorianCalendar;
16  import java.util.Locale;
17  import java.util.TimeZone;
18  
19  import de.jaret.util.misc.PropertyObservableBase;
20  
21  /**
22   * A wrapper for <code>java.util.Date</code> and <code>java.util.Calendar</code> to ease the use of date and time.
23   * There are some convenience methods for quick textual output. They are located in a delegate that supports i8n. Use
24   * <code>setLocale</code> to set the locale of the delegate. The delegate is static and any change will affect the
25   * output of all JaretDates!
26   * <p>
27   * A good practice is to use an immutable type for representing dates. The JaretDate is not immutable! This is nice in a
28   * lot of ways but it requires some caution when copying instances. Recommended is to use it like an immuntable type
29   * most of the times (use the copy() method).
30   * </p>
31   * 
32   * @author Peter Kliem
33   * @version $Id: JaretDate.java 883 2009-10-07 21:03:00Z kliem $
34   */
35  public class JaretDate extends PropertyObservableBase implements Comparable<JaretDate> {
36      /** number of milliseconds in one hour. */
37      public static final long MILLIS_PER_HOUR = 60 * 60 * 1000;
38      /** number of milliseconds in one minute. */
39      public static final long MILLIS_PER_MINUTE = 60 * 1000;
40      /** number of milliseconds in one second. */
41      public static final long MILLIS_PER_SECOND = 1000;
42  
43      /**
44       * Delegate for date formatting and parsing.
45       */
46      private static JaretDateFormatter _jaretDateFormatter = new JaretDateFormatter();
47  
48      /** encapsulated Date. */
49      private Date _date;
50      /** Calendar will only be instantiated if necessary. */
51      private Calendar _calendar;
52  
53      /**
54       * Constructs a JaretDate with the current date and time.
55       */
56      public JaretDate() {
57          _date = new Date();
58      }
59  
60      /**
61       * Constructs a JaretDate using a clone of the given Date.
62       * 
63       * @param date initial date to set
64       */
65      public JaretDate(Date date) {
66          _date = (Date) date.clone();
67      }
68  
69      /**
70       * Constructs a JaretDate by milliseconds given in a String.
71       * 
72       * @param millisecondsString as String
73       */
74      public JaretDate(String millisecondsString) {
75          long ms = Long.parseLong(millisecondsString);
76          _date = new Date(ms);
77      }
78  
79      /**
80       * Constructs a JaretDate using the given millesecond value.
81       * 
82       * @param milliseconds as long
83       */
84      public JaretDate(long milliseconds) {
85          long ms = milliseconds;
86          _date = new Date(ms);
87      }
88  
89      /**
90       * Constructs a new JaretDate object with the same time as the given jaretDate.
91       * 
92       * @param jdate JaretDate to copy
93       */
94      public JaretDate(JaretDate jdate) {
95          _date = new Date(jdate.getDate().getTime());
96      }
97  
98      /**
99       * Constructs a JaretDate setting it to a given date and time.
100      * 
101      * @param day day of month
102      * @param month month of year
103      * @param year year
104      * @param hours hours in day
105      * @param minutes minutes in hour
106      * @param seconds seconds in minute
107      */
108     public JaretDate(int day, int month, int year, int hours, int minutes, int seconds) {
109         this();
110         setDateTime(day, month, year, hours, minutes, seconds);
111     }
112 
113     /**
114      * Retrieve the configured JaretDateFormatter.
115      * 
116      * @return JaretDateFormatter used for formatting and parsing
117      */
118     public JaretDateFormatter getJaretDateFormatter() {
119         return _jaretDateFormatter;
120     }
121 
122     /**
123      * Sets the JaretDateFormatter to be used for parsing and formatting. The JaretDateFormatter is used for all
124      * JaretDates! A Change will affect parsing and formatting of all JaretDates!
125      * 
126      * @param jaretDateFormatter the new Formatter to be used.
127      */
128     public static void setJaretDateFormatter(JaretDateFormatter jaretDateFormatter) {
129         // JaretDateFormatter oldVal = _jaretDateFormatter;
130         _jaretDateFormatter = jaretDateFormatter;
131         // if we detect a real change, fire a prop change thus enabling listeners to redraw
132         // textual representations
133         /*
134          * if (!oldVal.equals(jaretDateFormatter)) { firePropertyChange(); }
135          */}
136 
137     /**
138      * Set the locale of the JaretDateFormatter. Calling will fire a property change for the date.
139      * 
140      * @param locale Locale to be used
141      */
142     public void setLocale(Locale locale) {
143         _jaretDateFormatter.setLocale(locale);
144         firePropertyChange();
145     }
146 
147     /**
148      * Sets the date and time of the JaretDate by values.
149      * 
150      * @param day day of month
151      * @param month month of year
152      * @param year year
153      * @param hours hours in day
154      * @param minutes minutes in hour
155      * @param seconds seconds in minute
156      * @param milliseconds milliseconds in second
157      */
158     public void setDateTime(int day, int month, int year, int hours, int minutes, int seconds, int milliseconds) {
159         Calendar cal = getCalendar();
160         cal.set(Calendar.DAY_OF_MONTH, day);
161         cal.set(Calendar.MONTH, month - 1);
162         cal.set(Calendar.YEAR, year);
163         cal.set(Calendar.HOUR_OF_DAY, hours);
164         cal.set(Calendar.MINUTE, minutes);
165         cal.set(Calendar.SECOND, seconds);
166         cal.set(Calendar.MILLISECOND, milliseconds);
167         _date.setTime(cal.getTimeInMillis());
168         firePropertyChange();
169     }
170 
171     /**
172      * Sets the date and time of the JaretDate by values.
173      * 
174      * @param day day of month
175      * @param month month of year
176      * @param year year
177      * @param hours hours in day
178      * @param minutes minutes in hour
179      * @param seconds seconds in minute
180      */
181     public void setDateTime(int day, int month, int year, int hours, int minutes, int seconds) {
182         setDateTime(day, month, year, hours, minutes, seconds, 0);
183     }
184 
185     /**
186      * Set the time. Does not affect the date.
187      * 
188      * @param hours hour value
189      * @param minutes minute value
190      * @param seconds seconds value
191      * @param milliseconds millisecond value
192      * @return the modified date
193      */
194     public JaretDate setTime(int hours, int minutes, int seconds, int milliseconds) {
195         Calendar cal = getCalendar();
196         cal.set(Calendar.HOUR_OF_DAY, hours);
197         cal.set(Calendar.MINUTE, minutes);
198         cal.set(Calendar.SECOND, seconds);
199         cal.set(Calendar.MILLISECOND, milliseconds);
200         _date.setTime(cal.getTimeInMillis());
201         firePropertyChange();
202         return this;
203     }
204 
205     /**
206      * Set the time. Does not affect the date. Will set the milliseconds to zero.
207      * 
208      * @param hours hour value
209      * @param minutes minute value
210      * @param seconds seconds value
211      * @return the modified date
212      */
213     public JaretDate setTime(int hours, int minutes, int seconds) {
214         setTime(hours, minutes, seconds, 0);
215         return this;
216     }
217 
218     /**
219      * Set the date. Does not affect the time.
220      * 
221      * @param day day of month
222      * @param month month
223      * @param year year
224      * @return this
225      */
226     public JaretDate setDate(int day, int month, int year) {
227         Calendar cal = getCalendar();
228         cal.set(Calendar.DAY_OF_MONTH, day);
229         cal.set(Calendar.MONTH, month - 1);
230         cal.set(Calendar.YEAR, year);
231         _date.setTime(cal.getTimeInMillis());
232         firePropertyChange();
233         return this;
234     }
235 
236     /**
237      * Set the date. Does not affect the time.
238      * 
239      * @param date JaretDate to copy the date from
240      * @return this
241      */
242     public JaretDate setDate(JaretDate date) {
243         setDate(date.getDay(), date.getMonth(), date.getYear());
244         return this;
245     }
246 
247     
248     
249     /**
250      * Set the month of the year.
251      * 
252      * @param month month of the year (1=january
253      */
254     public void setMonth(int month) {
255         Calendar cal = getCalendar();
256         cal.set(Calendar.MONTH, month - 1);
257         _date.setTime(cal.getTimeInMillis());
258         firePropertyChange();
259     }
260 
261     /**
262      * Set the day of month.
263      * 
264      * @param day day of month
265      */
266     public void setDay(int day) {
267         Calendar cal = getCalendar();
268         cal.set(Calendar.DAY_OF_MONTH, day);
269         _date.setTime(cal.getTimeInMillis());
270         firePropertyChange();
271     }
272 
273     /**
274      * Set the hour in day field of the date. Does not affect any other field.
275      * 
276      * @param hours hour value to set
277      */
278     public void setHours(int hours) {
279         if (hours > 23) {
280             throw new IllegalArgumentException("hour must not exceedd 23");
281         }
282         Calendar cal = getCalendar();
283         cal.set(Calendar.HOUR_OF_DAY, hours);
284         _date.setTime(cal.getTimeInMillis());
285         firePropertyChange();
286     }
287 
288     /**
289      * Set the minutes in the date. Does not affect any other field.
290      * 
291      * @param minutes minute value
292      */
293     public void setMinutes(int minutes) {
294         if (minutes > 59) {
295             throw new IllegalArgumentException("minutes must not exceed 59");
296         }
297         Calendar cal = getCalendar();
298         cal.set(Calendar.MINUTE, minutes);
299         _date.setTime(cal.getTimeInMillis());
300         firePropertyChange();
301     }
302 
303     /**
304      * Set the seconds. Will set the milliseconds to zero.
305      * 
306      * @param seconds second value
307      */
308     public void setSeconds(int seconds) {
309         if (seconds > 59) {
310             throw new IllegalArgumentException("seconds must not exceed 59");
311         }
312         Calendar cal = getCalendar();
313         cal.set(Calendar.SECOND, seconds);
314         cal.set(Calendar.MILLISECOND, 0);
315         _date.setTime(cal.getTimeInMillis());
316         firePropertyChange();
317     }
318 
319     /**
320      * Set the milliseconds.
321      * 
322      * @param milliseconds millisecond value
323      */
324     public void setMilliseconds(int milliseconds) {
325         if (milliseconds > 999) {
326             throw new IllegalArgumentException("milliseconds must not exceed 999");
327         }
328         Calendar cal = getCalendar();
329         cal.set(Calendar.MILLISECOND, milliseconds);
330         _date.setTime(cal.getTimeInMillis());
331         firePropertyChange();
332     }
333 
334     /**
335      * Sets the date by a parseble String. If the String fails to be parsed the result will be <code>false</code> and
336      * the date will not be changed. The parsing will be delegated to the JaretDateFormatter.
337      * 
338      * @param text string to be parsed as date
339      * @return true if parsing is successful false otherwise
340      */
341     public boolean setDateByText(String text) {
342         Date date = _jaretDateFormatter.parseTextualDate(text);
343         if (date == null) {
344             return false;
345         } else {
346             _date = date;
347             firePropertyChange();
348             return true;
349         }
350     }
351 
352     /**
353      * Supply a configured (set to the current time) Calendar for internal use.
354      * 
355      * @return Calendar set to the current date
356      */
357     protected Calendar getCalendar() {
358         if (_calendar == null) {
359             _calendar = Calendar.getInstance(_jaretDateFormatter.getLocale());
360         }
361         _calendar.setTime(_date);
362         return _calendar;
363     }
364 
365     /**
366      * Calculate the Milliseconds from 0:00 ignoring the millisecond field.
367      * 
368      * @return Milliseconds from 0:00 ignoring millisecond field
369      */
370     public long getMillisInDay() {
371         Calendar cal = getCalendar();
372         long h = cal.get(Calendar.HOUR_OF_DAY);
373         long m = cal.get(Calendar.MINUTE);
374         long s = cal.get(Calendar.SECOND);
375         return h * MILLIS_PER_HOUR + m * MILLIS_PER_MINUTE + s * MILLIS_PER_SECOND;
376     }
377 
378     /**
379      * Returns the encapsulated java.util.Date.
380      * 
381      * @return the encapsulated java.util.Date
382      */
383     public Date getDate() {
384         return _date;
385     }
386 
387     /**
388      * Convenient way for a quick textual output of the timestamp.
389      * 
390      * @return a textual representation of the date (timestamp)
391      */
392     public String toDisplayString() {
393         return _jaretDateFormatter.generateDisplayString(this);
394     }
395 
396     /**
397      * Convenient way for quick textual output of the date (day) only.
398      * 
399      * @return a textual representation of the date (day)
400      */
401     public String toDisplayStringDate() {
402         return _jaretDateFormatter.generateDisplayStringDate(this);
403     }
404 
405     /**
406      * Convenient way for quick textual represenation (time).
407      * 
408      * @param seconds if true, seconds will be included in the format hh:mm:ss
409      * @return a textual represenation of the time
410      */
411     public String toDisplayStringTime(boolean seconds) {
412         return _jaretDateFormatter.toDisplayStringTime(this, seconds);
413     }
414 
415     /**
416      * 
417      * @return toDisplayStringTime(false)
418      */
419     public String toDisplayStringTime() {
420         return toDisplayStringTime(false);
421     }
422 
423     /**
424      * The standard toString behaviour is the value of the date in milliseconds.
425      * 
426      * @return milliseconds as String
427      */
428     public String toString() {
429         return Long.toString(_date.getTime());
430     }
431 
432     /**
433      * Sets the date to the current system time.
434      */
435     public void setToNow() {
436         _date.setTime(System.currentTimeMillis());
437         firePropertyChange();
438     }
439 
440     /**
441      * Substracts the the given date from this date and returns the difference in minutes.
442      * 
443      * @param date the Date to be substracted
444      * @return difference in minutes
445      */
446     public double diffMinutes(JaretDate date) {
447         return ((double) diffMilliSeconds(date)) / MILLIS_PER_MINUTE;
448     }
449 
450     /**
451      * Substracts the the given date from this date and returns the difference in seconds (long).
452      * 
453      * @param date the Date to be substracted
454      * @return difference in seconds (long)
455      */
456     public int diffSeconds(JaretDate date) {
457         return (int) ((_date.getTime() - date.getDate().getTime()) / MILLIS_PER_SECOND);
458     }
459 
460     /**
461      * Substracts the the given date from this date and returns the difference in seconds.
462      * 
463      * @param date the Date to be substracted
464      * @return difference in seconds
465      */
466     public long diffSecondsL(JaretDate date) {
467         return (long) ((_date.getTime() - date.getDate().getTime()) / MILLIS_PER_SECOND);
468     }
469 
470     /**
471      * Substracts the the given date from this date and returns the difference in milliseconds.
472      * 
473      * @param date the Date to be substracted
474      * @return difference in milliseconds
475      */
476     public long diffMilliSeconds(JaretDate date) {
477         return _date.getTime() - date.getDate().getTime();
478     }
479 
480     /**
481      * Advance by a certain number of months.
482      * 
483      * @param months number of months
484      * @return modified date
485      */
486     public JaretDate advanceMonths(int months) {
487         Calendar cal = getCalendar();
488         cal.add(Calendar.MONTH, months);
489         _date.setTime(cal.getTimeInMillis());
490         firePropertyChange();
491         return this;
492     }
493 
494     /**
495      * Advance by a certain number of years.
496      * 
497      * @param years number of years to advance
498      * @return modified date
499      */
500     public JaretDate advanceYears(int years) {
501         Calendar cal = getCalendar();
502         cal.add(Calendar.YEAR, years);
503         _date.setTime(cal.getTimeInMillis());
504         firePropertyChange();
505         return this;
506     }
507 
508     /**
509      * Advance by a certain number of days.
510      * 
511      * @param days number of days to advance
512      * @return modified date
513      */
514     public JaretDate advanceDays(int days) {
515         Calendar cal = getCalendar();
516         cal.add(Calendar.DAY_OF_YEAR, days);
517         _date.setTime(cal.getTimeInMillis());
518         firePropertyChange();
519         return this;
520     }
521 
522     /**
523      * Adds a number of days to the date.
524      * 
525      * @param days number of days to add
526      * @return the date for cascading calls
527      */
528     public JaretDate advanceDays(double days) {
529         _date.setTime(_date.getTime() + ((long) (days * 24.0 * 60.0 * 60.0 * 1000.0)));
530         firePropertyChange();
531         return this;
532     }
533 
534     public JaretDate backDays(double days) {
535         _date.setTime(_date.getTime() - ((long) (days * 24.0 * 60.0 * 60.0 * 1000.0)));
536         firePropertyChange();
537         return this;
538     }
539 
540     public JaretDate advanceHours(double hours) {
541         _date.setTime(_date.getTime() + ((long) (hours * 60.0 * 60.0 * 1000.0)));
542         firePropertyChange();
543         return this;
544     }
545 
546     public JaretDate backHours(double hours) {
547         _date.setTime(_date.getTime() - ((long) (hours * 60.0 * 60.0 * 1000.0)));
548         firePropertyChange();
549         return this;
550     }
551 
552     public JaretDate advanceMinutes(double minutes) {
553         _date.setTime(_date.getTime() + ((long) (minutes * 60.0 * 1000.0)));
554         firePropertyChange();
555         return this;
556     }
557 
558     public JaretDate backMinutes(double minutes) {
559         _date.setTime(_date.getTime() - ((long) (minutes * 60.0 * 1000.0)));
560         firePropertyChange();
561         return this;
562     }
563 
564     public JaretDate advanceSeconds(double seconds) {
565         _date.setTime(_date.getTime() + ((long) (seconds * 1000.0)));
566         firePropertyChange();
567         return this;
568     }
569 
570     public JaretDate advanceMillis(long millis) {
571         _date.setTime(_date.getTime() + millis);
572         firePropertyChange();
573         return this;
574     }
575 
576     public JaretDate backSeconds(double seconds) {
577         _date.setTime(_date.getTime() - ((long) (seconds * 1000.0)));
578         firePropertyChange();
579         return this;
580     }
581 
582     /**
583      * {@inheritDoc} Two JaretDates are equal if the encapsulated Date is equal.
584      */
585     public boolean equals(Object o) {
586         return _date.equals(((JaretDate) o).getDate());
587     }
588 
589     /**
590      * {@inheritDoc} Hashcode is the Hash of the encapsulted Date.
591      */
592     public int hashCode() {
593         return _date.hashCode();
594     }
595 
596     /**
597      * Compare this to another JaretDate.
598      * 
599      * @param date JaretDate to compare to
600      * @return 0 for an exact match, &gt;0 for this&gt;date, &lt;0 for this&lt;date
601      */
602     public int compareTo(JaretDate date) {
603         return _date.compareTo(date._date);
604     }
605 
606     /**
607      * Compares only the time of day of the date with the given day.
608      * 
609      * @param date the date to compare to
610      * @return 0 for an exact match, &gt;0 for this&gt;date, &lt;0 for this&lt;date
611      */
612     public long compareTimeTo(JaretDate date) {
613         return getMillisInDay() - date.getMillisInDay();
614     }
615 
616     /**
617      * Compare the date (day) of this and the given date.
618      * 
619      * @param date date to compare to
620      * @return 0 for exact match, &gt;0 for this&gt;date, &lt;0 for this&lt;date
621      */
622     public int compareDateTo(JaretDate date) {
623         int result;
624         result = getYear() - date.getYear();
625         if (result == 0) {
626             result = getDayOfYear() - date.getDayOfYear();
627         }
628         return result;
629     }
630 
631     /**
632      * Produce a new JaretDate with the time of this date.
633      * 
634      * @return a new instance of JaretDate
635      */
636     public JaretDate copy() {
637         return new JaretDate(this);
638     }
639 
640     /**
641      * Retrive the month (1 based).
642      * 
643      * @return month (1 for january)
644      */
645     public int getMonth() {
646         Calendar cal = getCalendar();
647         return cal.get(Calendar.MONTH) + 1;
648     }
649 
650     /**
651      * Retrieve a string for the month of the date (full length).
652      * 
653      * @return string for teh month
654      */
655     public String getMonthString() {
656         return _jaretDateFormatter.getMonthString(getMonth() - 1);
657     }
658 
659     /**
660      * Retrieve short string for the month.
661      * 
662      * @return shor (abbreviated) month name
663      */
664     public String getShortMonthString() {
665         return _jaretDateFormatter.getShortMonthString(getMonth() - 1);
666     }
667 
668     public int getWeekOfYear() {
669         Calendar cal = getCalendar();
670         return cal.get(Calendar.WEEK_OF_YEAR);
671     }
672 
673     /**
674      * Retrieve localized name of the current day of the week.
675      * 
676      * @return long name of the day of week
677      */
678     public String getDayOfWeekString() {
679         return _jaretDateFormatter.getDayOfWeekString(getDayOfWeek());
680     }
681 
682     public String getShortDayOfWeekString() {
683         return _jaretDateFormatter.getShortDayOfWeekString(getDayOfWeek());
684     }
685 
686     /**
687      * Get the day of the week as constant defined in java.util.Calendar.
688      * 
689      * @return day of the week.
690      */
691     public int getDayOfWeek() {
692         Calendar cal = getCalendar();
693         return cal.get(Calendar.DAY_OF_WEEK);
694     }
695 
696     public boolean isWeekendDay() {
697         return getDayOfWeek() == Calendar.SATURDAY || getDayOfWeek() == Calendar.SUNDAY;
698     }
699 
700     public int getDay() {
701         Calendar cal = getCalendar();
702         return cal.get(Calendar.DAY_OF_MONTH);
703     }
704 
705     public int getHours() {
706         Calendar cal = getCalendar();
707         return cal.get(Calendar.HOUR_OF_DAY);
708     }
709 
710     public int getMinutes() {
711         Calendar cal = getCalendar();
712         return cal.get(Calendar.MINUTE);
713     }
714 
715     public int getSeconds() {
716         Calendar cal = getCalendar();
717         return cal.get(Calendar.SECOND);
718     }
719 
720     public int getMillis() {
721         Calendar cal = getCalendar();
722         return cal.get(Calendar.MILLISECOND);
723     }
724 
725     public int getDayOfYear() {
726         Calendar cal = getCalendar();
727         return cal.get(Calendar.DAY_OF_YEAR);
728     }
729 
730     /**
731      * Retrieve the year of the date.
732      * 
733      * @return year of the date
734      */
735     public int getYear() {
736         Calendar cal = getCalendar();
737         return cal.get(Calendar.YEAR);
738     }
739 
740     private void firePropertyChange() {
741         firePropertyChange("date", null, this);
742     }
743 
744     /**
745      * Clear time fields to reduce the jaretdate to a clean date.
746      * 
747      */
748     public void clearTime() {
749         setHours(0);
750         setMinutes(0);
751         setSeconds(0);
752         setMilliseconds(0);
753     }
754 
755     /**
756      * Retrieve a jaret date for the first day in a given week.
757      * 
758      * @param week week
759      * @param year year
760      * @return first day of that week
761      */
762     public static JaretDate getFirstDayOfAWeek(int week, int year) {
763         Calendar cal = new GregorianCalendar();
764         cal.set(Calendar.YEAR, year);
765         cal.set(Calendar.WEEK_OF_YEAR, week);
766         cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
767         JaretDate d = new JaretDate(cal.getTime());
768         d.clearTime();
769         return d;
770     }
771         
772 
773 }