KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > data > time > Week


1 /* ===========================================================
2  * JFreeChart : a free chart library for the Java(tm) platform
3  * ===========================================================
4  *
5  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
6  *
7  * Project Info: http://www.jfree.org/jfreechart/index.html
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this library; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22  *
23  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
24  * in the United States and other countries.]
25  *
26  * ---------
27  * Week.java
28  * ---------
29  * (C) Copyright 2001-2004, by Object Refinery Limited and Contributors.
30  *
31  * Original Author: David Gilbert (for Object Refinery Limited);
32  * Contributor(s): Aimin Han;
33  *
34  * $Id: Week.java,v 1.7 2005/05/19 10:35:27 mungady Exp $
35  *
36  * Changes
37  * -------
38  * 11-Oct-2001 : Version 1 (DG);
39  * 18-Dec-2001 : Changed order of parameters in constructor (DG);
40  * 19-Dec-2001 : Added a new constructor as suggested by Paul English (DG);
41  * 29-Jan-2002 : Worked on the parseWeek() method (DG);
42  * 13-Feb-2002 : Fixed bug in Week(Date) constructor (DG);
43  * 26-Feb-2002 : Changed getStart(), getMiddle() and getEnd() methods to
44  * evaluate with reference to a particular time zone (DG);
45  * 05-Apr-2002 : Reinstated this class to the JCommon library (DG);
46  * 24-Jun-2002 : Removed unnecessary main method (DG);
47  * 10-Sep-2002 : Added getSerialIndex() method (DG);
48  * 06-Oct-2002 : Fixed errors reported by Checkstyle (DG);
49  * 18-Oct-2002 : Changed to observe 52 or 53 weeks per year, consistent with
50  * GregorianCalendar. Thanks to Aimin Han for the code (DG);
51  * 02-Jan-2003 : Removed debug code (DG);
52  * 13-Mar-2003 : Moved to com.jrefinery.data.time package, and implemented
53  * Serializable (DG);
54  * 21-Oct-2003 : Added hashCode() method (DG);
55  * 24-May-2004 : Modified getFirstMillisecond() and getLastMillisecond() to
56  * take account of firstDayOfWeek setting in Java's Calendar
57  * class (DG);
58  * 30-Sep-2004 : Replaced getTime().getTime() with getTimeInMillis() (DG);
59  * 04-Nov-2004 : Reverted change of 30-Sep-2004, because it won't work for
60  * JDK 1.3 (DG);
61  *
62  */

63
64 package org.jfree.data.time;
65
66 import java.io.Serializable JavaDoc;
67 import java.util.Calendar JavaDoc;
68 import java.util.Date JavaDoc;
69 import java.util.TimeZone JavaDoc;
70
71 /**
72  * A calendar week. All years are considered to have 53 weeks, numbered from 1
73  * to 53, although in many cases the 53rd week is empty. Most of the time, the
74  * 1st week of the year *begins* in the previous calendar year, but it always
75  * finishes in the current year (this behaviour matches the workings of the
76  * <code>GregorianCalendar</code> class).
77  * <P>
78  * This class is immutable, which is a requirement for all
79  * {@link RegularTimePeriod} subclasses.
80  */

