001: /*
002: *
003: *
004: * Portions Copyright 2000-2007 Sun Microsystems, Inc. All Rights
005: * Reserved. Use is subject to license terms.
006: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
007: *
008: * This program is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU General Public License version
010: * 2 only, as published by the Free Software Foundation.
011: *
012: * This program is distributed in the hope that it will be useful, but
013: * WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * General Public License version 2 for more details (a copy is
016: * included at /legal/license.txt).
017: *
018: * You should have received a copy of the GNU General Public License
019: * version 2 along with this work; if not, write to the Free Software
020: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
021: * 02110-1301 USA
022: *
023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
024: * Clara, CA 95054 or visit www.sun.com if you need additional
025: * information or have any questions.
026: */
027:
028: /*
029: * (C) Copyright Taligent, Inc. 1996-1998 - All Rights Reserved
030: * (C) Copyright IBM Corp. 1996-1998 - All Rights Reserved
031: *
032: * The original version of this source code and documentation is copyrighted
033: * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
034: * materials are provided under terms of a License Agreement between Taligent
035: * and Sun. This technology is protected by multiple US and International
036: * patents. This notice and attribution to Taligent may not be removed.
037: * Taligent is a registered trademark of Taligent, Inc.
038: *
039: */
040:
041: package java.util;
042:
043: /**
044: * <code>Calendar</code> is an abstract base class for converting between
045: * a <code>Date</code> object and a set of integer fields such as
046: * <code>YEAR</code>, <code>MONTH</code>, <code>DAY</code>, <code>HOUR</code>,
047: * and so on. (A <code>Date</code> object represents a specific instant in
048: * time with millisecond precision. See
049: * {@link Date}
050: * for information about the <code>Date</code> class.)
051: *
052: * <p>
053: * Subclasses of <code>Calendar</code> interpret a <code>Date</code>
054: * according to the rules of a specific calendar system.
055: *
056: * <p>
057: * Like other locale-sensitive classes, <code>Calendar</code> provides a
058: * class method, <code>getInstance</code>, for getting a generally useful
059: * object of this type.
060: * <blockquote>
061: * <pre>
062: * Calendar rightNow = Calendar.getInstance();
063: * </pre>
064: * </blockquote>
065: *
066: * <p>
067: * A <code>Calendar</code> object can produce all the time field values
068: * needed to implement the date-time formatting for a particular language
069: * and calendar style (for example, Japanese-Gregorian, Japanese-Traditional).
070: *
071: * <p>
072: * When computing a <code>Date</code> from time fields,
073: * there may be insufficient information to compute the
074: * <code>Date</code> (such as only year and month but no day in the month).
075: *
076: * <p>
077: * <strong>Insufficient information.</strong> The calendar will use default
078: * information to specify the missing fields. This may vary by calendar; for
079: * the Gregorian calendar, the default for a field is the same as that of the
080: * start of the epoch: i.e., YEAR = 1970, MONTH = JANUARY, DATE = 1, etc.
081: *
082: * <strong>Note:</strong> The ambiguity in interpretation of what day midnight
083: * belongs to, is resolved as so: midnight "belongs" to the following day.<br>
084: * 23:59 on Dec 31, 1969 < 00:00 on Jan 1, 1970.<br>
085: * 12:00 PM is midday, and 12:00 AM is midnight.<br>
086: * 11:59 PM on Jan 1 < 12:00 AM on Jan 2 < 12:01 AM on Jan 2.<br>
087: * 11:59 AM on Mar 10 < 12:00 PM on Mar 10 < 12:01 PM on Mar 10.<br>
088: * 24:00 or greater are invalid.
089: * Hours greater than 12 are invalid in AM/PM mode.
090: * Setting the time will never change the date.
091: * <p>
092: * If equivalent times are entered in AM/PM or 24 hour mode, equality will be
093: * determined by the actual time rather than the entered time.
094: * <p>
095: *
096: * This class has been subset for J2ME based on the JDK 1.3 Calendar class.
097: * Many methods and variables have been pruned, and other methods
098: * simplified, in an effort to reduce the size of this class.
099: *
100: * @see java.util.Date
101: * @see java.util.TimeZone
102: * @version CLDC 1.1 02/01/2002 (based on JDK 1.3)
103: */
104: public abstract class Calendar {
105: /**
106: * Field number for <code>get</code> and <code>set</code> indicating the
107: * year. This is a calendar-specific value.
108: */
109: public final static int YEAR = 1;
110: /**
111: * Field number for <code>get</code> and <code>set</code> indicating the
112: * month. This is a calendar-specific value.
113: */
114: public final static int MONTH = 2;
115: /**
116: * Field number for <code>get</code> and <code>set</code> indicating the
117: * day of the month. This is a synonym for <code>DAY_OF_MONTH</code>.
118: * @see #DAY_OF_MONTH
119: */
120: public final static int DATE = 5;
121: /**
122: * Field number for <code>get</code> and <code>set</code> indicating the
123: * day of the month. This is a synonym for <code>DATE</code>.
124: * @see #DATE
125: */
126: public final static int DAY_OF_MONTH = 5;
127: /**
128: * Field number for <code>get</code> and <code>set</code> indicating the
129: * day of the week.
130: */
131: public final static int DAY_OF_WEEK = 7;
132: /**
133: * Field number for <code>get</code> and <code>set</code> indicating
134: * whether the <code>HOUR</code> is before or after noon.
135: * E.g., at 10:04:15.250 PM the <code>AM_PM</code> is <code>PM</code>.
136: * @see #AM
137: * @see #PM
138: * @see #HOUR
139: */
140: public final static int AM_PM = 9;
141: /**
142: * Field number for <code>get</code> and <code>set</code> indicating the
143: * hour of the morning or afternoon. <code>HOUR</code> is used for the
144: * 12-hour clock.
145: * E.g., at 10:04:15.250 PM the <code>HOUR</code> is 10.
146: * @see #AM_PM
147: * @see #HOUR_OF_DAY
148: */
149: public final static int HOUR = 10;
150: /**
151: * Field number for <code>get</code> and <code>set</code> indicating the
152: * hour of the day. <code>HOUR_OF_DAY</code> is used for the 24-hour clock.
153: * E.g., at 10:04:15.250 PM the <code>HOUR_OF_DAY</code> is 22.
154: */
155: public final static int HOUR_OF_DAY = 11;
156: /**
157: * Field number for <code>get</code> and <code>set</code> indicating the
158: * minute within the hour.
159: * E.g., at 10:04:15.250 PM the <code>MINUTE</code> is 4.
160: */
161: public final static int MINUTE = 12;
162: /**
163: * Field number for <code>get</code> and <code>set</code> indicating the
164: * second within the minute.
165: * E.g., at 10:04:15.250 PM the <code>SECOND</code> is 15.
166: */
167: public final static int SECOND = 13;
168: /**
169: * Field number for <code>get</code> and <code>set</code> indicating the
170: * millisecond within the second.
171: * E.g., at 10:04:15.250 PM the <code>MILLISECOND</code> is 250.
172: */
173: public final static int MILLISECOND = 14;
174: /**
175: * Value of the <code>DAY_OF_WEEK</code> field indicating
176: * Sunday.
177: */
178: public final static int SUNDAY = 1;
179: /**
180: * Value of the <code>DAY_OF_WEEK</code> field indicating
181: * Monday.
182: */
183: public final static int MONDAY = 2;
184: /**
185: * Value of the <code>DAY_OF_WEEK</code> field indicating
186: * Tuesday.
187: */
188: public final static int TUESDAY = 3;
189: /**
190: * Value of the <code>DAY_OF_WEEK</code> field indicating
191: * Wednesday.
192: */
193: public final static int WEDNESDAY = 4;
194: /**
195: * Value of the <code>DAY_OF_WEEK</code> field indicating
196: * Thursday.
197: */
198: public final static int THURSDAY = 5;
199: /**
200: * Value of the <code>DAY_OF_WEEK</code> field indicating
201: * Friday.
202: */
203: public final static int FRIDAY = 6;
204: /**
205: * Value of the <code>DAY_OF_WEEK</code> field indicating
206: * Saturday.
207: */
208: public final static int SATURDAY = 7;
209: /**
210: * Value of the <code>MONTH</code> field indicating the
211: * first month of the year.
212: */
213: public final static int JANUARY = 0;
214: /**
215: * Value of the <code>MONTH</code> field indicating the
216: * second month of the year.
217: */
218: public final static int FEBRUARY = 1;
219: /**
220: * Value of the <code>MONTH</code> field indicating the
221: * third month of the year.
222: */
223: public final static int MARCH = 2;
224: /**
225: * Value of the <code>MONTH</code> field indicating the
226: * fourth month of the year.
227: */
228: public final static int APRIL = 3;
229: /**
230: * Value of the <code>MONTH</code> field indicating the
231: * fifth month of the year.
232: */
233: public final static int MAY = 4;
234: /**
235: * Value of the <code>MONTH</code> field indicating the
236: * sixth month of the year.
237: */
238: public final static int JUNE = 5;
239: /**
240: * Value of the <code>MONTH</code> field indicating the
241: * seventh month of the year.
242: */
243: public final static int JULY = 6;
244: /**
245: * Value of the <code>MONTH</code> field indicating the
246: * eighth month of the year.
247: */
248: public final static int AUGUST = 7;
249: /**
250: * Value of the <code>MONTH</code> field indicating the
251: * ninth month of the year.
252: */
253: public final static int SEPTEMBER = 8;
254: /**
255: * Value of the <code>MONTH</code> field indicating the
256: * tenth month of the year.
257: */
258: public final static int OCTOBER = 9;
259: /**
260: * Value of the <code>MONTH</code> field indicating the
261: * eleventh month of the year.
262: */
263: public final static int NOVEMBER = 10;
264: /**
265: * Value of the <code>MONTH</code> field indicating the
266: * twelfth month of the year.
267: */
268: public final static int DECEMBER = 11;
269: /**
270: * Value of the <code>AM_PM</code> field indicating the
271: * period of the day from midnight to just before noon.
272: */
273: public final static int AM = 0;
274: /**
275: * Value of the <code>AM_PM</code> field indicating the
276: * period of the day from noon to just before midnight.
277: */
278: public final static int PM = 1;
279:
280: // Internal notes:
281: // Calendar contains two kinds of time representations: current "time" in
282: // milliseconds, and a set of time "fields" representing the current time.
283: // The two representations are usually in sync, but can get out of sync
284: // as follows.
285: // 1. Initially, no fields are set, and the time is invalid.
286: // 2. If the time is set, all fields are computed and in sync.
287: // 3. If a single field is set, the time is invalid.
288: // Recomputation of the time and fields happens when the object needs
289: // to return a result to the user, or use a result for a computation.
290:
291: /*
292: * The number of fields for the array below.
293: */
294: private final static int FIELDS = 15;
295:
296: /**
297: * The field values for the currently set time for this calendar.
298: */
299: protected int fields[];
300:
301: /**
302: * The flags which tell if a specified time field for the calendar is set.
303: * This is an array of <code>FIELD_COUNT</code> booleans,
304: */
305: protected boolean isSet[];
306:
307: /**
308: * The currently set time for this calendar, expressed in milliseconds after
309: * January 1, 1970, 0:00:00 GMT.
310: */
311: protected long time;
312:
313: /**
314: * True if then the value of <code>time</code> is valid.
315: * The time is made invalid by a change to an item of <code>field[]</code>.
316: * @see #time
317: */
318: private boolean isTimeSet; // NOTE: Make transient when possible
319:
320: /**
321: * The <code>TimeZone</code> used by this calendar. </code>Calendar</code>
322: * uses the time zone data to translate between the current/default
323: * system time and GMT time.
324: */
325: private TimeZone zone;
326:
327: private Date dateObj = null;
328:
329: /**
330: * Constructs a Calendar with the default time zone.
331: *
332: * @see TimeZone#getDefault
333: */
334: protected Calendar() {
335: fields = new int[FIELDS];
336: isSet = new boolean[FIELDS];
337:
338: zone = TimeZone.getDefault();
339: if (zone == null) {
340: throw new RuntimeException(
341: /* #ifdef VERBOSE_EXCEPTIONS */
342: /// skipped "Could not find default timezone"
343: /* #endif */
344: );
345: }
346: setTimeInMillis(System.currentTimeMillis());
347: }
348:
349: /**
350: * Gets this Calendar's current time.
351: *
352: * @return the current time.
353: *
354: * @see #setTime
355: */
356: public final Date getTime() {
357: if (dateObj == null) {
358: return dateObj = new Date(getTimeInMillis());
359: } else {
360: synchronized (dateObj) {
361: dateObj.setTime(getTimeInMillis());
362: return dateObj;
363: }
364: }
365: }
366:
367: /**
368: * Sets this Calendar's current time with the given Date.
369: * <p>
370: * Note: Calling <code>setTime()</code> with
371: * <code>Date(Long.MAX_VALUE)</code> or <code>Date(Long.MIN_VALUE)</code>
372: * may yield incorrect field values from <code>get()</code>.
373: *
374: * @param date the given Date.
375: *
376: * @see #getTime
377: */
378: public final void setTime(Date date) {
379: setTimeInMillis(date.getTime());
380: }
381:
382: /**
383: * Gets a calendar using the default time zone.
384: *
385: * @return a Calendar.
386: */
387:
388: /* <p>
389: * The following is information for implementers. Applications
390: * should not need to be aware of this or rely on it, because
391: * each implementation may do it differently:
392: * <p>
393: * The Calendar class will look up a calendar implementation
394: * class at runtime. The class name will take the form:
395: * <p>
396: * <code>{classRoot}.util.{platform}.CalendarImpl</code>
397: * <p>
398: * To simplify things, we use a hard-coded path name here.
399: * Actual location of the implementation class may vary
400: * from one implementation to another.
401: */
402: public static synchronized Calendar getInstance() {
403: try {
404: // Obtain the calendar implementation class
405: Class clazz = Class
406: .forName("com.sun.cldc.util.j2me.CalendarImpl");
407:
408: // Construct a new instance
409: return (Calendar) clazz.newInstance();
410: } catch (Exception x) {
411: }
412: return null;
413: }
414:
415: /**
416: * Gets a calendar using the specified time zone.
417: * @param zone the time zone to use
418: * @return a Calendar.
419: */
420: public static synchronized Calendar getInstance(TimeZone zone) {
421: Calendar cal = getInstance();
422: cal.setTimeZone(zone);
423: return cal;
424: }
425:
426: /**
427: * Gets this Calendar's current time as a long expressed in milliseconds
428: * after January 1, 1970, 0:00:00 GMT (the epoch).
429: *
430: * @return the current time as UTC milliseconds from the epoch.
431: *
432: * @see #setTimeInMillis
433: */
434: protected long getTimeInMillis() {
435: if (!isTimeSet) {
436: computeTime();
437: isTimeSet = true;
438: }
439: return this .time;
440: }
441:
442: /**
443: * Sets this Calendar's current time from the given long value.
444: * @param millis the new time in UTC milliseconds from the epoch.
445: *
446: * @see #getTimeInMillis
447: */
448: protected void setTimeInMillis(long millis) {
449: isTimeSet = true;
450: this .fields[DAY_OF_WEEK] = 0;
451: this .time = millis;
452: computeFields();
453: }
454:
455: /**
456: * Gets the value for a given time field.
457: * @param field the given time field (either YEAR, MONTH, DATE, DAY_OF_WEEK,
458: * HOUR_OF_DAY, HOUR, AM_PM, MINUTE,
459: * SECOND, or MILLISECOND
460: * @return the value for the given time field.
461: * @exception ArrayIndexOutOfBoundsException if the parameter is not
462: * one of the above.
463: */
464: public final int get(int field) {
465: if (field == DAY_OF_WEEK || field == HOUR_OF_DAY
466: || field == AM_PM || field == HOUR) {
467: getTimeInMillis();
468: computeFields();
469: }
470: return this .fields[field];
471: }
472:
473: /**
474: * Sets the time field with the given value.
475: *
476: * @param field the given time field.
477: * @param value the value to be set for the given time field.
478: *
479: * @exception ArrayIndexOutOfBoundsException if an illegal field
480: * parameter is received.
481: */
482: public final void set(int field, int value) {
483: isTimeSet = false;
484:
485: this .isSet[field] = true;
486: this .fields[field] = value;
487: }
488:
489: /**
490: * Compares this calendar to the specified object.
491: * The result is <code>true</code> if and only if the argument is
492: * not <code>null</code> and is a <code>Calendar</code> object that
493: * represents the same calendar as this object.
494: * @param obj the object to compare with.
495: * @return <code>true</code> if the objects are the same;
496: * <code>false</code> otherwise.
497: */
498: public boolean equals(Object obj) {
499: if (this == obj) {
500: return true;
501: }
502:
503: if (!(obj instanceof Calendar)) {
504: return false;
505: }
506:
507: Calendar that = (Calendar) obj;
508: return getTimeInMillis() == that.getTimeInMillis()
509: && zone.equals(that.zone);
510: }
511:
512: /**
513: * Compares the time field records.
514: * Equivalent to comparing result of conversion to UTC.
515: * @param when the Calendar to be compared with this Calendar.
516: * @return true if the current time of this Calendar is before
517: * the time of Calendar when; false otherwise.
518: */
519: public boolean before(Object when) {
520: return (when instanceof Calendar && getTimeInMillis() < ((Calendar) when)
521: .getTimeInMillis());
522: }
523:
524: /**
525: * Compares the time field records.
526: * Equivalent to comparing result of conversion to UTC.
527: * @param when the Calendar to be compared with this Calendar.
528: * @return true if the current time of this Calendar is after
529: * the time of Calendar when; false otherwise.
530: */
531: public boolean after(Object when) {
532: return (when instanceof Calendar && getTimeInMillis() > ((Calendar) when)
533: .getTimeInMillis());
534: }
535:
536: /**
537: * Sets the time zone with the given time zone value.
538: * @param value the given time zone.
539: *
540: * @see #getTimeZone
541: */
542: public void setTimeZone(TimeZone value) {
543: zone = value;
544: getTimeInMillis();
545: computeFields();
546: }
547:
548: /**
549: * Gets the time zone.
550: * @return the time zone object associated with this calendar.
551: *
552: * @see #setTimeZone
553: */
554: public TimeZone getTimeZone() {
555: return zone;
556: }
557:
558: /**
559: * Converts
560: * the current millisecond time value
561: * <code>time</code>
562: * to field values in <code>fields[]</code>.
563: * This allows you to sync up the time field values with
564: * a new time that is set for the calendar.
565: */
566: protected abstract void computeFields();
567:
568: /**
569: * Converts the current field values in <code>fields[]</code>
570: * to the millisecond time value
571: * <code>time</code>.
572: */
573: protected abstract void computeTime();
574: }
|