1
2
3
4
5
6
7
8
9
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
130 _jaretDateFormatter = jaretDateFormatter;
131
132
133
134
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, >0 for this>date, <0 for this<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, >0 for this>date, <0 for this<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, >0 for this>date, <0 for this<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 }