81 public class Week extends RegularTimePeriod implements Serializable JavaDoc {
82
83     /** For serialization. */
84     private static final long serialVersionUID = 1856387786939865061L;
85     
86     /** Constant for the first week in the year. */
87     public static final int FIRST_WEEK_IN_YEAR = 1;
88
89     /** Constant for the last week in the year. */
90     public static final int LAST_WEEK_IN_YEAR = 53;
91
92     /** The year in which the week falls. */
93     private Year year;
94
95     /** The week (1-53). */
96     private int week;
97
98     /**
99      * Creates a new time period for the week in which the current system
100      * date/time falls.
101      */

102     public Week() {
103         this(new Date JavaDoc());
104     }
105
106     /**
107      * Creates a time period representing the week in the specified year.
108      *
109      * @param week the week (1 to 53).
110      * @param year the year (1900 to 9999).
111      */

112     public Week(int week, int year) {
113         this(week, new Year(year));
114     }
115
116     /**
117      * Creates a time period representing the week in the specified year.
118      *
119      * @param week the week (1 to 53).
120      * @param year the year (1900 to 9999).
121      */

122     public Week(int week, Year year) {
123         if ((week < FIRST_WEEK_IN_YEAR) && (week > LAST_WEEK_IN_YEAR)) {
124             throw new IllegalArgumentException JavaDoc(
125                 "The 'week' argument must be in the range 1 - 53."
126             );
127         }
128         this.week = week;
129         this.year = year;
130     }
131
132     /**
133      * Creates a time period for the week in which the specified date/time
134      * falls.
135      *
136      * @param time the time (<code>null</code> not permitted).
137      */

138     public Week(Date JavaDoc time) {
139         // defer argument checking...
140
this(time, RegularTimePeriod.DEFAULT_TIME_ZONE);
141     }
142
143     /**
144      * Creates a time period for the week in which the specified date/time
145      * falls, calculated relative to the specified time zone.
146      *
147      * @param time the date/time (<code>null</code> not permitted).
148      * @param zone the time zone (<code>null</code> not permitted).
149      */

150     public Week(Date JavaDoc time, TimeZone JavaDoc zone) {
151         if (time == null) {
152             throw new IllegalArgumentException JavaDoc("Null 'time' argument.");
153         }
154         if (zone == null) {
155             throw new IllegalArgumentException JavaDoc("Null 'zone' argument.");
156         }
157         Calendar JavaDoc calendar = Calendar.getInstance(zone);
158         calendar.setTime(time);
159
160         // sometimes the last few days of the year are considered to fall in
161
// the *first* week of the following year. Refer to the Javadocs for
162
// GregorianCalendar.
163
int tempWeek = calendar.get(Calendar.WEEK_OF_YEAR);
164         if (tempWeek == 1
165                 && calendar.get(Calendar.MONTH) == Calendar.DECEMBER) {
166             this.week = 1;
167             this.year = new Year(calendar.get(Calendar.YEAR) + 1);
168         }
169         else {
170             this.week = Math.min(tempWeek, LAST_WEEK_IN_YEAR);
171             this.year = new Year(calendar.get(Calendar.YEAR));
172         }
173
174     }
175
176     /**
177      * Returns the year in which the week falls.
178      *
179      * @return The year (never <code>null</code>).
180      */

181     public Year getYear() {
182         return this.year;
183     }
184
185     /**
186      * Returns the year in which the week falls, as an integer value.
187      *
188      * @return The year.
189      */

190     public int getYearValue() {
191         return this.year.getYear();
192     }
193
194     /**
195      * Returns the week.
196      *
197      * @return The week.
198      */

199     public int getWeek() {
200         return this.week;
201     }
202
203     /**
204      * Returns the week preceding this one. This method will return
205      * <code>null</code> for some lower limit on the range of weeks (currently
206      * week 1, 1900). For week 1 of any year, the previous week is always week
207      * 53, but week 53 may not contain any days (you should check for this).
208      *
209      * @return The preceding week (possibly <code>null</code>).
210      */

211     public RegularTimePeriod previous() {
212
213         Week result;
214         if (this.week != FIRST_WEEK_IN_YEAR) {
215             result = new Week(this.week - 1, this.year);
216         }
217         else {
218             // we need to work out if the previous year has 52 or 53 weeks...
219
Year prevYear = (Year) this.year.previous();
220             if (prevYear != null) {
221                 int yy = prevYear.getYear();
222                 Calendar JavaDoc prevYearCalendar = Calendar.getInstance();
223                 prevYearCalendar.set(yy, Calendar.DECEMBER, 31);
224                 result = new Week(
225                     prevYearCalendar.getActualMaximum(Calendar.WEEK_OF_YEAR),
226                     prevYear
227                 );
228             }
229             else {
230                 result = null;
231             }
232         }
233         return result;
234
235     }
236
237     /**
238      * Returns the week following this one. This method will return
239      * <code>null</code> for some upper limit on the range of weeks (currently
240      * week 53, 9999). For week 52 of any year, the following week is always
241      * week 53, but week 53 may not contain any days (you should check for
242      * this).
243      *
244      * @return The following week (possibly <code>null</code>).
245      */

246     public RegularTimePeriod next() {
247
248         Week result;
249         if (this.week < 52) {
250             result = new Week(this.week + 1, this.year);
251         }
252         else {
253             Calendar JavaDoc calendar = Calendar.getInstance();
254             calendar.set(this.year.getYear(), Calendar.DECEMBER, 31);
255             int actualMaxWeek
256                 = calendar.getActualMaximum(Calendar.WEEK_OF_YEAR);
257             if (this.week != actualMaxWeek) {
258                 result = new Week(this.week + 1, this.year);
259             }
260             else {
261                 Year nextYear = (Year) this.year.next();
262                 if (nextYear != null) {
263                     result = new Week(FIRST_WEEK_IN_YEAR, nextYear);
264                 }
265                 else {
266                     result = null;
267                 }
268             }
269         }
270         return result;
271
272     }
273
274     /**
275      * Returns a serial index number for the week.
276      *
277      * @return The serial index number.
278      */

279     public long getSerialIndex() {
280         return this.year.getYear() * 53L + this.week;
281     }
282
283     /**
284      * Returns the first millisecond of the week, evaluated using the supplied
285      * calendar (which determines the time zone).
286      *
287      * @param calendar the calendar.
288      *
289      * @return The first millisecond of the week.
290      */

291     public long getFirstMillisecond(Calendar JavaDoc calendar) {
292         Calendar JavaDoc c = (Calendar JavaDoc) calendar.clone();
293         c.clear();
294         c.set(Calendar.YEAR, this.year.getYear());
295         c.set(Calendar.WEEK_OF_YEAR, this.week);
296         c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek());
297         c.set(Calendar.HOUR, 0);
298         c.set(Calendar.MINUTE, 0);
299         c.set(Calendar.SECOND, 0);
300         c.set(Calendar.MILLISECOND, 0);
301         //return c.getTimeInMillis(); // this won't work for JDK 1.3
302
return c.getTime().getTime();
303     }
304
305     /**
306      * Returns the last millisecond of the week, evaluated using the supplied
307      * calendar (which determines the time zone).
308      *
309      * @param calendar the calendar.
310      *
311      * @return The last millisecond of the week.
312      */

