OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [java/] [util/] [Calendar.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* Calendar.java --
2
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package java.util;
40
 
41
import java.io.IOException;
42
import java.io.ObjectInputStream;
43
import java.io.ObjectOutputStream;
44
import java.io.Serializable;
45
import java.lang.reflect.Constructor;
46
import java.lang.reflect.InvocationTargetException;
47
 
48
/**
49
 * This class is an abstract base class for Calendars, which can be
50
 * used to convert between <code>Date</code> objects and a set of
51
 * integer fields which represent <code>YEAR</code>,
52
 * <code>MONTH</code>, <code>DAY</code>, etc.  The <code>Date</code>
53
 * object represents a time in milliseconds since the Epoch. <br>
54
 *
55
 * This class is locale sensitive.  To get the Object matching the
56
 * current locale you can use <code>getInstance</code>.  You can even provide
57
 * a locale or a timezone.  <code>getInstance</code> returns currently
58
 * a <code>GregorianCalendar</code> for the current date. <br>
59
 *
60
 * If you want to convert a date from the Year, Month, Day, DayOfWeek,
61
 * etc.  Representation to a <code>Date</code>-Object, you can create
62
 * a new Calendar with <code>getInstance()</code>,
63
 * <code>clear()</code> all fields, <code>set(int,int)</code> the
64
 * fields you need and convert it with <code>getTime()</code>. <br>
65
 *
66
 * If you want to convert a <code>Date</code>-object to the Calendar
67
 * representation, create a new Calendar, assign the
68
 * <code>Date</code>-Object with <code>setTime()</code>, and read the
69
 * fields with <code>get(int)</code>. <br>
70
 *
71
 * When computing the date from time fields, it may happen, that there
72
 * are either two few fields set, or some fields are inconsistent.  This
73
 * cases will handled in a calendar specific way.  Missing fields are
74
 * replaced by the fields of the epoch: 1970 January 1 00:00. <br>
75
 *
76
 * To understand, how the day of year is computed out of the fields
77
 * look at the following table.  It is traversed from top to bottom,
78
 * and for the first line all fields are set, that line is used to
79
 * compute the day. <br>
80
 *
81
 *
82
<pre>month + day_of_month
83
month + week_of_month + day_of_week
84
month + day_of_week_of_month + day_of_week
85
day_of_year
86
day_of_week + week_of_year</pre>
87
 *
88
 * The hour_of_day-field takes precedence over the ampm and
89
 * hour_of_ampm fields. <br>
90
 *
91
 * <STRONG>Note:</STRONG> This can differ for non-Gregorian calendar. <br>
92
 *
93
 * To convert a calendar to a human readable form and vice versa,  use
94
 * the <code>java.text.DateFormat</code> class. <br>
95
 *
96
 * Other useful things you can do with an calendar, is
97
 * <code>roll</code>ing fields (that means increase/decrease a
98
 * specific field by one, propagating overflows), or
99
 * <code>add</code>ing/substracting a fixed amount to a field.
100
 *
101
 * @see Date
102
 * @see GregorianCalendar
103
 * @see TimeZone
104
 * @see java.text.DateFormat
105
 */
106
public abstract class Calendar implements Serializable, Cloneable
107
{
108
  /**
109
   * Constant representing the era time field.
110
   */
111
  public static final int ERA = 0;
112
 
113
  /**
114
   * Constant representing the year time field.
115
   */
116
  public static final int YEAR = 1;
117
 
118
  /**
119
   * Constant representing the month time field.  This field
120
   * should contain one of the JANUARY,...,DECEMBER constants below.
121
   */
122
  public static final int MONTH = 2;
123
 
124
  /**
125
   * Constant representing the week of the year field.
126
   * @see #setFirstDayOfWeek(int)
127
   */
128
  public static final int WEEK_OF_YEAR = 3;
129
 
130
  /**
131
   * Constant representing the week of the month time field.
132
   * @see #setFirstDayOfWeek(int)
133
   */
134
  public static final int WEEK_OF_MONTH = 4;
135
 
136
  /**
137
   * Constant representing the day time field, synonym for DAY_OF_MONTH.
138
   */
139
  public static final int DATE = 5;
140
 
141
  /**
142
   * Constant representing the day time field.
143
   */
144
  public static final int DAY_OF_MONTH = 5;
145
 
146
  /**
147
   * Constant representing the day of year time field.  This is
148
   * 1 for the first day in month.
149
   */
150
  public static final int DAY_OF_YEAR = 6;
151
 
152
  /**
153
   * Constant representing the day of week time field.  This field
154
   * should contain one of the SUNDAY,...,SATURDAY constants below.
155
   */
156
  public static final int DAY_OF_WEEK = 7;
157
 
158
  /**
159
   * Constant representing the day-of-week-in-month field.  For
160
   * instance this field contains 2 for the second thursday in a
161
   * month.  If you give a negative number here, the day will count
162
   * from the end of the month.
163
   */
164
  public static final int DAY_OF_WEEK_IN_MONTH = 8;
165
 
166
  /**
167
   * Constant representing the part of the day for 12-hour clock.  This
168
   * should be one of AM or PM.
169
   */
170
  public static final int AM_PM = 9;
171
 
172
  /**
173
   * Constant representing the hour time field for 12-hour clock.
174
   */
175
  public static final int HOUR = 10;
176
 
177
  /**
178
   * Constant representing the hour of day time field for 24-hour clock.
179
   */
180
  public static final int HOUR_OF_DAY = 11;
181
 
182
  /**
183
   * Constant representing the minute of hour time field.
184
   */
185
  public static final int MINUTE = 12;
186
 
187
  /**
188
   * Constant representing the second time field.
189
   */
190
  public static final int SECOND = 13;
191
 
192
  /**
193
   * Constant representing the millisecond time field.
194
   */
195
  public static final int MILLISECOND = 14;
196
 
197
  /**
198
   * Constant representing the time zone offset time field for the
199
   * time given in the other fields.  It is measured in
200
   * milliseconds.  The default is the offset of the time zone.
201
   */
202
  public static final int ZONE_OFFSET = 15;
203
 
204
  /**
205
   * Constant representing the daylight saving time offset in
206
   * milliseconds.  The default is the value given by the time zone.
207
   */
208
  public static final int DST_OFFSET = 16;
209
 
210
  /**
211
   * Number of time fields.
212
   */
213
  public static final int FIELD_COUNT = 17;
214
 
215
  /**
216
   * Constant representing Sunday.
217
   */
218
  public static final int SUNDAY = 1;
219
 
220
  /**
221
   * Constant representing Monday.
222
   */
223
  public static final int MONDAY = 2;
224
 
225
  /**
226
   * Constant representing Tuesday.
227
   */
228
  public static final int TUESDAY = 3;
229
 
230
  /**
231
   * Constant representing Wednesday.
232
   */
233
  public static final int WEDNESDAY = 4;
234
 
235
  /**
236
   * Constant representing Thursday.
237
   */
238
  public static final int THURSDAY = 5;
239
 
240
  /**
241
   * Constant representing Friday.
242
   */
243
  public static final int FRIDAY = 6;
244
 
245
  /**
246
   * Constant representing Saturday.
247
   */
248
  public static final int SATURDAY = 7;
249
 
250
  /**
251
   * Constant representing January.
252
   */
253
  public static final int JANUARY = 0;
254
 
255
  /**
256
   * Constant representing February.
257
   */
258
  public static final int FEBRUARY = 1;
259
 
260
  /**
261
   * Constant representing March.
262
   */
263
  public static final int MARCH = 2;
264
 
265
  /**
266
   * Constant representing April.
267
   */
268
  public static final int APRIL = 3;
269
 
270
  /**
271
   * Constant representing May.
272
   */
273
  public static final int MAY = 4;
274
 
275
  /**
276
   * Constant representing June.
277
   */
278
  public static final int JUNE = 5;
279
 
280
  /**
281
   * Constant representing July.
282
   */
283
  public static final int JULY = 6;
284
 
285
  /**
286
   * Constant representing August.
287
   */
288
  public static final int AUGUST = 7;
289
 
290
  /**
291
   * Constant representing September.
292
   */
293
  public static final int SEPTEMBER = 8;
294
 
295
  /**
296
   * Constant representing October.
297
   */
298
  public static final int OCTOBER = 9;
299
 
300
  /**
301
   * Constant representing November.
302
   */
303
  public static final int NOVEMBER = 10;
304
 
305
  /**
306
   * Constant representing December.
307
   */
308
  public static final int DECEMBER = 11;
309
 
310
  /**
311
   * Constant representing Undecimber. This is an artificial name useful
312
   * for lunar calendars.
313
   */
314
  public static final int UNDECIMBER = 12;
315
 
316
  /**
317
   * Useful constant for 12-hour clock.
318
   */
319
  public static final int AM = 0;
320
 
321
  /**
322
   * Useful constant for 12-hour clock.
323
   */
324
  public static final int PM = 1;
325
 
326
  /**
327
   * The time fields.  The array is indexed by the constants YEAR to
328
   * DST_OFFSET.
329
   * @serial
330
   */
331
  protected int[] fields = new int[FIELD_COUNT];
332
 
333
  /**
334
   * The flags which tell if the fields above have a value.
335
   * @serial
336
   */
337
  protected boolean[] isSet = new boolean[FIELD_COUNT];
338
 
339
  /**
340
   * The time in milliseconds since the epoch.
341
   * @serial
342
   */
343
  protected long time;
344
 
345
  /**
346
   * Tells if the above field has a valid value.
347
   * @serial
348
   */
349
  protected boolean isTimeSet;
350
 
351
  /**
352
   * Tells if the fields have a valid value.  This superseeds the isSet
353
   * array.
354
   * @serial
355
   */
356
  protected boolean areFieldsSet;
357
 
358
  /**
359
   * The time zone of this calendar.  Used by sub classes to do UTC / local
360
   * time conversion.  Sub classes can access this field with getTimeZone().
361
   * @serial
362
   */
363
  private TimeZone zone;
364
 
365
  /**
366
   * Specifies if the date/time interpretation should be lenient.
367
   * If the flag is set, a date such as "February 30, 1996" will be
368
   * treated as the 29th day after the February 1.  If this flag
369
   * is false, such dates will cause an exception.
370
   * @serial
371
   */
372
  private boolean lenient;
373
 
374
  /**
375
   * Sets what the first day of week is.  This is used for
376
   * WEEK_OF_MONTH and WEEK_OF_YEAR fields.
377
   * @serial
378
   */
379
  private int firstDayOfWeek;
380
 
381
  /**
382
   * Sets how many days are required in the first week of the year.
383
   * If the first day of the year should be the first week you should
384
   * set this value to 1.  If the first week must be a full week, set
385
   * it to 7.
386
   * @serial
387
   */
388
  private int minimalDaysInFirstWeek;
389
 
390
  /**
391
   * Is set to true if DST_OFFSET is explicitly set. In that case
392
   * it's value overrides the value computed from the current
393
   * time and the timezone.
394
   */
395
  private boolean explicitDSTOffset = false;
396
 
397
  /**
398
   * The version of the serialized data on the stream.
399
   * <dl><dt>0 or not present</dt>
400
   * <dd> JDK 1.1.5 or later.</dd>
401
   * <dt>1</dt>
402
   * <dd>JDK 1.1.6 or later.  This always writes a correct `time' value
403
   * on the stream, as well as the other fields, to be compatible with
404
   * earlier versions</dd></dl>
405
   * @since JDK1.1.6
406
   * @serial
407
   */
408
  private int serialVersionOnStream = 1;
409
 
410
  /**
411
   * XXX - I have not checked the compatibility.  The documentation of
412
   * the serialized-form is quite hairy...
413
   */
414
  static final long serialVersionUID = -1807547505821590642L;
415
 
416
  /**
417
   * The name of the resource bundle. Used only by getBundle()
418
   */
419
  private static final String bundleName = "gnu.java.locale.Calendar";
420
 
421
  /**
422
   * get resource bundle:
423
   * The resources should be loaded via this method only. Iff an application
424
   * uses this method, the resourcebundle is required.
425
   */
426
  private static ResourceBundle getBundle(Locale locale)
427
  {
428
    return ResourceBundle.getBundle(bundleName, locale,
429
                                    ClassLoader.getSystemClassLoader());
430
  }
431
 
432
  /**
433
   * Constructs a new Calendar with the default time zone and the default
434
   * locale.
435
   */
436
  protected Calendar()
437
  {
438
    this(TimeZone.getDefault(), Locale.getDefault());
439
  }
440
 
441
  /**
442
   * Constructs a new Calendar with the given time zone and the given
443
   * locale.
444
   * @param zone a time zone.
445
   * @param locale a locale.
446
   */
447
  protected Calendar(TimeZone zone, Locale locale)
448
  {
449
    this.zone = zone;
450
    lenient = true;
451
 
452
    ResourceBundle rb = getBundle(locale);
453
 
454
    firstDayOfWeek = ((Integer) rb.getObject("firstDayOfWeek")).intValue();
455
    minimalDaysInFirstWeek = ((Integer) rb.getObject("minimalDaysInFirstWeek"))
456
                             .intValue();
457
    clear();
458
  }
459
 
460
  /**
461
   * Creates a calendar representing the actual time, using the default
462
   * time zone and locale.
463
   */
464
  public static synchronized Calendar getInstance()
465
  {
466
    return getInstance(TimeZone.getDefault(), Locale.getDefault());
467
  }
468
 
469
  /**
470
   * Creates a calendar representing the actual time, using the given
471
   * time zone and the default locale.
472
   * @param zone a time zone.
473
   */
474
  public static synchronized Calendar getInstance(TimeZone zone)
475
  {
476
    return getInstance(zone, Locale.getDefault());
477
  }
478
 
479
  /**
480
   * Creates a calendar representing the actual time, using the default
481
   * time zone and the given locale.
482
   * @param locale a locale.
483
   */
484
  public static synchronized Calendar getInstance(Locale locale)
485
  {
486
    return getInstance(TimeZone.getDefault(), locale);
487
  }
488
 
489
  /**
490
   * Cache of locale->calendar-class mappings. This avoids having to do a ResourceBundle
491
   * lookup for every getInstance call.
492
   */
493
  private static HashMap cache = new HashMap();
494
 
495
  /** Preset argument types for calendar-class constructor lookup.  */
496
  private static Class[] ctorArgTypes = new Class[]
497
                                        {
498
                                          TimeZone.class, Locale.class
499
                                        };
500
 
501
  /**
502
   * Creates a calendar representing the actual time, using the given
503
   * time zone and locale.
504
   * @param zone a time zone.
505
   * @param locale a locale.
506
   */
507
  public static synchronized Calendar getInstance(TimeZone zone, Locale locale)
508
  {
509
    Class calendarClass = (Class) cache.get(locale);
510
    Throwable exception = null;
511
 
512
    try
513
      {
514
        if (calendarClass == null)
515
          {
516
            ResourceBundle rb = getBundle(locale);
517
            String calendarClassName = rb.getString("calendarClass");
518
 
519
            if (calendarClassName != null)
520
              {
521
                calendarClass = Class.forName(calendarClassName);
522
                if (Calendar.class.isAssignableFrom(calendarClass))
523
                  cache.put(locale, calendarClass);
524
              }
525
          }
526
 
527
        // GregorianCalendar is by far the most common case. Optimize by 
528
        // avoiding reflection.
529
        if (calendarClass == GregorianCalendar.class)
530
          return new GregorianCalendar(zone, locale);
531
 
532
        if (Calendar.class.isAssignableFrom(calendarClass))
533
          {
534
            Constructor ctor = calendarClass.getConstructor(ctorArgTypes);
535
            return (Calendar) ctor.newInstance(new Object[] { zone, locale });
536
          }
537
      }
538
    catch (ClassNotFoundException ex)
539
      {
540
        exception = ex;
541
      }
542
    catch (IllegalAccessException ex)
543
      {
544
        exception = ex;
545
      }
546
    catch (NoSuchMethodException ex)
547
      {
548
        exception = ex;
549
      }
550
    catch (InstantiationException ex)
551
      {
552
        exception = ex;
553
      }
554
    catch (InvocationTargetException ex)
555
      {
556
        exception = ex;
557
      }
558
 
559
    throw new RuntimeException("Error instantiating calendar for locale "
560
                               + locale, exception);
561
  }
562
 
563
  /**
564
   * Gets the set of locales for which a Calendar is available.
565
   * @exception MissingResourceException if locale data couldn't be found.
566
   * @return the set of locales.
567
   */
568
  public static synchronized Locale[] getAvailableLocales()
569
  {
570
    ResourceBundle rb = getBundle(new Locale("", ""));
571
    return (Locale[]) rb.getObject("availableLocales");
572
  }
573
 
574
  /**
575
   * Converts the time field values (<code>fields</code>) to
576
   * milliseconds since the epoch UTC (<code>time</code>).  Override
577
   * this method if you write your own Calendar.  */
578
  protected abstract void computeTime();
579
 
580
  /**
581
   * Converts the milliseconds since the epoch UTC
582
   * (<code>time</code>) to time fields
583
   * (<code>fields</code>). Override this method if you write your
584
   * own Calendar.
585
   */
586
  protected abstract void computeFields();
587
 
588
  /**
589
   * Converts the time represented by this object to a
590
   * <code>Date</code>-Object.
591
   * @return the Date.
592
   */
593
  public final Date getTime()
594
  {
595
    if (! isTimeSet)
596
      computeTime();
597
    return new Date(time);
598
  }
599
 
600
  /**
601
   * Sets this Calendar's time to the given Date.  All time fields
602
   * are invalidated by this method.
603
   */
604
  public final void setTime(Date date)
605
  {
606
    setTimeInMillis(date.getTime());
607
  }
608
 
609
  /**
610
   * Returns the time represented by this Calendar.
611
   * @return the time in milliseconds since the epoch.
612
   * @specnote This was made public in 1.4.
613
   */
614
  public long getTimeInMillis()
615
  {
616
    if (! isTimeSet)
617
      computeTime();
618
    return time;
619
  }
620
 
621
  /**
622
   * Sets this Calendar's time to the given Time.  All time fields
623
   * are invalidated by this method.
624
   * @param time the time in milliseconds since the epoch
625
   * @specnote This was made public in 1.4.
626
   */
627
  public void setTimeInMillis(long time)
628
  {
629
    clear();
630
    this.time = time;
631
    isTimeSet = true;
632
    computeFields();
633
  }
634
 
635
  /**
636
   * Gets the value of the specified field.  They are recomputed
637
   * if they are invalid.
638
   * @param field the time field. One of the time field constants.
639
   * @return the value of the specified field
640
   * @throws ArrayIndexOutOfBoundsException if the field is outside
641
   *         the valid range.  The value of field must be >= 0 and
642
   *         <= <code>FIELD_COUNT</code>.
643
   * @specnote Not final since JDK 1.4
644
   */
645
  public int get(int field)
646
  {
647
    // If the requested field is invalid, force all fields to be recomputed.
648
    if (! isSet[field])
649
      areFieldsSet = false;
650
    complete();
651
    return fields[field];
652
  }
653
 
654
  /**
655
   * Gets the value of the specified field. This method doesn't
656
   * recompute the fields, if they are invalid.
657
   * @param field the time field. One of the time field constants.
658
   * @return the value of the specified field, undefined if
659
   * <code>areFieldsSet</code> or <code>isSet[field]</code> is false.
660
   * @throws ArrayIndexOutOfBoundsException if the field is outside
661
   *         the valid range.  The value of field must be >= 0 and
662
   *         <= <code>FIELD_COUNT</code>.
663
   */
664
  protected final int internalGet(int field)
665
  {
666
    return fields[field];
667
  }
668
 
669
  /**
670
   * Sets the time field with the given value.  This does invalidate
671
   * the time in milliseconds.
672
   * @param field the time field. One of the time field constants
673
   * @param value the value to be set.
674
   * @throws ArrayIndexOutOfBoundsException if field is outside
675
   *         the valid range.  The value of field must be >= 0 and
676
   *         <= <code>FIELD_COUNT</code>.
677
   * @specnote Not final since JDK 1.4
678
   */
679
  public void set(int field, int value)
680
  {
681
    if (isTimeSet)
682
      for (int i = 0; i < FIELD_COUNT; i++)
683
        isSet[i] = false;
684
    isTimeSet = false;
685
    fields[field] = value;
686
    isSet[field] = true;
687
 
688
    // The five valid date patterns, in order of priority
689
    // 1  YEAR + MONTH + DAY_OF_MONTH
690
    // 2  YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
691
    // 3  YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
692
    // 4  YEAR + DAY_OF_YEAR
693
    // 5  YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
694
    switch (field)
695
      {
696
      case MONTH: // pattern 1,2 or 3
697
        isSet[DAY_OF_YEAR] = false;
698
        isSet[WEEK_OF_YEAR] = false;
699
        break;
700
      case DAY_OF_MONTH: // pattern 1
701
        isSet[YEAR] = true;
702
        isSet[MONTH] = true;
703
        isSet[WEEK_OF_MONTH] = true;
704
        isSet[DAY_OF_WEEK] = false;
705
        isSet[DAY_OF_WEEK_IN_MONTH] = false;
706
        isSet[DAY_OF_YEAR] = false;
707
        isSet[WEEK_OF_YEAR] = false;
708
        break;
709
      case WEEK_OF_MONTH: // pattern 2
710
        if (! isSet[DAY_OF_WEEK])
711
          fields[DAY_OF_WEEK] = getFirstDayOfWeek();
712
        isSet[YEAR] = true;
713
        isSet[MONTH] = true;
714
        isSet[DAY_OF_WEEK] = true;
715
        isSet[DAY_OF_MONTH] = false;
716
        isSet[DAY_OF_WEEK_IN_MONTH] = false;
717
        isSet[DAY_OF_YEAR] = false;
718
        isSet[WEEK_OF_YEAR] = false;
719
        break;
720
      case DAY_OF_WEEK_IN_MONTH: // pattern 3
721
        if (! isSet[DAY_OF_WEEK])
722
          fields[DAY_OF_WEEK] = getFirstDayOfWeek();
723
        isSet[YEAR] = true;
724
        isSet[MONTH] = true;
725
        isSet[DAY_OF_WEEK] = true;
726
        isSet[DAY_OF_YEAR] = false;
727
        isSet[DAY_OF_MONTH] = false;
728
        isSet[WEEK_OF_MONTH] = false;
729
        isSet[WEEK_OF_YEAR] = false;
730
        break;
731
      case DAY_OF_YEAR: // pattern 4
732
        isSet[YEAR] = true;
733
        isSet[MONTH] = false;
734
        isSet[WEEK_OF_MONTH] = false;
735
        isSet[DAY_OF_MONTH] = false;
736
        isSet[DAY_OF_WEEK] = false;
737
        isSet[WEEK_OF_YEAR] = false;
738
        isSet[DAY_OF_WEEK_IN_MONTH] = false;
739
        break;
740
      case WEEK_OF_YEAR: // pattern 5
741
        if (! isSet[DAY_OF_WEEK])
742
          fields[DAY_OF_WEEK] = getFirstDayOfWeek();
743
        isSet[YEAR] = true;
744
        isSet[DAY_OF_WEEK] = true;
745
        isSet[MONTH] = false;
746
        isSet[DAY_OF_MONTH] = false;
747
        isSet[WEEK_OF_MONTH] = false;
748
        isSet[DAY_OF_YEAR] = false;
749
        isSet[DAY_OF_WEEK_IN_MONTH] = false;
750
        break;
751
      case AM_PM:
752
        isSet[HOUR] = true;
753
        isSet[HOUR_OF_DAY] = false;
754
        break;
755
      case HOUR_OF_DAY:
756
        isSet[AM_PM] = false;
757
        isSet[HOUR] = false;
758
        break;
759
      case HOUR:
760
        isSet[AM_PM] = true;
761
        isSet[HOUR_OF_DAY] = false;
762
        break;
763
      case DST_OFFSET:
764
        explicitDSTOffset = true;
765
      }
766
 
767
    // May have crossed over a DST boundary.
768
    if (! explicitDSTOffset && (field != DST_OFFSET && field != ZONE_OFFSET))
769
      isSet[DST_OFFSET] = false;
770
  }
771
 
772
  /**
773
   * Sets the fields for year, month, and date
774
   * @param year the year.
775
   * @param month the month, one of the constants JANUARY..UNDICEMBER.
776
   * @param date the day of the month
777
   */
778
  public final void set(int year, int month, int date)
779
  {
780
    isTimeSet = false;
781
    fields[YEAR] = year;
782
    fields[MONTH] = month;
783
    fields[DATE] = date;
784
    isSet[YEAR] = isSet[MONTH] = isSet[DATE] = true;
785
    isSet[WEEK_OF_YEAR] = false;
786
    isSet[DAY_OF_YEAR] = false;
787
    isSet[WEEK_OF_MONTH] = false;
788
    isSet[DAY_OF_WEEK] = false;
789
    isSet[DAY_OF_WEEK_IN_MONTH] = false;
790
    isSet[ERA] = false;
791
 
792
    if (! explicitDSTOffset)
793
      isSet[DST_OFFSET] = false; // May have crossed a DST boundary.
794
  }
795
 
796
  /**
797
   * Sets the fields for year, month, date, hour, and minute
798
   * @param year the year.
799
   * @param month the month, one of the constants JANUARY..UNDICEMBER.
800
   * @param date the day of the month
801
   * @param hour the hour of day.
802
   * @param minute the minute.
803
   */
804
  public final void set(int year, int month, int date, int hour, int minute)
805
  {
806
    set(year, month, date);
807
    fields[HOUR_OF_DAY] = hour;
808
    fields[MINUTE] = minute;
809
    isSet[HOUR_OF_DAY] = isSet[MINUTE] = true;
810
    isSet[AM_PM] = false;
811
    isSet[HOUR] = false;
812
  }
813
 
814
  /**
815
   * Sets the fields for year, month, date, hour, and minute
816
   * @param year the year.
817
   * @param month the month, one of the constants JANUARY..UNDICEMBER.
818
   * @param date the day of the month
819
   * @param hour the hour of day.
820
   * @param minute the minute.
821
   * @param second the second.
822
   */
823
  public final void set(int year, int month, int date, int hour, int minute,
824
                        int second)
825
  {
826
    set(year, month, date, hour, minute);
827
    fields[SECOND] = second;
828
    isSet[SECOND] = true;
829
  }
830
 
831
  /**
832
   * Clears the values of all the time fields.
833
   */
834
  public final void clear()
835
  {
836
    isTimeSet = false;
837
    areFieldsSet = false;
838
    int zoneOffs = zone.getRawOffset();
839
    int[] tempFields =
840
                       {
841
                         1, 1970, JANUARY, 1, 1, 1, 1, THURSDAY, 1, AM, 0, 0, 0,
842
                         0, 0, zoneOffs, 0
843
                       };
844
    fields = tempFields;
845
    for (int i = 0; i < FIELD_COUNT; i++)
846
      isSet[i] = false;
847
  }
848
 
849
  /**
850
   * Clears the values of the specified time field.
851
   * @param field the time field. One of the time field constants.
852
   * @throws ArrayIndexOutOfBoundsException if field is outside
853
   *         the valid range.  The value of field must be >= 0 and
854
   *         <= <code>FIELD_COUNT</code>.
855
   */
856
  public final void clear(int field)
857
  {
858
    int[] tempFields =
859
                       {
860
                         1, 1970, JANUARY, 1, 1, 1, 1, THURSDAY, 1, AM, 0, 0, 0,
861
                         0, 0, zone.getRawOffset(), 0
862
                       };
863
    isTimeSet = false;
864
    areFieldsSet = false;
865
    isSet[field] = false;
866
    fields[field] = tempFields[field];
867
  }
868
 
869
  /**
870
   * Determines if the specified field has a valid value.
871
   * @return true if the specified field has a value.
872
   * @throws ArrayIndexOutOfBoundsException if the field is outside
873
   *         the valid range.  The value of field must be >= 0 and
874
   *         <= <code>FIELD_COUNT</code>.
875
   */
876
  public final boolean isSet(int field)
877
  {
878
    return isSet[field];
879
  }
880
 
881
  /**
882
   * Fills any unset fields in the time field list
883
   */
884
  protected void complete()
885
  {
886
    if (! isTimeSet)
887
      computeTime();
888
    if (! areFieldsSet)
889
      computeFields();
890
  }
891
 
892
  /**
893
   * Compares the given calendar with this.
894
   * @param o the object to that we should compare.
895
   * @return true, if the given object is a calendar, that represents
896
   * the same time (but doesn't necessary have the same fields).
897
   */
898
  public boolean equals(Object o)
899
  {
900
    if (! (o instanceof Calendar))
901
      return false;
902
    Calendar cal = (Calendar) o;
903
    if (getTimeInMillis() == ((Calendar) o).getTimeInMillis()
904
        && cal.getFirstDayOfWeek() == getFirstDayOfWeek()
905
        && cal.isLenient() == isLenient()
906
        && cal.getMinimalDaysInFirstWeek() == getMinimalDaysInFirstWeek())
907
      {
908
        TimeZone self = getTimeZone();
909
        TimeZone oth = cal.getTimeZone();
910
        return self == null ? oth == null : self.equals(oth);
911
      }
912
    return false;
913
  }
914
 
915
  /**
916
   * Returns a hash code for this calendar.
917
   * @return a hash code, which fullfits the general contract of
918
   * <code>hashCode()</code>
919
   */
920
  public int hashCode()
921
  {
922
    long time = getTimeInMillis();
923
    int val = (int) ((time & 0xffffffffL) ^ (time >> 32));
924
    val += (getFirstDayOfWeek() + (isLenient() ? 1230 : 1237)
925
            + getMinimalDaysInFirstWeek());
926
    TimeZone self = getTimeZone();
927
    if (self != null)
928
      val ^= self.hashCode();
929
    return val;
930
  }
931
 
932
  /**
933
   * Compares the given calendar with this.
934
   * @param o the object to that we should compare.
935
   * @return true, if the given object is a calendar, and this calendar
936
   * represents a smaller time than the calendar o.
937
   * @exception ClassCastException if o is not an calendar.
938
   * @since JDK1.2 you don't need to override this method
939
   */
940
  public boolean before(Object o)
941
  {
942
    return getTimeInMillis() < ((Calendar) o).getTimeInMillis();
943
  }
944
 
945
  /**
946
   * Compares the given calendar with this.
947
   * @param o the object to that we should compare.
948
   * @return true, if the given object is a calendar, and this calendar
949
   * represents a bigger time than the calendar o.
950
   * @exception ClassCastException if o is not an calendar.
951
   * @since JDK1.2 you don't need to override this method
952
   */
953
  public boolean after(Object o)
954
  {
955
    return getTimeInMillis() > ((Calendar) o).getTimeInMillis();
956
  }
957
 
958
  /**
959
   * Adds the specified amount of time to the given time field.  The
960
   * amount may be negative to subtract the time.  If the field overflows
961
   * it does what you expect: Jan, 25 + 10 Days is Feb, 4.
962
   * @param field the time field. One of the time field constants.
963
   * @param amount the amount of time.
964
   * @throws ArrayIndexOutOfBoundsException if the field is outside
965
   *         the valid range.  The value of field must be >= 0 and
966
   *         <= <code>FIELD_COUNT</code>.
967
   */
968
  public abstract void add(int field, int amount);
969
 
970
  /**
971
   * Rolls the specified time field up or down.  This means add one
972
   * to the specified field, but don't change the other fields.  If
973
   * the maximum for this field is reached, start over with the
974
   * minimum value.  <br>
975
   *
976
   * <strong>Note:</strong> There may be situation, where the other
977
   * fields must be changed, e.g rolling the month on May, 31.
978
   * The date June, 31 is automatically converted to July, 1.
979
   * @param field the time field. One of the time field constants.
980
   * @param up the direction, true for up, false for down.
981
   * @throws ArrayIndexOutOfBoundsException if the field is outside
982
   *         the valid range.  The value of field must be >= 0 and
983
   *         <= <code>FIELD_COUNT</code>.
984
   */
985
  public abstract void roll(int field, boolean up);
986
 
987
  /**
988
   * Rolls up or down the specified time field by the given amount.
989
   * A negative amount rolls down.  The default implementation is
990
   * call <code>roll(int, boolean)</code> for the specified amount.
991
   *
992
   * Subclasses should override this method to do more intuitiv things.
993
   *
994
   * @param field the time field. One of the time field constants.
995
   * @param amount the amount to roll by, positive for rolling up,
996
   * negative for rolling down.
997
   * @throws ArrayIndexOutOfBoundsException if the field is outside
998
   *         the valid range.  The value of field must be >= 0 and
999
   *         <= <code>FIELD_COUNT</code>.
1000
   * @since JDK1.2
1001
   */
1002
  public void roll(int field, int amount)
1003
  {
1004
    while (amount > 0)
1005
      {
1006
        roll(field, true);
1007
        amount--;
1008
      }
1009
    while (amount < 0)
1010
      {
1011
        roll(field, false);
1012
        amount++;
1013
      }
1014
  }
1015
 
1016
  /**
1017
   * Sets the time zone to the specified value.
1018
   * @param zone the new time zone
1019
   */
1020
  public void setTimeZone(TimeZone zone)
1021
  {
1022
    this.zone = zone;
1023
  }
1024
 
1025
  /**
1026
   * Gets the time zone of this calendar
1027
   * @return the current time zone.
1028
   */
1029
  public TimeZone getTimeZone()
1030
  {
1031
    return zone;
1032
  }
1033
 
1034
  /**
1035
   * Specifies if the date/time interpretation should be lenient.
1036
   * If the flag is set, a date such as "February 30, 1996" will be
1037
   * treated as the 29th day after the February 1.  If this flag
1038
   * is false, such dates will cause an exception.
1039
   * @param lenient true, if the date should be interpreted linient,
1040
   * false if it should be interpreted strict.
1041
   */
1042
  public void setLenient(boolean lenient)
1043
  {
1044
    this.lenient = lenient;
1045
  }
1046
 
1047
  /**
1048
   * Tells if the date/time interpretation is lenient.
1049
   * @return true, if the date should be interpreted linient,
1050
   * false if it should be interpreted strict.
1051
   */
1052
  public boolean isLenient()
1053
  {
1054
    return lenient;
1055
  }
1056
 
1057
  /**
1058
   * Sets what the first day of week is.  This is used for
1059
   * WEEK_OF_MONTH and WEEK_OF_YEAR fields.
1060
   * @param value the first day of week.  One of SUNDAY to SATURDAY.
1061
   */
1062
  public void setFirstDayOfWeek(int value)
1063
  {
1064
    firstDayOfWeek = value;
1065
  }
1066
 
1067
  /**
1068
   * Gets what the first day of week is.  This is used for
1069
   * WEEK_OF_MONTH and WEEK_OF_YEAR fields.
1070
   * @return the first day of week.  One of SUNDAY to SATURDAY.
1071
   */
1072
  public int getFirstDayOfWeek()
1073
  {
1074
    return firstDayOfWeek;
1075
  }
1076
 
1077
  /**
1078
   * Sets how many days are required in the first week of the year.
1079
   * If the first day of the year should be the first week you should
1080
   * set this value to 1.  If the first week must be a full week, set
1081
   * it to 7.
1082
   * @param value the minimal days required in the first week.
1083
   */
1084
  public void setMinimalDaysInFirstWeek(int value)
1085
  {
1086
    minimalDaysInFirstWeek = value;
1087
  }
1088
 
1089
  /**
1090
   * Gets how many days are required in the first week of the year.
1091
   * @return the minimal days required in the first week.
1092
   * @see #setMinimalDaysInFirstWeek
1093
   */
1094
  public int getMinimalDaysInFirstWeek()
1095
  {
1096
    return minimalDaysInFirstWeek;
1097
  }
1098
 
1099
  /**
1100
   * Gets the smallest value that is allowed for the specified field.
1101
   * @param field the time field. One of the time field constants.
1102
   * @return the smallest value.
1103
   */
1104
  public abstract int getMinimum(int field);
1105
 
1106
  /**
1107
   * Gets the biggest value that is allowed for the specified field.
1108
   * @param field the time field. One of the time field constants.
1109
   * @return the biggest value.
1110
   */
1111
  public abstract int getMaximum(int field);
1112
 
1113
  /**
1114
   * Gets the greatest minimum value that is allowed for the specified field.
1115
   * @param field the time field. One of the time field constants.
1116
   * @return the greatest minimum value.
1117
   */
1118
  public abstract int getGreatestMinimum(int field);
1119
 
1120
  /**
1121
   * Gets the smallest maximum value that is allowed for the
1122
   * specified field.  For example this is 28 for DAY_OF_MONTH.
1123
   * @param field the time field. One of the time field constants.
1124
   * @return the least maximum value.
1125
   */
1126
  public abstract int getLeastMaximum(int field);
1127
 
1128
  /**
1129
   * Gets the actual minimum value that is allowed for the specified field.
1130
   * This value is dependent on the values of the other fields.
1131
   * @param field the time field. One of the time field constants.
1132
   * @return the actual minimum value.
1133
   * @throws ArrayIndexOutOfBoundsException if the field is outside
1134
   *         the valid range.  The value of field must be >= 0 and
1135
   *         <= <code>FIELD_COUNT</code>.
1136
   * @since jdk1.2
1137
   */
1138
  public int getActualMinimum(int field)
1139
  {
1140
    Calendar tmp = (Calendar) clone(); // To avoid restoring state
1141
    int min = tmp.getGreatestMinimum(field);
1142
    int end = tmp.getMinimum(field);
1143
    tmp.set(field, min);
1144
    for (; min > end; min--)
1145
      {
1146
        tmp.add(field, -1); // Try to get smaller
1147
        if (tmp.get(field) != min - 1)
1148
          break; // Done if not successful
1149
      }
1150
    return min;
1151
  }
1152
 
1153
  /**
1154
   * Gets the actual maximum value that is allowed for the specified field.
1155
   * This value is dependent on the values of the other fields.
1156
   * @param field the time field. One of the time field constants.
1157
   * @return the actual maximum value.
1158
   * @throws ArrayIndexOutOfBoundsException if the field is outside
1159
   *         the valid range.  The value of field must be >= 0 and
1160
   *         <= <code>FIELD_COUNT</code>.
1161
   * @since jdk1.2
1162
   */
1163
  public int getActualMaximum(int field)
1164
  {
1165
    Calendar tmp = (Calendar) clone(); // To avoid restoring state
1166
    int max = tmp.getLeastMaximum(field);
1167
    int end = tmp.getMaximum(field);
1168
    tmp.set(field, max);
1169
    for (; max < end; max++)
1170
      {
1171
        tmp.add(field, 1);
1172
        if (tmp.get(field) != max + 1)
1173
          break;
1174
      }
1175
    return max;
1176
  }
1177
 
1178
  /**
1179
   * Return a clone of this object.
1180
   */
1181
  public Object clone()
1182
  {
1183
    try
1184
      {
1185
        Calendar cal = (Calendar) super.clone();
1186
        cal.fields = (int[]) fields.clone();
1187
        cal.isSet = (boolean[]) isSet.clone();
1188
        return cal;
1189
      }
1190
    catch (CloneNotSupportedException ex)
1191
      {
1192
        return null;
1193
      }
1194
  }
1195
 
1196
  private static final String[] fieldNames =
1197
                                             {
1198
                                               ",ERA=", ",YEAR=", ",MONTH=",
1199
                                               ",WEEK_OF_YEAR=",
1200
                                               ",WEEK_OF_MONTH=",
1201
                                               ",DAY_OF_MONTH=",
1202
                                               ",DAY_OF_YEAR=", ",DAY_OF_WEEK=",
1203
                                               ",DAY_OF_WEEK_IN_MONTH=",
1204
                                               ",AM_PM=", ",HOUR=",
1205
                                               ",HOUR_OF_DAY=", ",MINUTE=",
1206
                                               ",SECOND=", ",MILLISECOND=",
1207
                                               ",ZONE_OFFSET=", ",DST_OFFSET="
1208
                                             };
1209
 
1210
  /**
1211
   * Returns a string representation of this object.  It is mainly
1212
   * for debugging purposes and its content is implementation
1213
   * specific.
1214
   */
1215
  public String toString()
1216
  {
1217
    StringBuffer sb = new StringBuffer();
1218
    sb.append(getClass().getName()).append('[');
1219
    sb.append("time=");
1220
    if (isTimeSet)
1221
      sb.append(time);
1222
    else
1223
      sb.append("?");
1224
    sb.append(",zone=" + zone);
1225
    sb.append(",areFieldsSet=" + areFieldsSet);
1226
    for (int i = 0; i < FIELD_COUNT; i++)
1227
      {
1228
        sb.append(fieldNames[i]);
1229
        if (isSet[i])
1230
          sb.append(fields[i]);
1231
        else
1232
          sb.append("?");
1233
      }
1234
    sb.append(",lenient=").append(lenient);
1235
    sb.append(",firstDayOfWeek=").append(firstDayOfWeek);
1236
    sb.append(",minimalDaysInFirstWeek=").append(minimalDaysInFirstWeek);
1237
    sb.append("]");
1238
    return sb.toString();
1239
  }
1240
 
1241
  /**
1242
   * Saves the state of the object to the stream.  Ideally we would
1243
   * only write the time field, but we need to be compatible with
1244
   * earlier versions. <br>
1245
   *
1246
   * This doesn't write the JDK1.1 field nextStamp to the stream, as
1247
   * I don't know what it is good for, and because the documentation
1248
   * says, that it could be omitted.  */
1249
  private void writeObject(ObjectOutputStream stream) throws IOException
1250
  {
1251
    if (! isTimeSet)
1252
      computeTime();
1253
    stream.defaultWriteObject();
1254
  }
1255
 
1256
  /**
1257
   * Reads the object back from stream (deserialization).
1258
   */
1259
  private void readObject(ObjectInputStream stream)
1260
    throws IOException, ClassNotFoundException
1261
  {
1262
    stream.defaultReadObject();
1263
    if (! isTimeSet)
1264
      computeTime();
1265
 
1266
    if (serialVersionOnStream > 1)
1267
      {
1268
        // This is my interpretation of the serial number:
1269
        // Sun wants to remove all fields from the stream someday
1270
        // and will then increase the serialVersion number again.
1271
        // We prepare to be compatible.
1272
        fields = new int[FIELD_COUNT];
1273
        isSet = new boolean[FIELD_COUNT];
1274
        areFieldsSet = false;
1275
      }
1276
  }
1277
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.