KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jodd > datetime > JDateTime


1 // Copyright (c) 2003-2007, Jodd Team (jodd.sf.net). All Rights Reserved.
2

3 package jodd.datetime;
4
5 import java.util.Calendar JavaDoc;
6 import java.util.TimeZone JavaDoc;
7 import java.util.Locale JavaDoc;
8
9 import jodd.datetime.converter.*;
10 import jodd.datetime.formatter.DefaultFormatter;
11 import jodd.datetime.formatter.JdtFormatter;
12 import jodd.util.ObjectUtil;
13 import jodd.util.HashCodeUtil;
14
15 /**
16  * Universal all-in-one date and time class that uses Astronomical Julian
17  * Dates for time calculations. Guaranteed precision for all manipulations
18  * and calculations is up to 1 ms (0.001 sec).
19  *
20  * <p>
21  * The Julian day or Julian day number (JDN) is the (integer) number of days that
22  * have elapsed since Monday, January 1, 4713 BC in the proleptic Julian calendar 1.
23  * That day is counted as Julian day zero. Thus the multiples of 7 are Mondays.
24  * Negative values can also be used.
25  *
26  * <p>
27  * The Julian Date (JD) is the number of days (with decimal fraction of the day) that
28  * have elapsed since 12 noon Greenwich Mean Time (UT or TT) of that day.
29  * Rounding to the nearest integer gives the Julian day number.
30  *
31  * <p>
32  * <code>JDateTime</code> contains date/time information for current day. By
33  * default, behavior and formats are set to ISO standard, although this may
34  * be changed.
35  *
36  * <p>
37  * <code>JDateTime</code> can be set in many different ways by using <code>setXxx()</code>
38  * methods or equivalent constructors. Moreover, date time information may be loaded from an instance
39  * of any available java date-time class. This functionality can be easily
40  * enhanced for any custom date/time class. Furthermore, <code>JDateTime</code>
41  * can be converted to any such date/time class.
42  *
43  * <p>
44  * Rolling dates with <code>JDateTime</code> is easy. For this
45  * <code>JDateTime</code> contains many <code>addXxx()</code> methods. Time can be added
46  * or subtracted with any value or more values at once. All combinations are
47  * valid. Calculations also performs month fixes by default.
48  *
49  * <p>
50  * <code>JDateTime</code> behavior is set by several attributes (or
51  * parameters). Each one contains 2 values: one is the default value, used by
52  * all instances of <code>JDateTime</code> and the other one is just for a
53  * specific instance of <code>JDateTime</code>. This means that it is
54  * possible to set behavior of all instances at once or of one particular
55  * instance.
56  *
57  * <p>
58  * Bellow is the list of behavior attributes:
59  *
60  * <ul>
61  *
62  * <li>monthFix - since months do not have the same number of days, adding
63  * months and years may be calculated in two different ways: with or
64  * without month fix. when month fix is on, <code>JDateTime</code> will
65  * additionally fix all time adding and fix the date. For example, adding
66  * one month to 2003-01-31 will give 2003-02-28 and not 2003-03-03.
67  * By default, monthFix is turned on and set to <code>true</code>.
68  * </li>
69  *
70  * <li>locale - current locale, used for getting names during formating the
71  * output string.
72  * </li>
73  *
74  * <li>timezone - current timezone</li>
75  *
76  * <li>format - is String that describes how time is converted and parsed to
77  * and from a String. Default format matches ISO standard. An instance of
78  * <code>JdtFormatter</code> parses and uses this template.</li>
79  *
80  * <li>week definition - is used for specifying the definition of the week.
81  * Week is defined with first day of the week and with the must have day. A
82  * must have day is a day that must exist in the 1st week of the year. For
83  * example, default value is Thursday (4) as specified by ISO standard.
84  * Alternatively, instead of must have day, minimal days of week may be used,
85  * since this two numbers are in relation.
86  * </li>
87  *
88  * </ul>
89  *
90  * Optimization: although based on heavy calculations, <code>JDateTime</code>
91  * works significantly faster then java's <code>Calendar</code>s. Since
92  * <code>JDateTime</code> doesn't use lazy initialization, setXxx() method is
93  * slower. However, this doesn't have much effect to the global performances:
94  * settings are usually not used without gettings:) As soon as any other method is
95  * used (getXxx() or addXxx()) performances of <code>JDateTime</code> becomes
96  * significantly better.
97  *
98  * <p>
99  * Year 1582 is (almost:) working: after 1582-10-04 (Thursday) is 1582-10-15 (Friday).
100  * Users must be aware of this when doing time rolling before across this period.
101  *
102  * <p>
103  * More info: <a HREF="http://en.wikipedia.org/wiki/Julian_Date">Julian Date on Wikipedia</a>
104  */