313     public long getLastMillisecond(Calendar JavaDoc calendar) {
314         RegularTimePeriod next = next();
315         return next.getFirstMillisecond(calendar) - 1;
316     }
317
318     /**
319      * Returns a string representing the week (e.g. "Week 9, 2002").
320      *
321      * TODO: look at internationalisation.
322      *
323      * @return A string representing the week.
324      */

325     public String JavaDoc toString() {
326         return "Week " + this.week + ", " + this.year;
327     }
328
329     /**
330      * Tests the equality of this Week object to an arbitrary object. Returns
331      * true if the target is a Week instance representing the same week as this
332      * object. In all other cases, returns false.
333      * @param obj The object.
334      *
335      * @return <code>true</code> if week and year of this and object are the
336      * same.
337      */

338     public boolean equals(Object JavaDoc obj) {
339
340         if (obj == this) {
341             return true;
342         }
343         if (!(obj instanceof Week)) {
344             return false;
345         }
346         Week that = (Week) obj;
347         if (this.week != that.week) {
348             return false;
349         }
350         if (!this.year.equals(that.year)) {
351             return false;
352         }
353         return true;
354
355     }
356
357     /**
358      * Returns a hash code for this object instance. The approach described by
359      * Joshua Bloch in "Effective Java" has been used here:
360      * <p>
361      * <code>http://developer.java.sun.com/developer/Books/effectivejava
362      * /Chapter3.pdf</code>
363      *
364      * @return A hash code.
365      */

366     public int hashCode() {
367         int result = 17;
368         result = 37 * result + this.week;
369         result = 37 * result + this.year.hashCode();
370         return result;
371     }
372
373     /**
374      * Returns an integer indicating the order of this Week object relative to
375      * the specified object:
376      *
377      * negative == before, zero == same, positive == after.
378      *
379      * @param o1 the object to compare.
380      *
381      * @return negative == before, zero == same, positive == after.
382      */

