001    /*
002     * $Id: DateUtils.java,v 1.4 2005/10/10 18:02:45 rbair Exp $
003     *
004     * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005     * Santa Clara, California 95054, U.S.A. All rights reserved.
006     *
007     * This library is free software; you can redistribute it and/or
008     * modify it under the terms of the GNU Lesser General Public
009     * License as published by the Free Software Foundation; either
010     * version 2.1 of the License, or (at your option) any later version.
011     * 
012     * This library is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015     * Lesser General Public License for more details.
016     * 
017     * You should have received a copy of the GNU Lesser General Public
018     * License along with this library; if not, write to the Free Software
019     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020     */
021    package org.jdesktop.swingx.calendar;
022    
023    import java.util.Calendar;
024    import java.util.Date;
025    
026    /**
027     * @author Scott Violet
028     * @version  $Revision: 1.4 $
029     */
030    public class DateUtils {
031        private static Calendar CALENDAR = Calendar.getInstance();
032    
033        /**
034         * Returns the last millisecond of the specified date.
035         *
036         * @param date Date to calculate end of day from
037         * @return Last millisecond of <code>date</code>
038         */
039        public static Date endOfDay(Date date) {
040            Calendar calendar = CALENDAR;
041            synchronized(calendar) {
042                calendar.setTime(date);
043                calendar.set(Calendar.HOUR_OF_DAY, 23);
044                calendar.set(Calendar.MILLISECOND, 999);
045                calendar.set(Calendar.SECOND, 59);
046                calendar.set(Calendar.MINUTE, 59);
047                return calendar.getTime();
048            }
049        }
050    
051    
052        /**
053         * Returns a new Date with the hours, milliseconds, seconds and minutes
054         * set to 0.
055         *
056         * @param date Date used in calculating start of day
057         * @return Start of <code>date</code>
058         */
059        public static Date startOfDay(Date date) {
060            Calendar calendar = CALENDAR;
061            synchronized(calendar) {
062                calendar.setTime(date);
063                calendar.set(Calendar.HOUR_OF_DAY, 0);
064                calendar.set(Calendar.MILLISECOND, 0);
065                calendar.set(Calendar.SECOND, 0);
066                calendar.set(Calendar.MINUTE, 0);
067                return calendar.getTime();
068            }
069        }
070    
071         /**
072         * Returns day in millis with the hours, milliseconds, seconds and minutes
073         * set to 0.
074         *
075         * @param date long used in calculating start of day
076         * @return Start of <code>date</code>
077         */
078        public static long startOfDayInMillis(long date) {
079            Calendar calendar = CALENDAR;
080            synchronized(calendar) {
081                calendar.setTimeInMillis(date);
082                calendar.set(Calendar.HOUR_OF_DAY, 0);
083                calendar.set(Calendar.MILLISECOND, 0);
084                calendar.set(Calendar.SECOND, 0);
085                calendar.set(Calendar.MINUTE, 0);
086                return calendar.getTimeInMillis();
087            }
088        }
089    
090        /**
091         * Returns the last millisecond of the specified date.
092         *
093         * @param date long to calculate end of day from
094         * @return Last millisecond of <code>date</code>
095         */
096        public static long endOfDayInMillis(long date) {
097            Calendar calendar = CALENDAR;
098            synchronized(calendar) {
099                calendar.setTimeInMillis(date);
100                calendar.set(Calendar.HOUR_OF_DAY, 23);
101                calendar.set(Calendar.MILLISECOND, 999);
102                calendar.set(Calendar.SECOND, 59);
103                calendar.set(Calendar.MINUTE, 59);
104                return calendar.getTimeInMillis();
105            }
106        }
107    
108    
109        /**
110         * Returns the day after <code>date</code>.
111         *
112         * @param date Date used in calculating next day
113         * @return Day after <code>date</code>.
114         */
115        public static Date nextDay(Date date) {
116            return new Date(addDays(date.getTime(), 1));
117        }
118    
119        /**
120         * Adds <code>amount</code> days to <code>time</code> and returns
121         * the resulting time.
122         *
123         * @param time Base time
124         * @param amount Amount of increment.
125         * 
126         * @return the <var>time</var> + <var>amount</var> days
127         */
128        public static long addDays(long time, int amount) {
129            Calendar calendar = CALENDAR;
130            synchronized(calendar) {
131                calendar.setTimeInMillis(time);
132                calendar.add(Calendar.DAY_OF_MONTH, amount);
133                return calendar.getTimeInMillis();
134            }
135        }
136    
137        /**
138         * Returns the day after <code>date</code>.
139         *
140         * @param date Date used in calculating next day
141         * @return Day after <code>date</code>.
142         */
143        public static long nextDay(long date) {
144            return addDays(date, 1);
145        }
146    
147        /**
148         * Returns the week after <code>date</code>.
149         *
150         * @param date Date used in calculating next week
151         * @return week after <code>date</code>.
152         */
153        public static long nextWeek(long date) {
154            return addDays(date, 7);
155        }
156    
157    
158        /**
159         * Returns the number of days difference between <code>t1</code> and
160         * <code>t2</code>.
161         *
162         * @param t1 Time 1
163         * @param t2 Time 2
164         * @param checkOverflow indicates whether to check for overflow
165         * @return Number of days between <code>start</code> and <code>end</code>
166         */
167        public static int getDaysDiff(long t1, long t2, boolean checkOverflow) {
168            if (t1 > t2) {
169                long tmp = t1;
170                t1 = t2;
171                t2 = tmp;
172            }
173            Calendar calendar = CALENDAR;
174            synchronized(calendar) {
175                calendar.setTimeInMillis(t1);
176                int delta = 0;
177                while (calendar.getTimeInMillis() < t2) {
178                    calendar.add(Calendar.DAY_OF_MONTH, 1);
179                    delta++;
180                }
181                if (checkOverflow && (calendar.getTimeInMillis() > t2)) {
182                    delta--;
183                }
184                return delta;
185            }
186        }
187    
188       /**
189         * Returns the number of days difference between <code>t1</code> and
190         * <code>t2</code>.
191         *
192         * @param t1 Time 1
193         * @param t2 Time 2
194         * @return Number of days between <code>start</code> and <code>end</code>
195         */
196          public static int getDaysDiff(long t1, long t2) {
197           return  getDaysDiff(t1, t2, true);
198        }
199    
200        /**
201         * Check, whether the date passed in is the first day of the year.
202         *
203         * @param date date to check in millis
204         * @return <code>true</code> if <var>date</var> corresponds to the first
205         *         day of a year
206         * @see Date#getTime() 
207         */
208        public static boolean isFirstOfYear(long date) {
209            boolean ret = false;
210            Calendar calendar = CALENDAR;
211            synchronized(calendar) {
212                calendar.setTimeInMillis(date);
213                int currentYear = calendar.get(Calendar.YEAR);
214                // Check yesterday
215                calendar.add(Calendar.DATE,-1);
216                int yesterdayYear = calendar.get(Calendar.YEAR);
217                ret = (currentYear != yesterdayYear);
218            }
219            return ret;
220        }
221    
222        /**
223         * Check, whether the date passed in is the first day of the month.
224         *
225         * @param date date to check in millis
226         * @return <code>true</code> if <var>date</var> corresponds to the first
227         *         day of a month
228         * @see Date#getTime() 
229         */
230        public static boolean isFirstOfMonth(long date) {
231            boolean ret = false;
232            Calendar calendar = CALENDAR;
233            synchronized(calendar) {
234                calendar.setTimeInMillis(date);
235                int currentMonth = calendar.get(Calendar.MONTH);
236                // Check yesterday
237                calendar.add(Calendar.DATE,-1);
238                int yesterdayMonth = calendar.get(Calendar.MONTH);
239                ret =  (currentMonth != yesterdayMonth);
240            }
241            return ret;     
242        }
243    
244    
245        /**
246         * Returns the day before <code>date</code>.
247         *
248         * @param date Date used in calculating previous day
249         * @return Day before <code>date</code>.
250         */
251        public static long previousDay(long date) {
252            return addDays(date, -1);
253        }
254    
255        /**
256         * Returns the week before <code>date</code>.
257         *
258         * @param date Date used in calculating previous week
259         * @return week before <code>date</code>.
260         */
261        public static long previousWeek(long date) {
262            return addDays(date, -7);
263        }
264    
265    
266        /**
267         * Returns the first day before <code>date</code> that has the
268         * day of week matching <code>startOfWeek</code>.  For example, if you
269         * want to find the previous monday relative to <code>date</code> you
270         * would call <code>getPreviousDay(date, Calendar.MONDAY)</code>.
271         *
272         * @param date Base date
273         * @param startOfWeek Calendar constant correspoding to start of week.
274         * @return start of week, return value will have 0 hours, 0 minutes,
275         *         0 seconds and 0 ms.
276         * 
277         */
278        public static long getPreviousDay(long date, int startOfWeek) {
279            return getDay(date, startOfWeek, -1);
280        }
281    
282        /**
283         * Returns the first day after <code>date</code> that has the
284         * day of week matching <code>startOfWeek</code>.  For example, if you
285         * want to find the next monday relative to <code>date</code> you
286         * would call <code>getPreviousDay(date, Calendar.MONDAY)</code>.
287         *
288         * @param date Base date
289         * @param startOfWeek Calendar constant correspoding to start of week.
290         * @return start of week, return value will have 0 hours, 0 minutes,
291         *         0 seconds and 0 ms.
292         * 
293         */
294        public static long getNextDay(long date, int startOfWeek) {
295            return getDay(date, startOfWeek, 1);
296        }
297    
298        private static long getDay(long date, int startOfWeek, int increment) {
299            Calendar calendar = CALENDAR;
300            synchronized(calendar) {
301                calendar.setTimeInMillis(date);
302                int day = calendar.get(Calendar.DAY_OF_WEEK);
303                // Normalize the view starting date to a week starting day
304                while (day != startOfWeek) {
305                    calendar.add(Calendar.DATE, increment);
306                    day = calendar.get(Calendar.DAY_OF_WEEK);
307                }
308                return startOfDayInMillis(calendar.getTimeInMillis());
309            }
310        }
311    
312        /**
313         * Returns the previous month.
314         * 
315         * @param date Base date
316         * @return previous month
317         */
318        public static long getPreviousMonth(long date) {
319            return incrementMonth(date, -1);
320        }
321    
322        /**
323         * Returns the next month.
324         * 
325         * @param date Base date
326         * @return next month
327         */
328        public static long getNextMonth(long date) {
329            return incrementMonth(date, 1);
330        }
331    
332        private static long incrementMonth(long date, int increment) {
333            Calendar calendar = CALENDAR;
334            synchronized(calendar) {
335                calendar.setTimeInMillis(date);
336                calendar.add(Calendar.MONTH, increment);
337                return calendar.getTimeInMillis();
338            }
339        }
340    
341        /**
342         * Returns the date corresponding to the start of the month.
343         *
344         * @param date Base date
345         * @return Start of month.
346         */
347        public static long getStartOfMonth(long date) {
348            return getMonth(date, -1);
349        }
350    
351        /**
352         * Returns the date corresponding to the end of the month.
353         *
354         * @param date Base date
355         * @return End of month.
356         */
357        public static long getEndOfMonth(long date) {
358            return getMonth(date, 1);
359        }
360    
361        private static long getMonth(long date, int increment) {
362            long result;
363            Calendar calendar = CALENDAR;
364            synchronized(calendar) {
365                calendar.setTimeInMillis(date);
366                if (increment == -1) {
367                    calendar.set(Calendar.DAY_OF_MONTH, 1);
368                    result = startOfDayInMillis(calendar.getTimeInMillis());
369                } else {
370                    calendar.add(Calendar.MONTH, 1);
371                    calendar.set(Calendar.DAY_OF_MONTH, 1);
372                    calendar.set(Calendar.HOUR_OF_DAY, 0);
373                    calendar.set(Calendar.MILLISECOND, 0);
374                    calendar.set(Calendar.SECOND, 0);
375                    calendar.set(Calendar.MINUTE, 0);
376                    calendar.add(Calendar.MILLISECOND, -1);
377                    result = calendar.getTimeInMillis();
378                }
379            }
380            return result;
381        }
382    
383        /**
384         * Returns the day of the week.
385         *
386         * @param date date
387         * @return day of week.
388         */
389        public static int getDayOfWeek(long date) {
390           Calendar calendar = CALENDAR;
391            synchronized(calendar) {
392                calendar.setTimeInMillis(date);
393                return (calendar.get(Calendar.DAY_OF_WEEK));
394            }
395        }
396    }