105 public class JDateTime implements Comparable JavaDoc, Cloneable JavaDoc {
106
107     /**
108      * {@link DateTimeStamp} for current date.
109      */

110     protected DateTimeStamp time = new DateTimeStamp();
111
112     /**
113      * Day of week, range: [1-7] == [Monday - Sunday]
114      */

115     protected int dayofweek;
116
117     /**
118      * Day of year, range: [1-365] or [1-366]
119      */

120     protected int dayofyear;
121
122     /**
123      * Leap year flag.
124      */

125     protected boolean leap;
126
127     /**
128      * Week of year, range: [1-52] or [1-53]
129      */

130     protected int weekofyear;
131
132     /**
133      * Week of month.
134      */

135     protected int weekofmonth;
136
137     /**
138      * Current Julian Date.
139      */

140     protected JulianDateStamp jdate;
141
142
143     // ---------------------------------------------------------------- misc precalculated times
144

145     /**
146      * Julian Date for 1970-01-01T00:00:00 (Thursday).
147      */

148     public static final JulianDateStamp JD_1970 = new JulianDateStamp(2440587.5);
149
150     /**
151      * Julian Date for 2001-01-01T00:00:00 (Monday).
152      */

153     public static final JulianDateStamp JD_2001 = new JulianDateStamp(2451910.5);
154
155     /**
156      * The Modified Julian Day (MJD) is the number of days (with decimal fraction of the day)
157      * that have elapsed since midnight at the beginning of Wednesday November 17, 1858.
158      */

159     public static final JulianDateStamp JD_MJD = new JulianDateStamp(2400000.5);
160
161     /**
162      * The Reduced Julian Day (RJD) is also used by astronomers and counts days
163      * from the same day as MJD, but from noon.
164      */

165     public static final JulianDateStamp JD_RJD = new JulianDateStamp(2400000);
166
167     /**
168      * The Truncated Julian Day (TJD) was introduced by NASA for the space program.
169      * TJD began at midnight at the beginning of May 24, 1968 (Friday).
170      */

171     public static final JulianDateStamp JD_TJD = new JulianDateStamp(2440000.5);
172     
173
174
175     // ---------------------------------------------------------------- julian date (CORE)
176

177     /**
178      * Returns current {@link DateTimeStamp}.
179      * Returned instance is still used internally (i.e. it is not clonned before returning).
180      */

181     public DateTimeStamp getDateTimeStamp() {
182         return time;
183     }
184
185     /**
186      * Loads current date time information.
187      */

188     public void setDateTimeStamp(DateTimeStamp dts) {
189         set(dts.year, dts.month, dts.day, dts.hour, dts.minute, dts.second);
190     }
191
192     /**
193      * Sets current Julian Date. This is the core of the JDateTime class and it
194      * is used by all other classes. This method performs all calculations
195      * required for whole class.
196      *
197      * @param jds current julian date
198      */

199     public void setJulianDate(JulianDateStamp jds) {
200         setJdOnly((JulianDateStamp) jds.clone());
201         setParams();
202     }
203
204     /**
205      * Returns {@link JulianDateStamp}. It is the same instance used internally.
206      */

207     public JulianDateStamp getJulianDate() {
208         return jdate;
209     }
210
211     /**
212      * Internal method for setting various parameters other then date/time.
213      */

214     private void setParams() {
215         this.leap = TimeUtil.isLeapYear(time.year);
216         this.dayofweek = calcDayOfWeek();
217         this.dayofyear = calcDayOfYear();
218         this.weekofyear = calcWeekOfYear(getFirstDayOfWeek() ,getMustHaveDayOfFirstWeek());
219         this.weekofmonth = weekNumber(time.day, this.dayofweek);
220     }
221
222     /**
223      * Internal method that just sets the time stamp and not all other additional
224      * parameters. Used for faster calculations only and only by main core
225      * set/add methods.
226      *
227      * @param jds julian date
228      */

229     private void setJdOnly(JulianDateStamp jds) {
230         jdate = jds;
231         time = TimeUtil.fromJulianDate(jds);
232     }
233
234     /**
235      * Core method that sets date and time. All others set() methods use this
236      * one. Milliseconds are truncated after 3rd digit.
237      *
238      * @param year year to set
239      * @param month month to set
240      * @param day day to set
241      * @param hour hour to set
242      * @param minute minute to set
243      * @param second second to set
244      */

245     public void set(int year, int month, int day, int hour, int minute, double second) {
246
247         // fix seconds fractions because of float point arithmetics
248
//second = ((int) second) + ((int) ((second - (int)second) * 1000 + 1e-9) / 1000.0);
249
double ms = (second - (int)second) * 1000;
250         if (ms > 999) {
251             ms = 999;
252         } else {
253             ms += 1e-9;
254         }
255         second = ((int) second) + ((int) ms / 1000.0);
256         jdate = TimeUtil.toJulianDate(year, month, day, hour, minute, second);
257
258         // if given time is valid it means that there is no need to calculate it
259
// again from already calculated julian date. however, it is still
260
// necessary to fix milliseconds to match the value that would be
261
// calculated as setJulianDate() is used. This fix only deals with the
262
// time, not doing the complete and more extensive date calculation.
263
// this means that method works faster when regular date is specified.
264
if (TimeUtil.isValidDateTime(year, month, day, hour, minute, second)) {
265
266             int ka = (int)(jdate.fraction + 0.5);
267             double frac = jdate.fraction + 0.5 - ka + 1e-10;
268
269             // hour with minute and second included as fraction
270
double d_hour = frac * 24.0;
271
272             // minute with second included as a fraction
273
double d_minute = (d_hour - (int)d_hour) * 60.0;
274
275             second = (d_minute - (int)d_minute) * 60.0;
276
277             // fix calculation errors
278
second = ((int) (second * 10000) + 0.5) / 10000.0;
279
280             time.year = year; time.month = month; time.day = day;
281             time.hour = hour; time.minute = minute; time.second = second;
282             setParams();
283         } else {
284             setJulianDate(jdate);
285         }
286     }
287
288     /**
289      * Sets just Julian Date and no other parameter such as day of week etc.
290      * Used internally for speed.
291      *
292      * @param year year to set
293      * @param month month to set
294      * @param day day to set
295      * @param hour hour to set
296      * @param minute minute to set
297      * @param second second to set
298      */

299     private void setJdOnly(int year, int month, int day, int hour, int minute, double second) {
300         setJdOnly(TimeUtil.toJulianDate(year, month, day, hour, minute, second));
301     }
302
303
304     // ---------------------------------------------------------------- core calculations
305

306     /**
307      * Calculates day of week.
308      */

309     private int calcDayOfWeek() {
310         int jd = (int)(jdate.doubleValue() + 0.5);
311         return (jd % 7) + 1;
312         //return (jd + 1) % 7; // return 0 (Sunday), 1 (Monday),...
313
}
314
315     private static final int NUM_DAYS[] = {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; // 1-based
316
private static final int LEAP_NUM_DAYS[] = {-1, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}; // 1-based
317

318     /**
319      * Calculates day of year.
320      */

321     private int calcDayOfYear() {
322         if (leap == true) {
323             return LEAP_NUM_DAYS[time.month] + time.day;
324         }
325         return NUM_DAYS[time.month] + time.day;
326     }
327
328
329     /**
330      * Calculates week of year. Based on:
331      * "Algorithm for Converting Gregorian Dates to ISO 8601 Week Date"
332      * by Rick McCarty, 1999
333      *
334      * @param start first day of week
335      * @param must must have day of week
336      *
337      * @return week of year number
338      */

339     private int calcWeekOfYear(int start, int must) {
340
341         // is modification required?
342
// modification is a fix for the days of year because of the different
343
// starting day of week. when modification is required, one week is added
344
// or subtracted to the current day, so calculation of the week of year
345
// would be correct.
346
int delta = 0;
347         if (start <= this.dayofweek) {
348             if (must < start) {
349                 delta = 7;
350             }
351         } else {
352             if (must >= start) {
353                 delta = -7;
354             }
355         }
356
357         int jd = (int)(jdate.doubleValue() + 0.5) + delta;
358         int WeekDay = (jd % 7) + 1;
359
360         int time_year = time.year;
361         int DayOfYearNumber = this.dayofyear + delta;
362         if (DayOfYearNumber < 1) {
363             time_year--;
364             DayOfYearNumber = TimeUtil.isLeapYear(time_year) ? 366 + DayOfYearNumber: 365 + DayOfYearNumber;
365         } else if (DayOfYearNumber > (this.leap ? 366 : 365)) {
366             DayOfYearNumber = this.leap ? DayOfYearNumber - 366: DayOfYearNumber - 365;
367             time_year++;
368         }
369
370         // modification, if required, is finished. proceed to the calculation.
371

372         int firstDay = jd - DayOfYearNumber + 1;
373         int Jan1WeekDay = (firstDay % 7) + 1;
374
375         // find if the date falls in YearNumber Y - 1 set WeekNumber to 52 or 53
376
int YearNumber = time_year;
377         int WeekNumber = 52;
378         if ((DayOfYearNumber <= (8 - Jan1WeekDay)) && (Jan1WeekDay > must)) {
379             YearNumber--;
380             if ((Jan1WeekDay == must + 1) || ( (Jan1WeekDay == must + 2) && (TimeUtil.isLeapYear(YearNumber)) ) ) {
381                 WeekNumber = 53;
382             }
383         }
384
385         // set WeekNumber to 1 to 53 if date falls in YearNumber
386
int m = 365;
387         if (YearNumber == time_year) {
388             if (TimeUtil.isLeapYear(time_year) == true) {
389                 m = 366;
390             }
391             if ((m - DayOfYearNumber) < (must - WeekDay)) {
392                 YearNumber = time_year + 1;
393                 WeekNumber = 1;
394             }
395         }
396
397         if (YearNumber == time_year) {
398             int n = DayOfYearNumber + (7 - WeekDay) + (Jan1WeekDay - 1);
399             WeekNumber = n / 7;
400             if (Jan1WeekDay > must) {
401                 WeekNumber -= 1;
402             }
403         }
404         return WeekNumber;
405     }
406
407     /**
408      * Return the week number of a day, within a period. This may be the week number in
409      * a year, or the week number in a month. Usually this will be a value >= 1, but if
410      * some initial days of the period are excluded from week 1, because
411      * minimalDaysInFirstWeek is > 1, then the week number will be zero for those
412      * initial days. Requires the day of week for the given date in order to determine
413      * the day of week of the first day of the period.
414      *
415      * @param dayOfPeriod
416      * Day-of-year or day-of-month. Should be 1 for first day of period.
417      * @param dayOfWeek
418      *
419      * @return Week number, one-based, or zero if the day falls in part of the
420      * month before the first week, when there are days before the first
421      * week because the minimum days in the first week is more than one.
422      */

423     private int weekNumber(int dayOfPeriod, int dayOfWeek) {
424         // Determine the day of the week of the first day of the period
425
// in question (either a year or a month). Zero represents the
426
// first day of the week on this calendar.
427
int periodStartDayOfWeek = (dayOfWeek - getFirstDayOfWeek() - dayOfPeriod + 1) % 7;
428         if (periodStartDayOfWeek < 0) {
429             periodStartDayOfWeek += 7;
430         }
431
432         // Compute the week number. Initially, ignore the first week, which
433
// may be fractional (or may not be). We add periodStartDayOfWeek in
434
// order to fill out the first week, if it is fractional.
435
int weekNo = (dayOfPeriod + periodStartDayOfWeek - 1) / 7;
436
437         // If the first week is long enough, then count it. If
438
// the minimal days in the first week is one, or if the period start
439
// is zero, we always increment weekNo.
440
if ((7 - periodStartDayOfWeek) >= getMinDaysInFirstWeek()) {
441             ++weekNo;
442         }
443
444         return weekNo;
445     }
446
447     // ---------------------------------------------------------------- add time
448

449     /**
450      * Adds time to current time. The main add method. All other add() methods
451      * must use this one. <p>
452      *
453      * There are 2 different kind of addings, when months are added:
454      * <ul>
455      * <li>when months are not specially concern, and month is aproximated as 31
456      * days. example: 2003-01-31 + 0-01-0 = 2003-03-03</li>
457      * <li>when months addition is fixed, and month is not approximated.
458      * example: 2003-01-31 + 0-01-0 = 2003-28-02</li>
459      * </ul>
460      * <p>
461      *
462      * @param year delta year
463      * @param month delta month
464      * @param day delta days
465      * @param hour delta hours
466      * @param minute delta minutes
467      * @param second delta seconds
468      * @param monthFix <code>true</code> for month fixing, <code>false</code> otherwise
469      */

470
471     public void add(int year, int month, int day, int hour, int minute, double second, boolean monthFix) {
472         second += time.second;
473         minute += time.minute;
474         hour += time.hour;
475         day += time.day;
476         if (monthFix == false) {
477             month += time.month;
478             year += time.year;
479             set(year, month, day, hour, minute, second);
480         } else {
481             // month fix:
482
// 1. add all except month and year
483
// 2. store day value
484
// 3. add just months
485
// 4. if new date is not equal to stored, return to last day of previous month
486
setJdOnly(time.year, time.month, day, hour, minute, second);
487             int from = time.day;
488             month += time.month + (year * 12); // delta years to add are converted to delta months
489
setJdOnly(time.year, month, time.day, time.hour, time.minute, time.second);
490             if (time.day < from) {
491                 set(time.year, time.month, 0, time.hour, time.minute, time.second);
492             } else {
493                 setParams();
494             }
495
496             /*
497             // 5. store month value
498             // 6. add just year
499             // 7. if new month is not equal to stored, return to last day of previous month
500             from = time.month;
501             year += time.year;
502             setJdOnly(year, time.month, time.day, time.hour, time.minute, time.second);
503             if (time.month > from) {
504                 set(time.year, time.month, 0, time.hour, time.minute, time.second);
505             }*/

506         }
507     }
508
509
510     /**
511      * Performs time adding with preset value of monthFix attribute.
512      *
513      * @param year delta year
514      * @param month delta month
515      * @param day delta days
516      * @param hour delta hours
517      * @param minute delta minutes
518      * @param second delta seconds
519      *
520      * @see #add(int, int, int, int, int, double, boolean)
521      */

522     public void add(int year, int month, int day, int hour, int minute, double second) {
523         add(year, month, day, hour, minute, second, getMonthFix());
524     }
525
526
527     /**
528      * Adds date, leaving time unchanged.
529      *
530      * @param year years to add
531      * @param month months to add
532      * @param day days to add
533      * @param monthFix <code>true</code> for month fixing, <code>false</code> otherwise
534      *
535      * @see #add(int, int, int, int, int, double, boolean)
536      */

537     public void add(int year, int month, int day, boolean monthFix) {
538         add(year, month, day, 0, 0, 0, monthFix);
539     }
540     /**
541      * Adds date, leaving time unchanged, with preset value of monthFix.
542      * attribute.
543      *
544      * @param year years to add
545      * @param month months to add
546      * @param day days to add
547      *
548      * @see #add(int, int, int, boolean)
549      */

550     public void add(int year, int month, int day) {
551         add(year, month, day, getMonthFix());
552     }
553
554
555     /**
556      * Adds time.
557      *
558      * @param hour hours to add
559      * @param minute minutes to add
560      * @param second seconds to add
561      * @param monthFix <code>true</code> for month fixing, <code>false</code> otherwise
562      *
563      * @see #add(int, int, int, int, int, double)
564      */

565     public void addTime(int hour, int minute, double second, boolean monthFix) {
566         add(0, 0, 0, hour, minute, second, monthFix);
567     }
568     /**
569      * Adds time, with preset value of monthFix.
570      *
571      * @param hour hours to add
572      * @param minute minutes to add
573      * @param second seconds to add
574      *
575      * @see #addTime(int, int, double, boolean)
576      */

577     public void addTime(int hour, int minute, double second) {
578         addTime(hour, minute, second, getMonthFix());
579     }
580
581
582     /**
583      * Adds year.
584      *
585      * @param y year to add
586      * @param monthFix <code>true</code> for month fixing, <code>false</code> otherwise
587      */

588     public void addYear(int y, boolean monthFix) {
589         add(y, 0, 0, monthFix);
590     }
591     /**
592      * Adds year, with preset value of monthFix.
593      *
594      * @param y year to add
595      */

596     public void addYear(int y) {
597         addYear(y, getMonthFix());
598     }
599
600
601     /**
602      * Adds month.
603      *
604      * @param m month to add
605      * @param monthFix <code>true</code> for month fixing, <code>false</code> otherwise
606      */

607     public void addMonth(int m, boolean monthFix) {
608         add(0, m, 0, monthFix);
609     }
610     /**
611      * Adds month, with preset value of monthFix.
612      *
613      * @param m month to add
614      */

615     public void addMonth(int m) {
616         addMonth(m, getMonthFix());
617     }
618
619     /**
620      * Adds days.
621      *
622      * @param d days to add
623      * @param monthFix <code>true</code> for month fixing, <code>false</code> otherwise
624      */

625     public void addDay(int d, boolean monthFix) {
626         add(0, 0, d, monthFix);
627     }
628     /**
629      * Adds days, with preset value of monthFix.
630      *
631      * @param d days to add
632      */

633     public void addDay(int d) {
634         addDay(d, getMonthFix());
635     }
636
637     /**
638      * Adds hours.
639      *
640      * @param h hours to add
641      * @param monthFix <code>true</code> for month fixing, <code>false</code> otherwise
642      */

643     public void addHour(int h, boolean monthFix) {
644         addTime(h, 0, 0, monthFix);
645     }
646     /**
647      * Adds hours, with preset value of monthFix.
648      *
649      * @param h hours to add
650      */

651     public void addHour(int h) {
652         addHour(h, getMonthFix());
653     }
654
655
656     /**
657      * Adds minutes.
658      *
659      * @param m minutes to add.
660      * @param monthFix <code>true</code> for month fixing, <code>false</code> otherwise
661      */

662     public void addMinute(int m, boolean monthFix) {
663         addTime(0, m, 0, monthFix);
664     }
665     /**
666      * Adds minutes, with preset value of monthFix.
667      *
668      * @param m minutes to add.
669      */

670     public void addMinute(int m) {
671         addMinute(m, getMonthFix());
672     }
673
674     /**
675      * Adds seconds.
676      *
677      * @param s seconds to add
678      * @param monthFix <code>true</code> for month fixing, <code>false</code> otherwise
679      */

680     public void addSecond(double s, boolean monthFix) {
681         addTime(0, 0, s, monthFix);
682     }
683     /**
684      * Adds seconds, with preset value of monthFix.
685      *
686      * @param s seconds to add
687      */

688     public void addSecond(double s) {
689         addSecond(s, getMonthFix());
690     }
691
692
693     /**
694      * Adds milliseconds.
695      *
696      * @param ms miliseconds to add
697      * @param monthFix <code>true</code> for month fixing, <code>false</code> otherwise
698      */

699     public void addMillisecond(int ms, boolean monthFix) {
700         addTime(0, 0, ms / 1000.0, monthFix);
701     }
702     /**
703      * Adds milliseconds, with preset value of monthFix.
704      *
705      * @param ms miliseconds to add
706      */

707     public void addMillisecond(int ms) {
708         addMillisecond(ms, getMonthFix());
709     }
710
711     // ---------------------------------------------------------------- ctors & sets
712

713     /**
714      * Constructor that set date and time.
715      *
716      * @param year year to set
717      * @param month month to set
718      * @param day day to set
719      * @param hour hours to set
720      * @param minute minutes to set
721      * @param second seconds to set
722      *
723      * @see #set(int, int, int, int, int, double)
724      */

725     public JDateTime(int year, int month, int day, int hour, int minute, double second) {
726         this.set(year, month, day, hour, minute, second);
727     }
728
729     /**
730      * Sets date, time is set to midnight (00:00:00.000).
731      *
732      * @param year year to set
733      * @param month month to set
734      * @param day day to set
735      */

736     public void set(int year, int month, int day) {
737         set(year, month, day, 0, 0, 0);
738     }
739
740     /**
741      * Constructor that sets just date. Time is set to 00:00:00.
742      *
743      * @param year year to set
744      * @param month month to set
745      * @param day day to set
746      *
747      * @see #set(int, int, int)
748      */

749     public JDateTime(int year, int month, int day) {
750         this.set(year, month, day);
751     }
752
753     /**
754      * Sets time, date is unchanged.
755      *
756      * @param hour hours to set
757      * @param minute minutes to set
758      * @param second secnds to set
759      */

760     public void setTime(int hour, int minute, double second) {
761         set(time.year, time.month, time.day, hour, minute, second);
762     }
763
764     /**
765      * Sets date, time remains unchanged.
766      *
767      * @param year year
768      * @param month month
769      * @param day day
770      */

771     public void setDate(int year, int month, int day) {
772         set(year, month, day, time.hour, time.minute, time.second);
773     }
774
775
776     // ---------------------------------------------------------------- milliseconds
777

778     /**
779      * Constructor that sets current time specified as time in milliseconds, from
780      * the midnight, January 1, 1970 UTC.
781      *
782      * @param milis time in milliseconds, from the midnight, January 1, 1970 UTC
783      *
784      * @see #setTimeInMillis(long )
785      */

786     public JDateTime(long milis) {
787         setTimeInMillis(milis);
788     }
789
790     /**
791      * Sets the time based on current time in milliseconds. Current time is
792      * calculated from the midnight, January 1, 1970 UTC.
793      * <p>
794      * Calculation is divided in two steps, due to precission issues.
795      *
796      * @param millis time in milliseconds, from the midnight, January 1, 1970 UTC
797      */

798     public void setTimeInMillis(long millis) {
799         millis += getTimeZone().getOffset(millis);
800         JulianDateStamp now = new JulianDateStamp();
801         now.integer = (int) (millis / TimeUtil.MILLIS_IN_DAY);
802         now.fraction = (double)(millis % TimeUtil.MILLIS_IN_DAY) / TimeUtil.MILLIS_IN_DAY;
803         now.integer += JD_1970.integer;
804         now.fraction += JD_1970.fraction;
805         if (now.fraction >= 1.0) {
806             now.integer++;
807             now.fraction -= 1.0;
808         }
809         setJulianDate(now);
810     }
811
812     /**
813      * Returns time based on current time in milliseconds. Current time is
814      * calculated from the midnight, January 1, 1970 UTC.
815      * <p>
816      * Due to popssible huge values calculation is divided in two steps:
817      * first for fractionals difference, and thene for integer parts.
818      *
819      * @return milis time in milliseconds, from the midnight, January 1, 1970 UTC
820      */

821     public long getTimeInMillis() {
822         double then = (jdate.fraction - JD_1970.fraction) * TimeUtil.MILLIS_IN_DAY;
823         then += (jdate.integer - JD_1970.integer) * TimeUtil.MILLIS_IN_DAY;
824         then += then > 0 ? 1.0e-6 : -1.0e-6;
825         then -= getTimeZone().getOffset((long) then);
826         return (long) then;
827     }
828
829
830     // ---------------------------------------------------------------- date/time sets
831

832     /**
833      * Sets current year.
834      *
835      * @param y year to set
836      */

837     public void setYear(int y) {
838         setDate(y, time.month, time.day);
839     }
840
841     /**
842      * Sets current month.
843      *
844      * @param m month to set
845      */

846     public void setMonth(int m) {
847         setDate(time.year, m, time.day);
848     }
849
850     /**
851      * Sets current day.
852      *
853      * @param d day to set
854      */

855     public void setDay(int d) {
856         setDate(time.year, time.month, d);
857     }
858
859     /**
860      * Set current hour.
861      *
862      * @param h hour to set
863      */

864     public void setHour(int h) {
865         setTime(h, time.minute, time.second);
866     }
867
868     /**
869      * Set current minute.
870      *
871      * @param m minutes to set
872      */

873     public void setMinute(int m) {
874         setTime(time.hour, m, time.second);
875
876     }
877
878     /**
879      * Sets current second and millisecond.
880      *
881      * @param s seconds and milliseconds to set
882      */

883     public void setSecond(double s) {
884         setTime(time.hour, time.minute, s);
885     }
886
887     /**
888      * Sets current second.
889      *
890      * @param s seconds to set
891      */

892     public void setSecond(int s) {
893         double milis = s + (time.second - (int)time.second);
894         setTime(time.hour, time.minute, milis);
895     }
896
897     /**
898      * Sets current millisecond.
899      *
900      * @param m milliseconds to set
901      */

902     public void setMillisecond(int m) {
903         setTime(time.hour, time.minute, ((int)time.second) + m/1000.0);
904     }
905
906
907     // ---------------------------------------------------------------- date/time gets
908

909
910     /**
911      * Returns current year.
912      */

913     public int getYear() {
914         return time.year;
915     }
916
917     /**
918      * Returns current month.
919      */

920     public int getMonth() {
921         return time.month;
922     }
923
924     /**
925      * Returns current day of month.
926      * @see #getDayOfMonth
927      */

928     public int getDay() {
929         return time.day;
930     }
931
932     /**
933      * Returns current day of month.
934      * @see #getDay
935      */

936     public int getDayOfMonth() {
937         return time.day;
938     }
939
940     /**
941      * Returns current hour.
942      */

943     public int getHour() {
944         return time.hour;
945     }
946
947     /**
948      * Returns current minutes.
949      */

950     public int getMinute() {
951         return time.minute;
952     }
953
954     /**
955      * Return current secodns. For an integer value, just cast the returned
956      * value.
957      */

958     public double getSecond() {
959         return time.second;
960     }
961
962     /**
963      * Returns current milliseconds.
964      */

965     public int getMillisecond() {
966         return (int) ((time.second - (int)time.second) * 1000 + 1e-9);
967     }
968
969     // ---------------------------------------------------------------- other gets
970

971     /**
972      * Returns current day of week.
973      */

974     public int getDayOfWeek() {
975         return dayofweek;
976     }
977
978     /**
979      * Returns current day of year.
980      */

981     public int getDayOfYear() {
982         return dayofyear;
983     }
984
985     /**
986      * Returns <code>true</code> if current year is leap year.
987      */

988     public boolean isLeapYear() {
989         return leap;
990     }
991
992     /**
993      * Returns current week of year.
994      */

995     public int getWeekOfYear() {
996         return weekofyear;
997     }
998
999     /**
1000     * Returns current week of month.
1001     */

1002    public int getWeekOfMonth() {
1003        return weekofmonth;
1004    }
1005
1006
1007    /**
1008     * Length of months. Do not use directly!!!
1009     */

1010    private static final int MONTH_LENGTH[] = {0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1011
1012    /**
1013     * Returns the length of the specified month in days.
1014     */

1015    public int getMonthLength(int m) {
1016        if ((m < 1) || (m > 12)) {
1017            throw new IllegalArgumentException JavaDoc("Invalid month index: '" + m + "'.");
1018        }
1019        if (m == 2) {
1020            return this.leap ? 29 : 28;
1021        }
1022        if ((time.year == 1582) && (time.month == 10)) {
1023            return 21;
1024        }
1025        return MONTH_LENGTH[m];
1026    }
1027
1028    /**
1029     * Returns the length of the current month in days.
1030     */

1031    public int getMonthLength() {
1032        return getMonthLength(time.month);
1033    }
1034
1035    // ---------------------------------------------------------------- current date time
1036

1037    /**
1038     * Sets current local date and time.
1039     */

1040    public void setCurrentTime() {
1041        setTimeInMillis(System.currentTimeMillis());
1042    }
1043
1044    /**
1045     * Constructor that sets current local date and time.
1046     */

1047    public JDateTime() {
1048        this.setCurrentTime();
1049    }
1050
1051    // ---------------------------------------------------------------- conversion (general)
1052

1053    /**
1054     * Loads date time <b>from</b> an object using a converter registered in {@link JdtConverterManager}.
1055     * @see jodd.datetime.converter.JdtConverter#loadFrom(JDateTime, Object)
1056     */

1057    public void loadFrom(Object JavaDoc source) {
1058        JdtConverter converter = JdtConverterManager.lookup(source.getClass());
1059        if (converter == null) {
1060            throw new IllegalArgumentException JavaDoc("JdtConverter for '" + source.getClass() + "' type not registered.");
1061        }
1062        converter.loadFrom(this, source);
1063    }
1064
1065    /**
1066     * Converts date time <b>to</b> an another type.
1067     * All default converters have direct method for easier usage.
1068     * @see jodd.datetime.converter.JdtConverter#convertTo(JDateTime)
1069     */

1070    public Object JavaDoc convertTo(Class JavaDoc type) {
1071        JdtConverter converter = JdtConverterManager.lookup(type);
1072        if (converter == null) {
1073            throw new IllegalArgumentException JavaDoc("JdtConverter for '" + type + "' type not registered.");
1074        }
1075        return converter.convertTo(this);
1076    }
1077
1078
1079    /**
1080     * Stores date time <b>to</b> a destination instance.
1081     * @see jodd.datetime.converter.JdtConverter#storeTo(JDateTime, Object)
1082     */

1083    public void storeTo(Object JavaDoc destination) {
1084        JdtConverter converter = JdtConverterManager.lookup(destination.getClass());
1085        if (converter == null) {
1086            throw new IllegalArgumentException JavaDoc("JdtConverter for '" + destination.getClass() + "' type not registered.");
1087        }
1088        converter.storeTo(this, destination);
1089    }
1090
1091    // ---------------------------------------------------------------- conversions
1092

1093    /**
1094     * Converts to {@link Calendar} instance.
1095     * @see #convertTo(Class)
1096     */

1097    public java.util.Calendar JavaDoc convertToCalendar() {
1098        return (java.util.Calendar JavaDoc) convertTo(java.util.Calendar JavaDoc.class);
1099    }
1100
1101    /**
1102     * Converts to {@link java.util.Date} instance.
1103     * @see #convertTo(Class)
1104     */

1105    public java.util.Date JavaDoc convertToDate() {
1106        return (java.util.Date JavaDoc) convertTo(java.util.Date JavaDoc.class);
1107    }
1108
1109    /**
1110     * Converts to {@link java.util.GregorianCalendar} instance.
1111     * @see #convertTo(Class)
1112     */

1113    public java.util.GregorianCalendar JavaDoc convertToGregorianCalendar() {
1114        return (java.util.GregorianCalendar JavaDoc) convertTo(java.util.GregorianCalendar JavaDoc.class);
1115    }
1116
1117    /**
1118     * Converts to {@link java.sql.Date} instance.
1119     * @see #convertTo(Class)
1120     */

1121    public java.sql.Date JavaDoc convertToSqlDate() {
1122        return (java.sql.Date JavaDoc) convertTo(java.sql.Date JavaDoc.class);
1123    }
1124
1125    /**
1126     * Converts to {@link java.sql.Timestamp} instance.
1127     * @see #convertTo(Class)
1128     */

1129    public java.sql.Timestamp JavaDoc convertToSqlTimestamp() {
1130        return (java.sql.Timestamp JavaDoc) convertTo(java.sql.Timestamp JavaDoc.class);
1131    }
1132
1133    /**
1134     * Converts to {@link DateTimeStamp} instance.
1135     * @see #convertTo(Class)
1136     */

1137    public DateTimeStamp convertToDateTimeStamp() {
1138        return (DateTimeStamp) convertTo(DateTimeStamp.class);
1139    }
1140
1141
1142    // ---------------------------------------------------------------- ctors from conversions
1143

1144    /**
1145     * Contructs <code>JDateTime</code> from a objects.
1146     * @see #loadFrom(Object)
1147     */

1148    public JDateTime(Object JavaDoc o) {
1149        loadFrom(o);
1150    }
1151
1152    /**
1153     * Contructs <code>JDateTime</code> from <code>DateTimeStamp</code>.
1154     */

1155    public JDateTime(DateTimeStamp dts) {
1156        setDateTimeStamp(dts);
1157    }
1158
1159
1160    /**
1161     * Contructs <code>JDateTime</code> from <code>JulianDateStamp</code>.
1162     */

1163    public JDateTime(JulianDateStamp jds) {
1164        setJulianDate(jds);
1165    }
1166    // ---------------------------------------------------------------- monthFix
1167

1168    /**
1169     * Default month fix value.
1170     */

1171    public static boolean DEFAULT_MONTH_FIX = true;
1172    
1173    private Boolean JavaDoc monthFix = null;
1174
1175    /**
1176     * Sets custom month fix value.
1177     * Setting to <code>null</code> will reset value to {@link #DEFAULT_MONTH_FIX}.
1178     */

1179    public void setMonthFix(Boolean JavaDoc monthFix) {
1180        this.monthFix = monthFix;
1181    }
1182
1183    /**
1184     * Reset to global default values.
1185     */

1186    public void setDefaultMonthFix() {
1187        setMonthFix(null);
1188    }
1189
1190    /**
1191     * Returns currently <b>active</b> month fix value.
1192     * <b>IMPORTANT</b>: When no specific value is set, it returns {@link #DEFAULT_MONTH_FIX}.
1193     */

1194    public boolean getMonthFix() {
1195        return (monthFix != null ? monthFix.booleanValue() : DEFAULT_MONTH_FIX);
1196    }
1197
1198
1199    // ---------------------------------------------------------------- timezone
1200

1201    private TimeZone JavaDoc timezone = null;
1202
1203    /**
1204     * Set custom timezone. Current time is changed if time zone has been changed.
1205     * Setting to <code>null</code> will reset value to default time zone.
1206     */

1207    public void setTimeZone(TimeZone JavaDoc timezone) {
1208        long now = getTimeInMillis();
1209        int offsetBefore = getTimeZone().getOffset(now);
1210        this.timezone = timezone;
1211        int offsetAfter = getTimeZone().getOffset(now);
1212        if (offsetAfter != offsetBefore) {
1213            addMillisecond(offsetAfter - offsetBefore);
1214        }
1215    }
1216
1217    /**
1218     * Reset to global default values.
1219     */

1220    public void setDefaultTimeZone() {
1221        setTimeZone(null);
1222    }
1223
1224    /**
1225     * Return currently <b>active</b> time zone.
1226     * <b>IMPORTANT</b>: When no specific value set, it returns default timezone.
1227     */

1228    public TimeZone JavaDoc getTimeZone() {
1229        return (timezone != null ? timezone : TimeZone.getDefault());
1230    }
1231
1232
1233    // ---------------------------------------------------------------- locale
1234

1235    private Locale JavaDoc locale = null;
1236
1237    /**
1238     * Set custom locale.
1239     * Setting to <code>null</null> will reset value to default locale.
1240     */

1241    public void setLocale(Locale JavaDoc locale) {
1242        this.locale = locale;
1243    }
1244
1245    /**
1246     * Reset to global default values.
1247     */

1248    public void setDefaultLocale() {
1249        setLocale(null);
1250    }
1251
1252    /**
1253     * Return currently <b>active</b> locale.
1254     * <b>IMPORTANT</b>: When no specific value set, it returns default locale.
1255     */

1256    public Locale JavaDoc getLocale() {
1257        return (locale != null ? locale : Locale.getDefault());
1258    }
1259
1260    // ---------------------------------------------------------------- formats
1261

1262    /**
1263     * Default date time format.
1264     */

1265    public static String JavaDoc DEFAULT_FORMAT = "YYYY-MM-DD hh:mm:ss.mss";
1266
1267    private String JavaDoc format = null;
1268
1269    /**
1270     * Defines custom format.
1271     * Setting to <code>null</code> will reset value to {@link #DEFAULT_FORMAT}.
1272     */

1273    public void setFormat(String JavaDoc newFormat) {
1274        format = newFormat;
1275    }
1276
1277    /**
1278     * Reset to global default values.
1279     */

1280    public void setDefaultFormat() {
1281        setFormat(null);
1282    }
1283
1284    /**
1285     * Returns actual format.
1286     * <b>IMPORTANT</b>: When no specific format set, it returns {@link #DEFAULT_FORMAT}.
1287     */

1288    public String JavaDoc getFormat() {
1289        return (format != null ? format : DEFAULT_FORMAT);
1290    }
1291
1292
1293    // ---------------------------------------------------------------- formatter
1294

1295    /**
1296     * Default {@link JdtFormatter}.
1297     */

1298    public static JdtFormatter DEFAULT_JDTFORMATTER = new DefaultFormatter();
1299
1300    private JdtFormatter jdtFormatter = null;
1301
1302    /**
1303     * Defines custom formatter.
1304     * Setting to <code>null</code> will reset value to {@link #DEFAULT_JDTFORMATTER}.
1305     */

1306    public void setJdtFormatter(JdtFormatter jdtFormatter) {
1307        this.jdtFormatter = jdtFormatter;
1308    }
1309
1310    public void setDefaultJdtFormatter() {
1311        setJdtFormatter(null);
1312    }
1313
1314    /**
1315     * Returns actual {@link JdtFormatter}.
1316     * <b>IMPORTANT</b>: When no specific formatter set, it returns {@link #DEFAULT_JDTFORMATTER}.
1317     */

1318    public JdtFormatter getJdtFormatter() {
1319        return (jdtFormatter != null ? jdtFormatter : DEFAULT_JDTFORMATTER);
1320    }
1321
1322
1323    // ---------------------------------------------------------------- toString
1324

1325    /**
1326     * Returns string representation of date/time in specified format.
1327     * @param template format template
1328     */

1329    public String JavaDoc toString(String JavaDoc template) {
1330        return getJdtFormatter().convert(this, template);
1331    }
1332
1333    /**
1334     * Returns spring representation of current date/time in currently active format.
1335     * @see #getFormat()
1336     */

1337    public String JavaDoc toString() {
1338        return toString(getFormat());
1339    }
1340
1341
1342    /**
1343     * Sets date/time from a string given in provided template.
1344     * @param s string containing date time information
1345     * @param template format template
1346     */

1347    public void fromString(String JavaDoc s, String JavaDoc template) {
1348        DateTimeStamp dts = getJdtFormatter().parse(s, template);
1349        if (dts != null) {
1350            setDateTimeStamp(dts);
1351        }
1352    }
1353
1354    /**
1355     * Sets date/time from a string and currently active template.
1356     * @param s string containing date time information
1357     * @see #getFormat()
1358     */

1359    public void fromString(String JavaDoc s) {
1360        fromString(s, getFormat());
1361    }
1362
1363    /**
1364     * Checks if some string represents a valid date using actual template.
1365     *
1366     * @return <code>true</code> if date is valid, otherwise <code>false</code>
1367     */

1368    public boolean isValid(String JavaDoc s) {
1369        return isValid(s, getFormat());
1370    }
1371
1372    /**
1373     * Checks if some string represents a valid date using provided template.
1374     *
1375     * @return <code>true</code> if date is valid, otherwise <code>false</code>
1376     */

1377    public boolean isValid(String JavaDoc s, String JavaDoc template) {
1378        DateTimeStamp dtsOriginal = getJdtFormatter().parse(s, template);
1379        if (dtsOriginal == null) {
1380            return false;
1381        }
1382        return TimeUtil.isValidDateTime(dtsOriginal);
1383    }
1384
1385
1386    // ---------------------------------------------------------------- week definitions
1387

1388    /**
1389     * Default first day of the week value, in range [1-7].
1390     */

1391    public static int DEFAULT_FIRST_DAY_OF_WEEK = 1;
1392
1393    private int firstDayOfWeek = 0;
1394
1395    /**
1396     * Default day of the first week that will be in the week, in range [1-7].
1397     */

1398    public static int DEFAULT_MUST_HAVE_DAY_OF_FIRST_WEEK = 4;
1399
1400    private int mustHaveDayOfFirstWeek = 0;
1401
1402    /**
1403     * Defines week definitions. If provided parameter is <code>0</code>,
1404     * it resets value back to default.
1405     *
1406     * @param start first day in week, [1-7], 0 resets to default
1407     * @param must must have day of the 1st week, [1-7], 0 resets to default
1408     */

1409    public void setWeekDefinition(int start, int must) {
1410        if (start == 0) {
1411            firstDayOfWeek = 0;
1412        } else if ((start >= 1) && (start <= 7)) {
1413            firstDayOfWeek = start;
1414        }
1415        if (must == 0) {
1416            mustHaveDayOfFirstWeek = 0;
1417        } else if ((must >= 1) && (must <= 7)) {
1418            mustHaveDayOfFirstWeek = must;
1419            minDaysInFirstWeek = convertMin2Must(getFirstDayOfWeek(), must);
1420        }
1421    }
1422
1423    /**
1424     * Reset to global default values.
1425     */

1426    public void setDefaultWeekDefinition() {
1427        setWeekDefinition(0, 0);
1428    }
1429
1430    /**
1431     * Returns <b>actual</b> the first day of the week.
1432     */

1433    public int getFirstDayOfWeek() {
1434        return (firstDayOfWeek != 0 ? firstDayOfWeek : DEFAULT_FIRST_DAY_OF_WEEK);
1435    }
1436
1437    /**
1438     * Returns <b>actual</b> must have day of the 1st week.
1439     */

1440    public int getMustHaveDayOfFirstWeek() {
1441        return (mustHaveDayOfFirstWeek != 0 ? mustHaveDayOfFirstWeek : DEFAULT_MUST_HAVE_DAY_OF_FIRST_WEEK);
1442    }
1443
1444
1445    // ---------------------------------------------------------------- week definitions (alt)
1446

1447    /**
1448     * Default minimal days in first week, in range [1-7].
1449     */

1450    public static int DEFAULT_MIN_DAYS_IN_FIRST_WEEK = 4;
1451
1452    private int minDaysInFirstWeek = 0;
1453
1454    /**
1455     * Returns <b>actual</b> minimal number of days of the first week. It is
1456     * calculated from must have day of the first week.
1457     *
1458     * @return minimal number of days of the first week
1459     */

1460    public int getMinDaysInFirstWeek() {
1461        return (minDaysInFirstWeek != 0 ? minDaysInFirstWeek : DEFAULT_MIN_DAYS_IN_FIRST_WEEK);
1462    }
1463
1464    /**
1465     * Defines week alternatively.
1466     *
1467     * @param start first day in week
1468     * @param min minimal days of week
1469     */

1470
1471    public void setWeekDefinitionAlt(int start, int min) {
1472        if (start == 0) {
1473            firstDayOfWeek = 0;
1474        } if ((start >= 1) && (start <= 7)) {
1475            firstDayOfWeek = start;
1476        }
1477        if (min == 0) {
1478            mustHaveDayOfFirstWeek = 0;
1479            minDaysInFirstWeek = 0;
1480        } else if ((min >= 1) && (min <= 7)) {
1481            mustHaveDayOfFirstWeek = convertMin2Must(getFirstDayOfWeek(), min);
1482            minDaysInFirstWeek = min;
1483        }
1484    }
1485
1486    /**
1487     * Reset to global default values.
1488     */

1489    public void setDefaultWeekDefinitionAlt() {
1490        setWeekDefinitionAlt(0, 0);
1491    }
1492
1493    /**
1494     * Converts minimal day of week to must have day of week.
1495     * Method is symmetrical.
1496     *
1497     * @param start first day of week
1498     * @param min minimal day of week
1499     *
1500     * @return must have day of week
1501     */

1502    private static int convertMin2Must(int start, int min) {
1503        int must = 8 - min + (start - 1);
1504        if (must > 7) {
1505            must -= 7;
1506        }
1507        return must;
1508    }
1509
1510    // ---------------------------------------------------------------- equals & hashCode
1511

1512    Object JavaDoc[] state = new Object JavaDoc[] {
1513            jdate,
1514            locale,
1515            timezone,
1516            format,
1517            jdtFormatter,
1518    };
1519
1520    public boolean equals(Object JavaDoc object) {
1521        if (this == object) {
1522            return true;
1523        }
1524        if (ObjectUtil.equalsType(object, this) == false) {
1525            return false;
1526        }
1527        final JDateTime jdt = (JDateTime) object;
1528        return (this.monthFix == jdt.monthFix) &&
1529                (this.firstDayOfWeek == jdt.firstDayOfWeek) &&
1530                (this.mustHaveDayOfFirstWeek == jdt.mustHaveDayOfFirstWeek) &&
1531                ObjectUtil.equalsEx(state, jdt.state);
1532    }
1533
1534    public int hashCode() {
1535        int result = HashCodeUtil.SEED;
1536        result = HashCodeUtil.hash(result, state);
1537        result = HashCodeUtil.hash(result, monthFix);
1538        result = HashCodeUtil.hash(result, firstDayOfWeek);
1539        result = HashCodeUtil.hash(result, mustHaveDayOfFirstWeek);
1540        return result;
1541    }
1542
1543
1544    // ---------------------------------------------------------------- clone
1545

1546    public Object JavaDoc clone() {
1547        JDateTime jdt = new JDateTime(this.jdate);
1548        jdt.monthFix = this.monthFix;
1549        jdt.timezone = this.timezone;
1550        jdt.locale = this.locale;
1551        jdt.format = this.format;
1552        jdt.jdtFormatter = this.jdtFormatter;
1553        jdt.firstDayOfWeek = this.firstDayOfWeek;
1554        jdt.mustHaveDayOfFirstWeek = this.mustHaveDayOfFirstWeek;
1555        return jdt;
1556    }
1557
1558
1559    // ---------------------------------------------------------------- compare
1560

1561    /**
1562     * Compares current JDateTime object with another one, up to 1 millisecond.
1563     *
1564     * @param gt JDateTime to compare
1565     *
1566     * @return -1 if the current object is less than the argument, 0 if the argument is
1567     * equal, and 1 if the current object is greater than the argument
1568     */

1569    public int compareTo(Object JavaDoc gt) {
1570        return time.compareTo(((JDateTime)gt).getDateTimeStamp());
1571    }
1572
1573}
1574
Popular Tags