383     public int compareTo(Object JavaDoc o1) {
384
385         int result;
386
387         // CASE 1 : Comparing to another Week object
388
// --------------------------------------------
389
if (o1 instanceof Week) {
390             Week w = (Week) o1;
391             result = this.year.getYear() - w.getYear().getYear();
392             if (result == 0) {
393                 result = this.week - w.getWeek();
394             }
395         }
396
397         // CASE 2 : Comparing to another TimePeriod object
398
// -----------------------------------------------
399
else if (o1 instanceof RegularTimePeriod) {
400             // more difficult case - evaluate later...
401
result = 0;
402         }
403
404         // CASE 3 : Comparing to a non-TimePeriod object
405
// ---------------------------------------------
406
else {
407             // consider time periods to be ordered after general objects
408
result = 1;
409         }
410
411         return result;
412
413     }
414
415     /**
416      * Parses the string argument as a week.
417      * <P>
418      * This method is required to accept the format "YYYY-Wnn". It will also
419      * accept "Wnn-YYYY". Anything else, at the moment, is a bonus.
420      *
421      * @param s string to parse.
422      *
423      * @return <code>null</code> if the string is not parseable, the week
424      * otherwise.
425      */

426     public static Week parseWeek(String JavaDoc s) {
427
428         Week result = null;
429         if (s != null) {
430
431             // trim whitespace from either end of the string
432
s = s.trim();
433
434             int i = Week.findSeparator(s);
435             if (i != -1) {
436                 String JavaDoc s1 = s.substring(0, i).trim();
437                 String JavaDoc s2 = s.substring(i + 1, s.length()).trim();
438
439                 Year y = Week.evaluateAsYear(s1);
440                 int w;
441                 if (y != null) {
442                     w = Week.stringToWeek(s2);
443                     if (w == -1) {
444                         throw new TimePeriodFormatException(
445                             "Can't evaluate the week."
446                         );
447                     }
448                     result = new Week(w, y);
449                 }
450                 else {
451                     y = Week.evaluateAsYear(s2);
452                     if (y != null) {
453                         w = Week.stringToWeek(s1);
454                         if (w == -1) {
455                             throw new TimePeriodFormatException(
456                                 "Can't evaluate the week."
457                             );
458                         }
459                         result = new Week(w, y);
460                     }
461                     else {
462                         throw new TimePeriodFormatException(
463                             "Can't evaluate the year."
464                         );
465                     }
466                 }
467
468             }
469             else {
470                 throw new TimePeriodFormatException(
471                     "Could not find separator."
472                 );
473             }
474
475         }
476         return result;
477
478     }
479
480     /**
481      * Finds the first occurrence of ' ', '-', ',' or '.'
482      *
483      * @param s the string to parse.
484      *
485      * @return <code>-1</code> if none of the characters was found, the
486      * index of the first occurrence otherwise.
487      */

488     private static int findSeparator(String JavaDoc s) {
489
490         int result = s.indexOf('-');
491         if (result == -1) {
492             result = s.indexOf(',');
493         }
494         if (result == -1) {
495             result = s.indexOf(' ');
496         }
497         if (result == -1) {
498             result = s.indexOf('.');
499         }
500         return result;
501     }
502
503     /**
504      * Creates a year from a string, or returns null (format exceptions
505      * suppressed).
506      *
507      * @param s string to parse.
508      *
509      * @return <code>null</code> if the string is not parseable, the year
510      * otherwise.
511      */

512     private static Year evaluateAsYear(String JavaDoc s) {
513
514         Year result = null;
515         try {
516             result = Year.parseYear(s);
517         }
518         catch (TimePeriodFormatException e) {
519             // suppress
520
}
521         return result;
522
523     }
524
525     /**
526      * Converts a string to a week.
527      *
528      * @param s the string to parse.
529      * @return <code>-1</code> if the string does not contain a week number,
530      * the number of the week otherwise.
531      */

532     private static int stringToWeek(String JavaDoc s) {
533
534         int result = -1;
535         s = s.replace('W', ' ');
536         s = s.trim();
537         try {
538             result = Integer.parseInt(s);
539             if ((result < 1) || (result > LAST_WEEK_IN_YEAR)) {
540                 result = -1;
541             }
542         }
543         catch (NumberFormatException JavaDoc e) {
544             // suppress
545
}
546         return result;
547
548     }
549     
550 }
551
Popular Tags