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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [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
   * This is the default calendar class, that is returned on
367
   * java.util.Calendar.getInstance().
368
   * XXX - this isn't localized anywhere, is it?
369
   * @see java.util.Calendar#getInstance()
370
   */
371
  private static final String calendarClassName = "java.util.GregorianCalendar";
372
 
373
  /**
374
   * Specifies if the date/time interpretation should be lenient.
375
   * If the flag is set, a date such as "February 30, 1996" will be
376
   * treated as the 29th day after the February 1.  If this flag
377
   * is false, such dates will cause an exception.
378
   * @serial
379
   */
380
  private boolean lenient;
381
 
382
  /**
383
   * Sets what the first day of week is.  This is used for
384
   * WEEK_OF_MONTH and WEEK_OF_YEAR fields.
385
   * @serial
386
   */
387
  private int firstDayOfWeek;
388
 
389
  /**
390
   * Sets how many days are required in the first week of the year.
391
   * If the first day of the year should be the first week you should
392
   * set this value to 1.  If the first week must be a full week, set
393
   * it to 7.
394
   * @serial
395
   */
396
  private int minimalDaysInFirstWeek;
397
 
398
  /**
399
   * Is set to true if DST_OFFSET is explicitly set. In that case
400
   * it's value overrides the value computed from the current
401
   * time and the timezone.
402
   */
403
  private boolean explicitDSTOffset = false;
404
 
405
  /**
406
   * The version of the serialized data on the stream.
407
   * <dl><dt>0 or not present</dt>
408
   * <dd> JDK 1.1.5 or later.</dd>
409
   * <dt>1</dt>
410
   * <dd>JDK 1.1.6 or later.  This always writes a correct `time' value
411
   * on the stream, as well as the other fields, to be compatible with
412
   * earlier versions</dd></dl>
413
   * @since JDK1.1.6
414
   * @serial
415
   */
416
  private int serialVersionOnStream = 1;
417
 
418
  /**
419
   * XXX - I have not checked the compatibility.  The documentation of
420
   * the serialized-form is quite hairy...
421
   */
422
  static final long serialVersionUID = -1807547505821590642L;
423
 
424
  /**
425
   * The name of the resource bundle. Used only by getBundle()
426
   */
427
  private static final String bundleName = "gnu.java.locale.LocaleInformation";
428
 
429
  /**
430
   * get resource bundle:
431
   * The resources should be loaded via this method only. Iff an application
432
   * uses this method, the resourcebundle is required.
433
   */
434
  private static ResourceBundle getBundle(Locale locale)
435
  {
436
    return ResourceBundle.getBundle(bundleName, locale,
437
                                    ClassLoader.getSystemClassLoader());
438
  }
439
 
440
  /**
441
   * Constructs a new Calendar with the default time zone and the default
442
   * locale.
443
   */
444
  protected Calendar()
445
  {
446
    this(TimeZone.getDefault(), Locale.getDefault());
447
  }
448
 
449
  /**
450
   * Constructs a new Calendar with the given time zone and the given
451
   * locale.
452
   * @param zone a time zone.
453
   * @param locale a locale.
454
   */
455
  protected Calendar(TimeZone zone, Locale locale)
456
  {
457
    this.zone = zone;
458
    lenient = true;
459
    String[] days = { "", "sun", "mon", "tue", "wed", "thu", "fri", "sat" };
460
 
461
    ResourceBundle rb = getBundle(locale);
462
    String min = (String) rb.getObject("minNumberOfDaysInFirstWeek");
463
    String first = (String) rb.getObject("firstDayOfWeek");
464
    try
465
      {
466
        if (min != null)
467
          minimalDaysInFirstWeek = Integer.parseInt(min);
468
      }
469
    catch (NumberFormatException ex)
470
      {
471
        minimalDaysInFirstWeek = 1;
472
      }
473
 
474
    firstDayOfWeek = 1;
475
    if (first != null)
476
      for (int i = 0; i < 8; i++)
477
        if (days[i].equals(first))
478
          firstDayOfWeek = i;
479
 
480
    clear();
481
  }
482
 
483
  /**
484
   * Creates a calendar representing the actual time, using the default
485
   * time zone and locale.
486
   */
487
  public static synchronized Calendar getInstance()
488
  {
489
    return getInstance(TimeZone.getDefault(), Locale.getDefault());
490
  }
491
 
492
  /**
493
   * Creates a calendar representing the actual time, using the given
494
   * time zone and the default locale.
495
   * @param zone a time zone.
496
   */
497
  public static synchronized Calendar getInstance(TimeZone zone)
498
  {
499
    return getInstance(zone, Locale.getDefault());
500
  }
501
 
502
  /**
503
   * Creates a calendar representing the actual time, using the default
504
   * time zone and the given locale.
505
   * @param locale a locale.
506
   */
507
  public static synchronized Calendar getInstance(Locale locale)
508
  {
509
    return getInstance(TimeZone.getDefault(), locale);
510
  }
511
 
512
  /**
513
   * Cache of locale->calendar-class mappings. This avoids having to do a ResourceBundle
514
   * lookup for every getInstance call.
515
   */
516
  private static HashMap cache = new HashMap();
517
 
518
  /** Preset argument types for calendar-class constructor lookup.  */
519
  private static Class[] ctorArgTypes = new Class[]
520
                                        {
521
                                          TimeZone.class, Locale.class
522
                                        };
523
 
524
  /**
525
   * Creates a calendar representing the actual time, using the given
526
   * time zone and locale.
527
   * @param zone a time zone.
528
   * @param locale a locale.
529
   */
530
  public static synchronized Calendar getInstance(TimeZone zone, Locale locale)
531
  {
532
    Class calendarClass = (Class) cache.get(locale);
533
    Throwable exception = null;
534
 
535
    try
536
      {
537
        if (calendarClass == null)
538
          {
539
            calendarClass = Class.forName(calendarClassName);
540
            if (Calendar.class.isAssignableFrom(calendarClass))
541
              cache.put(locale, calendarClass);
542
          }
543
 
544
        // GregorianCalendar is by far the most common case. Optimize by 
545
        // avoiding reflection.
546
        if (calendarClass == GregorianCalendar.class)
547
          return new GregorianCalendar(zone, locale);
548
 
549
        if (Calendar.class.isAssignableFrom(calendarClass))
550
          {
551
            Constructor ctor = calendarClass.getConstructor(ctorArgTypes);
552
            return (Calendar) ctor.newInstance(new Object[] { zone, locale });
553
          }
554
      }
555
    catch (ClassNotFoundException ex)
556
      {
557
        exception = ex;
558
      }
559
    catch (IllegalAccessException ex)
560
      {
561
        exception = ex;
562
      }
563
    catch (NoSuchMethodException ex)
564
      {
565
        exception = ex;
566
      }
567
    catch (InstantiationException ex)
568
      {
569
        exception = ex;
570
      }
571
    catch (InvocationTargetException ex)
572
      {
573
        exception = ex;
574
      }
575
 
576
    throw new RuntimeException("Error instantiating calendar for locale "
577
                               + locale, exception);
578
  }
579
 
580
  /**
581
   * Gets the set of locales for which a Calendar is available.
582
   * @exception MissingResourceException if locale data couldn't be found.
583
   * @return the set of locales.
584
   */
585
  public static synchronized Locale[] getAvailableLocales()
586
  {
587
    ResourceBundle rb = getBundle(new Locale("", ""));
588
    return (Locale[]) rb.getObject("availableLocales");
589
  }
590
 
591
  /**
592
   * Converts the time field values (<code>fields</code>) to
593
   * milliseconds since the epoch UTC (<code>time</code>).  Override
594
   * this method if you write your own Calendar.  */
595
  protected abstract void computeTime();
596
 
597
  /**
598
   * Converts the milliseconds since the epoch UTC
599
   * (<code>time</code>) to time fields
600
   * (<code>fields</code>). Override this method if you write your
601
   * own Calendar.
602
   */
603
  protected abstract void computeFields();
604
 
605
  /**
606
   * Converts the time represented by this object to a
607
   * <code>Date</code>-Object.
608
   * @return the Date.
609
   */
610
  public final Date getTime()
611
  {
612
    if (! isTimeSet)
613
      computeTime();
614
    return new Date(time);
615
  }
616
 
617
  /**
618
   * Sets this Calendar's time to the given Date.  All time fields
619
   * are invalidated by this method.
620
   */
621
  public final void setTime(Date date)
622
  {
623
    setTimeInMillis(date.getTime());
624
  }
625
 
626
  /**
627
   * Returns the time represented by this Calendar.
628
   * @return the time in milliseconds since the epoch.
629
   * @specnote This was made public in 1.4.
630
   */
631
  public long getTimeInMillis()
632
  {
633
    if (! isTimeSet)
634
      computeTime();
635
    return time;
636
  }
637
 
638
  /**
639
   * Sets this Calendar's time to the given Time.  All time fields
640
   * are invalidated by this method.
641
   * @param time the time in milliseconds since the epoch
642
   * @specnote This was made public in 1.4.
643
   */
644
  public void setTimeInMillis(long time)
645
  {
646
    clear();
647
    this.time = time;
648
    isTimeSet = true;
649
    computeFields();
650
  }
651
 
652
  /**
653
   * Gets the value of the specified field.  They are recomputed
654
   * if they are invalid.
655
   * @param field the time field. One of the time field constants.
656
   * @return the value of the specified field
657
   * @throws ArrayIndexOutOfBoundsException if the field is outside
658
   *         the valid range.  The value of field must be >= 0 and
659
   *         <= <code>FIELD_COUNT</code>.
660
   * @specnote Not final since JDK 1.4
661
   */
662
  public int get(int field)
663
  {
664
    // If the requested field is invalid, force all fields to be recomputed.
665
    if (! isSet[field])
666
      areFieldsSet = false;
667
    complete();
668
    return fields[field];
669
  }
670
 
671
  /**
672
   * Gets the value of the specified field. This method doesn't
673
   * recompute the fields, if they are invalid.
674
   * @param field the time field. One of the time field constants.
675
   * @return the value of the specified field, undefined if
676
   * <code>areFieldsSet</code> or <code>isSet[field]</code> is false.
677
   * @throws ArrayIndexOutOfBoundsException if the field is outside
678
   *         the valid range.  The value of field must be >= 0 and
679
   *         <= <code>FIELD_COUNT</code>.
680
   */
681
  protected final int internalGet(int field)
682
  {
683
    return fields[field];
684
  }
685
 
686
  /**
687
   * Sets the time field with the given value.  This does invalidate
688
   * the time in milliseconds.
689
   * @param field the time field. One of the time field constants
690
   * @param value the value to be set.
691
   * @throws ArrayIndexOutOfBoundsException if field is outside
692
   *         the valid range.  The value of field must be >= 0 and
693
   *         <= <code>FIELD_COUNT</code>.
694
   * @specnote Not final since JDK 1.4
695
   */
696
  public void set(int field, int value)
697
  {
698
    if (isTimeSet)
699
      for (int i = 0; i < FIELD_COUNT; i++)
700
        isSet[i] = false;
701
    isTimeSet = false;
702
    fields[field] = value;
703
    isSet[field] = true;
704
 
705
    // The five valid date patterns, in order of priority
706
    // 1  YEAR + MONTH + DAY_OF_MONTH
707
    // 2  YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
708
    // 3  YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
709
    // 4  YEAR + DAY_OF_YEAR
710
    // 5  YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
711
    switch (field)
712
      {
713
      case MONTH: // pattern 1,2 or 3
714
        isSet[DAY_OF_YEAR] = false;
715
        isSet[WEEK_OF_YEAR] = false;
716
        break;
717
      case DAY_OF_MONTH: // pattern 1
718
        isSet[YEAR] = true;
719
        isSet[MONTH] = true;
720
        isSet[WEEK_OF_MONTH] = true;
721
        isSet[DAY_OF_WEEK] = false;
722
        isSet[DAY_OF_WEEK_IN_MONTH] = false;
723
        isSet[DAY_OF_YEAR] = false;
724
        isSet[WEEK_OF_YEAR] = false;
725
        break;
726
      case WEEK_OF_MONTH: // pattern 2
727
        if (! isSet[DAY_OF_WEEK])
728
          fields[DAY_OF_WEEK] = getFirstDayOfWeek();
729
        isSet[YEAR] = true;
730
        isSet[MONTH] = true;
731
        isSet[DAY_OF_WEEK] = true;
732
        isSet[DAY_OF_MONTH] = false;
733
        isSet[DAY_OF_WEEK_IN_MONTH] = false;
734
        isSet[DAY_OF_YEAR] = false;
735
        isSet[WEEK_OF_YEAR] = false;
736
        break;
737
      case DAY_OF_WEEK_IN_MONTH: // pattern 3
738
        if (! isSet[DAY_OF_WEEK])
739
          fields[DAY_OF_WEEK] = getFirstDayOfWeek();
740
        isSet[YEAR] = true;
741
        isSet[MONTH] = true;
742
        isSet[DAY_OF_WEEK] = true;
743
        isSet[DAY_OF_YEAR] = false;
744
        isSet[DAY_OF_MONTH] = false;
745
        isSet[WEEK_OF_MONTH] = false;
746
        isSet[WEEK_OF_YEAR] = false;
747
        break;
748
      case DAY_OF_YEAR: // pattern 4
749
        isSet[YEAR] = true;
750
        isSet[MONTH] = false;
751
        isSet[WEEK_OF_MONTH] = false;
752
        isSet[DAY_OF_MONTH] = false;
753
        isSet[DAY_OF_WEEK] = false;
754
        isSet[WEEK_OF_YEAR] = false;
755
        isSet[DAY_OF_WEEK_IN_MONTH] = false;
756
        break;
757
      case WEEK_OF_YEAR: // pattern 5
758
        if (! isSet[DAY_OF_WEEK])
759
          fields[DAY_OF_WEEK] = getFirstDayOfWeek();
760
        isSet[YEAR] = true;
761
        isSet[DAY_OF_WEEK] = true;
762
        isSet[MONTH] = false;
763
        isSet[DAY_OF_MONTH] = false;
764
        isSet[WEEK_OF_MONTH] = false;
765
        isSet[DAY_OF_YEAR] = false;
766
        isSet[DAY_OF_WEEK_IN_MONTH] = false;
767
        break;
768
      case AM_PM:
769
        isSet[HOUR] = true;
770
        isSet[HOUR_OF_DAY] = false;
771
        break;
772
      case HOUR_OF_DAY:
773
        isSet[AM_PM] = false;
774
        isSet[HOUR] = false;
775
        break;
776
      case HOUR:
777
        isSet[AM_PM] = true;
778
        isSet[HOUR_OF_DAY] = false;
779
        break;
780
      case DST_OFFSET:
781
        explicitDSTOffset = true;
782
      }
783
 
784
    // May have crossed over a DST boundary.
785
    if (! explicitDSTOffset && (field != DST_OFFSET && field != ZONE_OFFSET))
786
      isSet[DST_OFFSET] = false;
787
  }
788
 
789
  /**
790
   * Sets the fields for year, month, and date
791
   * @param year the year.
792
   * @param month the month, one of the constants JANUARY..UNDICEMBER.
793
   * @param date the day of the month
794
   */
795
  public final void set(int year, int month, int date)
796
  {
797
    isTimeSet = false;
798
    fields[YEAR] = year;
799
    fields[MONTH] = month;
800
    fields[DATE] = date;
801
    isSet[YEAR] = isSet[MONTH] = isSet[DATE] = true;
802
    isSet[WEEK_OF_YEAR] = false;
803
    isSet[DAY_OF_YEAR] = false;
804
    isSet[WEEK_OF_MONTH] = false;
805
    isSet[DAY_OF_WEEK] = false;
806
    isSet[DAY_OF_WEEK_IN_MONTH] = false;
807
    isSet[ERA] = false;
808
 
809
    if (! explicitDSTOffset)
810
      isSet[DST_OFFSET] = false; // May have crossed a DST boundary.
811
  }
812
 
813
  /**
814
   * Sets the fields for year, month, date, hour, and minute
815
   * @param year the year.
816
   * @param month the month, one of the constants JANUARY..UNDICEMBER.
817
   * @param date the day of the month
818
   * @param hour the hour of day.
819
   * @param minute the minute.
820
   */
821
  public final void set(int year, int month, int date, int hour, int minute)
822
  {
823
    set(year, month, date);
824
    fields[HOUR_OF_DAY] = hour;
825
    fields[MINUTE] = minute;
826
    isSet[HOUR_OF_DAY] = isSet[MINUTE] = true;
827
    isSet[AM_PM] = false;
828
    isSet[HOUR] = false;
829
  }
830
 
831
  /**
832
   * Sets the fields for year, month, date, hour, and minute
833
   * @param year the year.
834
   * @param month the month, one of the constants JANUARY..UNDICEMBER.
835
   * @param date the day of the month
836
   * @param hour the hour of day.
837
   * @param minute the minute.
838
   * @param second the second.
839
   */
840
  public final void set(int year, int month, int date, int hour, int minute,
841
                        int second)
842
  {
843
    set(year, month, date, hour, minute);
844
    fields[SECOND] = second;
845
    isSet[SECOND] = true;
846
  }
847
 
848
  /**
849
   * Clears the values of all the time fields.
850
   */
851
  public final void clear()
852
  {
853
    isTimeSet = false;
854
    areFieldsSet = false;
855
    int zoneOffs = zone.getRawOffset();
856
    int[] tempFields =
857
                       {
858
                         1, 1970, JANUARY, 1, 1, 1, 1, THURSDAY, 1, AM, 0, 0, 0,
859
                         0, 0, zoneOffs, 0
860
                       };
861
    fields = tempFields;
862
    for (int i = 0; i < FIELD_COUNT; i++)
863
      isSet[i] = false;
864
  }
865
 
866
  /**
867
   * Clears the values of the specified time field.
868
   * @param field the time field. One of the time field constants.
869
   * @throws ArrayIndexOutOfBoundsException if field is outside
870
   *         the valid range.  The value of field must be >= 0 and
871
   *         <= <code>FIELD_COUNT</code>.
872
   */
873
  public final void clear(int field)
874
  {
875
    int[] tempFields =
876
                       {
877
                         1, 1970, JANUARY, 1, 1, 1, 1, THURSDAY, 1, AM, 0, 0, 0,
878
                         0, 0, zone.getRawOffset(), 0
879
                       };
880
    isTimeSet = false;
881
    areFieldsSet = false;
882
    isSet[field] = false;
883
    fields[field] = tempFields[field];
884
  }
885
 
886
  /**
887
   * Determines if the specified field has a valid value.
888
   * @return true if the specified field has a value.
889
   * @throws ArrayIndexOutOfBoundsException if the field is outside
890
   *         the valid range.  The value of field must be >= 0 and
891
   *         <= <code>FIELD_COUNT</code>.
892
   */
893
  public final boolean isSet(int field)
894
  {
895
    return isSet[field];
896
  }
897
 
898
  /**
899
   * Fills any unset fields in the time field list
900
   */
901
  protected void complete()
902
  {
903
    if (! isTimeSet)
904
      computeTime();
905
    if (! areFieldsSet)
906
      computeFields();
907
  }
908
 
909
  /**
910
   * Compares the given calendar with this.
911
   * @param o the object to that we should compare.
912
   * @return true, if the given object is a calendar, that represents
913
   * the same time (but doesn't necessary have the same fields).
914
   */
915
  public boolean equals(Object o)
916
  {
917
    if (! (o instanceof Calendar))
918
      return false;
919
    Calendar cal = (Calendar) o;
920
    if (getTimeInMillis() == ((Calendar) o).getTimeInMillis()
921
        && cal.getFirstDayOfWeek() == getFirstDayOfWeek()
922
        && cal.isLenient() == isLenient()
923
        && cal.getMinimalDaysInFirstWeek() == getMinimalDaysInFirstWeek())
924
      {
925
        TimeZone self = getTimeZone();
926
        TimeZone oth = cal.getTimeZone();
927
        return self == null ? oth == null : self.equals(oth);
928
      }
929
    return false;
930
  }
931
 
932
  /**
933
   * Returns a hash code for this calendar.
934
   * @return a hash code, which fullfits the general contract of
935
   * <code>hashCode()</code>
936
   */
937
  public int hashCode()
938
  {
939
    long time = getTimeInMillis();
940
    int val = (int) ((time & 0xffffffffL) ^ (time >> 32));
941
    val += (getFirstDayOfWeek() + (isLenient() ? 1230 : 1237)
942
            + getMinimalDaysInFirstWeek());
943
    TimeZone self = getTimeZone();
944
    if (self != null)
945
      val ^= self.hashCode();
946
    return val;
947
  }
948
 
949
  /**
950
   * Compares the given calendar with this.
951
   * @param o the object to that we should compare.
952
   * @return true, if the given object is a calendar, and this calendar
953
   * represents a smaller time than the calendar o.
954
   * @exception ClassCastException if o is not an calendar.
955
   * @since JDK1.2 you don't need to override this method
956
   */
957
  public boolean before(Object o)
958
  {
959
    return getTimeInMillis() < ((Calendar) o).getTimeInMillis();
960
  }
961
 
962
  /**
963
   * Compares the given calendar with this.
964
   * @param o the object to that we should compare.
965
   * @return true, if the given object is a calendar, and this calendar
966
   * represents a bigger time than the calendar o.
967
   * @exception ClassCastException if o is not an calendar.
968
   * @since JDK1.2 you don't need to override this method
969
   */
970
  public boolean after(Object o)
971
  {
972
    return getTimeInMillis() > ((Calendar) o).getTimeInMillis();
973
  }
974
 
975
  /**
976
   * Adds the specified amount of time to the given time field.  The
977
   * amount may be negative to subtract the time.  If the field overflows
978
   * it does what you expect: Jan, 25 + 10 Days is Feb, 4.
979
   * @param field the time field. One of the time field constants.
980
   * @param amount the amount of time.
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 add(int field, int amount);
986
 
987
  /**
988
   * Rolls the specified time field up or down.  This means add one
989
   * to the specified field, but don't change the other fields.  If
990
   * the maximum for this field is reached, start over with the
991
   * minimum value.  <br>
992
   *
993
   * <strong>Note:</strong> There may be situation, where the other
994
   * fields must be changed, e.g rolling the month on May, 31.
995
   * The date June, 31 is automatically converted to July, 1.
996
   * @param field the time field. One of the time field constants.
997
   * @param up the direction, true for up, false for down.
998
   * @throws ArrayIndexOutOfBoundsException if the field is outside
999
   *         the valid range.  The value of field must be >= 0 and
1000
   *         <= <code>FIELD_COUNT</code>.
1001
   */
1002
  public abstract void roll(int field, boolean up);
1003
 
1004
  /**
1005
   * Rolls up or down the specified time field by the given amount.
1006
   * A negative amount rolls down.  The default implementation is
1007
   * call <code>roll(int, boolean)</code> for the specified amount.
1008
   *
1009
   * Subclasses should override this method to do more intuitiv things.
1010
   *
1011
   * @param field the time field. One of the time field constants.
1012
   * @param amount the amount to roll by, positive for rolling up,
1013
   * negative for rolling down.
1014
   * @throws ArrayIndexOutOfBoundsException if the field is outside
1015
   *         the valid range.  The value of field must be >= 0 and
1016
   *         <= <code>FIELD_COUNT</code>.
1017
   * @since JDK1.2
1018
   */
1019
  public void roll(int field, int amount)
1020
  {
1021
    while (amount > 0)
1022
      {
1023
        roll(field, true);
1024
        amount--;
1025
      }
1026
    while (amount < 0)
1027
      {
1028
        roll(field, false);
1029
        amount++;
1030
      }
1031
  }
1032
 
1033
  /**
1034
   * Sets the time zone to the specified value.
1035
   * @param zone the new time zone
1036
   */
1037
  public void setTimeZone(TimeZone zone)
1038
  {
1039
    this.zone = zone;
1040
  }
1041
 
1042
  /**
1043
   * Gets the time zone of this calendar
1044
   * @return the current time zone.
1045
   */
1046
  public TimeZone getTimeZone()
1047
  {
1048
    return zone;
1049
  }
1050
 
1051
  /**
1052
   * Specifies if the date/time interpretation should be lenient.
1053
   * If the flag is set, a date such as "February 30, 1996" will be
1054
   * treated as the 29th day after the February 1.  If this flag
1055
   * is false, such dates will cause an exception.
1056
   * @param lenient true, if the date should be interpreted linient,
1057
   * false if it should be interpreted strict.
1058
   */
1059
  public void setLenient(boolean lenient)
1060
  {
1061
    this.lenient = lenient;
1062
  }
1063
 
1064
  /**
1065
   * Tells if the date/time interpretation is lenient.
1066
   * @return true, if the date should be interpreted linient,
1067
   * false if it should be interpreted strict.
1068
   */
1069
  public boolean isLenient()
1070
  {
1071
    return lenient;
1072
  }
1073
 
1074
  /**
1075
   * Sets what the first day of week is.  This is used for
1076
   * WEEK_OF_MONTH and WEEK_OF_YEAR fields.
1077
   * @param value the first day of week.  One of SUNDAY to SATURDAY.
1078
   */
1079
  public void setFirstDayOfWeek(int value)
1080
  {
1081
    firstDayOfWeek = value;
1082
  }
1083
 
1084
  /**
1085
   * Gets what the first day of week is.  This is used for
1086
   * WEEK_OF_MONTH and WEEK_OF_YEAR fields.
1087
   * @return the first day of week.  One of SUNDAY to SATURDAY.
1088
   */
1089
  public int getFirstDayOfWeek()
1090
  {
1091
    return firstDayOfWeek;
1092
  }
1093
 
1094
  /**
1095
   * Sets how many days are required in the first week of the year.
1096
   * If the first day of the year should be the first week you should
1097
   * set this value to 1.  If the first week must be a full week, set
1098
   * it to 7.
1099
   * @param value the minimal days required in the first week.
1100
   */
1101
  public void setMinimalDaysInFirstWeek(int value)
1102
  {
1103
    minimalDaysInFirstWeek = value;
1104
  }
1105
 
1106
  /**
1107
   * Gets how many days are required in the first week of the year.
1108
   * @return the minimal days required in the first week.
1109
   * @see #setMinimalDaysInFirstWeek
1110
   */
1111
  public int getMinimalDaysInFirstWeek()
1112
  {
1113
    return minimalDaysInFirstWeek;
1114
  }
1115
 
1116
  /**
1117
   * Gets the smallest value that is allowed for the specified field.
1118
   * @param field the time field. One of the time field constants.
1119
   * @return the smallest value.
1120
   */
1121
  public abstract int getMinimum(int field);
1122
 
1123
  /**
1124
   * Gets the biggest value that is allowed for the specified field.
1125
   * @param field the time field. One of the time field constants.
1126
   * @return the biggest value.
1127
   */
1128
  public abstract int getMaximum(int field);
1129
 
1130
  /**
1131
   * Gets the greatest minimum value that is allowed for the specified field.
1132
   * @param field the time field. One of the time field constants.
1133
   * @return the greatest minimum value.
1134
   */
1135
  public abstract int getGreatestMinimum(int field);
1136
 
1137
  /**
1138
   * Gets the smallest maximum value that is allowed for the
1139
   * specified field.  For example this is 28 for DAY_OF_MONTH.
1140
   * @param field the time field. One of the time field constants.
1141
   * @return the least maximum value.
1142
   */
1143
  public abstract int getLeastMaximum(int field);
1144
 
1145
  /**
1146
   * Gets the actual minimum value that is allowed for the specified field.
1147
   * This value is dependent on the values of the other fields.
1148
   * @param field the time field. One of the time field constants.
1149
   * @return the actual minimum value.
1150
   * @throws ArrayIndexOutOfBoundsException if the field is outside
1151
   *         the valid range.  The value of field must be >= 0 and
1152
   *         <= <code>FIELD_COUNT</code>.
1153
   * @since jdk1.2
1154
   */
1155
  public int getActualMinimum(int field)
1156
  {
1157
    Calendar tmp = (Calendar) clone(); // To avoid restoring state
1158
    int min = tmp.getGreatestMinimum(field);
1159
    int end = tmp.getMinimum(field);
1160
    tmp.set(field, min);
1161
    for (; min > end; min--)
1162
      {
1163
        tmp.add(field, -1); // Try to get smaller
1164
        if (tmp.get(field) != min - 1)
1165
          break; // Done if not successful
1166
      }
1167
    return min;
1168
  }
1169
 
1170
  /**
1171
   * Gets the actual maximum value that is allowed for the specified field.
1172
   * This value is dependent on the values of the other fields.
1173
   * @param field the time field. One of the time field constants.
1174
   * @return the actual maximum value.
1175
   * @throws ArrayIndexOutOfBoundsException if the field is outside
1176
   *         the valid range.  The value of field must be >= 0 and
1177
   *         <= <code>FIELD_COUNT</code>.
1178
   * @since jdk1.2
1179
   */
1180
  public int getActualMaximum(int field)
1181
  {
1182
    Calendar tmp = (Calendar) clone(); // To avoid restoring state
1183
    int max = tmp.getLeastMaximum(field);
1184
    int end = tmp.getMaximum(field);
1185
    tmp.set(field, max);
1186
    for (; max < end; max++)
1187
      {
1188
        tmp.add(field, 1);
1189
        if (tmp.get(field) != max + 1)
1190
          break;
1191
      }
1192
    return max;
1193
  }
1194
 
1195
  /**
1196
   * Return a clone of this object.
1197
   */
1198
  public Object clone()
1199
  {
1200
    try
1201
      {
1202
        Calendar cal = (Calendar) super.clone();
1203
        cal.fields = (int[]) fields.clone();
1204
        cal.isSet = (boolean[]) isSet.clone();
1205
        return cal;
1206
      }
1207
    catch (CloneNotSupportedException ex)
1208
      {
1209
        return null;
1210
      }
1211
  }
1212
 
1213
  private static final String[] fieldNames =
1214
                                             {
1215
                                               ",ERA=", ",YEAR=", ",MONTH=",
1216
                                               ",WEEK_OF_YEAR=",
1217
                                               ",WEEK_OF_MONTH=",
1218
                                               ",DAY_OF_MONTH=",
1219
                                               ",DAY_OF_YEAR=", ",DAY_OF_WEEK=",
1220
                                               ",DAY_OF_WEEK_IN_MONTH=",
1221
                                               ",AM_PM=", ",HOUR=",
1222
                                               ",HOUR_OF_DAY=", ",MINUTE=",
1223
                                               ",SECOND=", ",MILLISECOND=",
1224
                                               ",ZONE_OFFSET=", ",DST_OFFSET="
1225
                                             };
1226
 
1227
  /**
1228
   * Returns a string representation of this object.  It is mainly
1229
   * for debugging purposes and its content is implementation
1230
   * specific.
1231
   */
1232
  public String toString()
1233
  {
1234
    StringBuffer sb = new StringBuffer();
1235
    sb.append(getClass().getName()).append('[');
1236
    sb.append("time=");
1237
    if (isTimeSet)
1238
      sb.append(time);
1239
    else
1240
      sb.append("?");
1241
    sb.append(",zone=" + zone);
1242
    sb.append(",areFieldsSet=" + areFieldsSet);
1243
    for (int i = 0; i < FIELD_COUNT; i++)
1244
      {
1245
        sb.append(fieldNames[i]);
1246
        if (isSet[i])
1247
          sb.append(fields[i]);
1248
        else
1249
          sb.append("?");
1250
      }
1251
    sb.append(",lenient=").append(lenient);
1252
    sb.append(",firstDayOfWeek=").append(firstDayOfWeek);
1253
    sb.append(",minimalDaysInFirstWeek=").append(minimalDaysInFirstWeek);
1254
    sb.append("]");
1255
    return sb.toString();
1256
  }
1257
 
1258
  /**
1259
   * Saves the state of the object to the stream.  Ideally we would
1260
   * only write the time field, but we need to be compatible with
1261
   * earlier versions. <br>
1262
   *
1263
   * This doesn't write the JDK1.1 field nextStamp to the stream, as
1264
   * I don't know what it is good for, and because the documentation
1265
   * says, that it could be omitted.  */
1266
  private void writeObject(ObjectOutputStream stream) throws IOException
1267
  {
1268
    if (! isTimeSet)
1269
      computeTime();
1270
    stream.defaultWriteObject();
1271
  }
1272
 
1273
  /**
1274
   * Reads the object back from stream (deserialization).
1275
   */
1276
  private void readObject(ObjectInputStream stream)
1277
    throws IOException, ClassNotFoundException
1278
  {
1279
    stream.defaultReadObject();
1280
    if (! isTimeSet)
1281
      computeTime();
1282
 
1283
    if (serialVersionOnStream > 1)
1284
      {
1285
        // This is my interpretation of the serial number:
1286
        // Sun wants to remove all fields from the stream someday
1287
        // and will then increase the serialVersion number again.
1288
        // We prepare to be compatible.
1289
        fields = new int[FIELD_COUNT];
1290
        isSet = new boolean[FIELD_COUNT];
1291
        areFieldsSet = false;
1292
      }
1293
  }
1294
}

powered by: WebSVN 2.1.0

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