Merge from the pain train
[official-gcc.git] / libjava / java / util / Date.java
blob3d8f2a69d9d00ce9c80e4e34859dadf55d989cb7
1 /* java.util.Date
2 Copyright (C) 1998, 1999, 2000, 2001, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
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.
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. */
38 package java.util;
40 import java.io.IOException;
41 import java.io.ObjectInputStream;
42 import java.io.ObjectOutputStream;
43 import java.io.Serializable;
45 /**
46 * <p>
47 * This class represents a specific time in milliseconds since the epoch.
48 * The epoch is 1970, January 1 00:00:00.0000 UTC.
49 * </p>
50 * <p>
51 * <code>Date</code> is intended to reflect universal time coordinate (UTC),
52 * but this depends on the underlying host environment. Most operating systems
53 * don't handle the leap second, which occurs about once every year or
54 * so. The leap second is added to the last minute of the day on either
55 * the 30th of June or the 31st of December, creating a minute 61 seconds
56 * in length.
57 * </p>
58 * <p>
59 * The representations of the date fields are as follows:
60 * <ul>
61 * <li>
62 * Years are specified as the difference between the year
63 * and 1900. Thus, the final year used is equal to
64 * 1900 + y, where y is the input value.
65 * </li>
66 * <li>
67 * Months are represented using zero-based indexing,
68 * making 0 January and 11 December.
69 * </li>
70 * <li>
71 * Dates are represented with the usual values of
72 * 1 through to 31.
73 * </li>
74 * <li>
75 * Hours are represented in the twenty-four hour clock,
76 * with integer values from 0 to 23. 12am is 0, and
77 * 12pm is 12.
78 * </li>
79 * <li>
80 * Minutes are again as usual, with values from 0 to 59.
81 * </li>
82 * <li>
83 * Seconds are represented with the values 0 through to 61,
84 * with 60 and 61 being leap seconds (as per the ISO C standard).
85 * </li>
86 * </ul>
87 * </p>
88 * <p>
89 * Prior to JDK 1.1, this class was the sole class handling date and time
90 * related functionality. However, this particular solution was not
91 * amenable to internationalization. The new <code>Calendar</code>
92 * class should now be used to handle dates and times, with <code>Date</code>
93 * being used only for values in milliseconds since the epoch. The
94 * <code>Calendar</code> class, and its concrete implementations, handle
95 * the interpretation of these values into minutes, hours, days, months
96 * and years. The formatting and parsing of dates is left to the
97 * <code>DateFormat</code> class, which is able to handle the different
98 * types of date format which occur in different locales.
99 * </p>
101 * @see Calendar
102 * @see GregorianCalendar
103 * @see java.text.DateFormat
104 * @author Jochen Hoenicke
105 * @author Per Bothner (bothner@cygnus.com)
106 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
108 public class Date
109 implements Cloneable, Comparable, Serializable
112 * This is the serialization UID for this class
113 * for compatability with Sun's JDK.
115 private static final long serialVersionUID = 7523967970034938905L;
118 * The time in milliseconds since the epoch.
120 private transient long time;
123 * An array of week names used to map names to integer values.
125 private static final String[] weekNames = { "Sun", "Mon", "Tue", "Wed",
126 "Thu", "Fri", "Sat" };
128 * An array of month names used to map names to integer values.
130 private static final String[] monthNames = { "Jan", "Feb", "Mar", "Apr",
131 "May", "Jun", "Jul", "Aug",
132 "Sep", "Oct", "Nov", "Dec" };
134 * Creates a new Date Object representing the current time.
136 public Date()
138 time = System.currentTimeMillis();
142 * Creates a new Date Object representing the given time.
144 * @param time the time in milliseconds since the epoch.
146 public Date(long time)
148 this.time = time;
152 * Creates a new Date Object representing the given time.
154 * @deprecated use <code>new GregorianCalendar(year+1900, month,
155 * day)</code> instead.
156 * @param year the difference between the required year and 1900.
157 * @param month the month as a value between 0 and 11.
158 * @param day the day as a value between 0 and 31.
160 public Date(int year, int month, int day)
162 this(year, month, day, 0, 0, 0);
166 * Creates a new Date Object representing the given time.
168 * @deprecated use <code>new GregorianCalendar(year+1900, month,
169 * day, hour, min)</code> instead.
170 * @param year the difference between the required year and 1900.
171 * @param month the month as a value between 0 and 11.
172 * @param day the day as a value between 0 and 31.
173 * @param hour the hour as a value between 0 and 23, in 24-hour
174 * clock notation.
175 * @param min the minute as a value between 0 and 59.
177 public Date(int year, int month, int day, int hour, int min)
179 this(year, month, day, hour, min, 0);
183 * Creates a new Date Object representing the given time.
185 * @deprecated use <code>new GregorianCalendar(year+1900, month,
186 * day, hour, min, sec)</code> instead.
187 * @param year the difference between the required year and 1900.
188 * @param month the month as a value between 0 and 11.
189 * @param day the day as a value between 0 and 31.
190 * @param hour the hour as a value between 0 and 23, in 24-hour
191 * clock notation.
192 * @param min the minute as a value between 0 and 59.
193 * @param sec the second as a value between 0 and 61 (with 60
194 * and 61 being leap seconds).
196 public Date(int year, int month, int day, int hour, int min, int sec)
198 GregorianCalendar cal =
199 new GregorianCalendar(year + 1900, month, day, hour, min, sec);
200 time = cal.getTimeInMillis();
204 * Creates a new Date from the given string representation. This
205 * does the same as <code>new Date(Date.parse(s))</code>
206 * @see #parse
207 * @deprecated use <code>java.text.DateFormat.parse(s)</code> instead.
209 public Date(String s)
211 time = parse(s);
215 * Returns a copy of this <code>Date</code> object.
217 * @return a copy, or null if the object couldn't be
218 * cloned.
219 * @see Object#clone()
221 public Object clone()
225 return super.clone();
227 catch (CloneNotSupportedException ex)
229 return null;
234 * Returns the number of milliseconds since the epoch
235 * specified by the given arguments. The arguments are
236 * interpreted relative to UTC rather than the local
237 * time zone.
239 * @deprecated Use <code>Calendar</code> with a UTC
240 * <code>TimeZone</code> instead.
241 * @param year the difference between the required year and 1900.
242 * @param month the month as a value between 0 and 11.
243 * @param day the day as a value between 0 and 31.
244 * @param hour the hour as a value between 0 and 23, in 24-hour
245 * clock notation.
246 * @param min the minute as a value between 0 and 59.
247 * @param sec the second as a value between 0 and 61 (with 60
248 * and 61 being leap seconds).
249 * @return the time in milliseconds since the epoch.
251 public static long UTC(int year, int month, int date,
252 int hrs, int min, int sec)
254 GregorianCalendar cal =
255 new GregorianCalendar(year + 1900, month, date, hrs, min, sec);
256 cal.set(Calendar.ZONE_OFFSET, 0);
257 cal.set(Calendar.DST_OFFSET, 0);
258 return cal.getTimeInMillis();
262 * Gets the time represented by this object.
264 * @return the time in milliseconds since the epoch.
266 public long getTime()
268 return time;
272 * Returns the number of minutes offset used with UTC to give the time
273 * represented by this object in the current time zone. The date information
274 * from this object is also used to determine whether or not daylight savings
275 * time is in effect. For example, the offset for the UK would be 0 if the
276 * month of the date object was January, and 1 if the month was August.
278 * @deprecated use
279 * <code>Calendar.get(Calendar.ZONE_OFFSET)+Calendar.get(Calendar.DST_OFFSET)</code>
280 * instead.
281 * @return The time zone offset in minutes of the local time zone
282 * relative to UTC. The time represented by this object is used to
283 * determine if we should use daylight savings.
285 public int getTimezoneOffset()
287 Calendar cal = Calendar.getInstance();
288 cal.setTimeInMillis(time);
289 return - (cal.get(Calendar.ZONE_OFFSET)
290 + cal.get(Calendar.DST_OFFSET)) / (60 * 1000);
294 * Sets the time which this object should represent.
296 * @param time the time in milliseconds since the epoch.
298 public void setTime(long time)
300 this.time = time;
304 * Tests if this date is after the specified date.
306 * @param when the other date
307 * @return true, if the date represented by this object is
308 * strictly later than the time represented by when.
310 public boolean after(Date when)
312 return time > when.time;
316 * Tests if this date is before the specified date.
318 * @param when the other date
319 * @return true, if the date represented by when is strictly later
320 * than the time represented by this object.
322 public boolean before(Date when)
324 return time < when.time;
328 * Compares two dates for equality.
330 * @param obj the object to compare.
331 * @return true, if obj is a Date object and the time represented
332 * by obj is exactly the same as the time represented by this
333 * object.
335 public boolean equals(Object obj)
337 return (obj instanceof Date && time == ((Date) obj).time);
341 * Compares two dates.
343 * @param when the other date.
344 * @return 0, if the date represented
345 * by obj is exactly the same as the time represented by this
346 * object, a negative if this Date is before the other Date, and
347 * a positive value otherwise.
349 public int compareTo(Date when)
351 return (time < when.time) ? -1 : (time == when.time) ? 0 : 1;
355 * Compares this Date to another object. This behaves like
356 * <code>compareTo(Date)</code>, but it takes a generic object
357 * and throws a <code>ClassCastException</code> if obj is
358 * not a <code>Date</code>.
360 * @param obj the other date.
361 * @return 0, if the date represented
362 * by obj is exactly the same as the time represented by this
363 * object, a negative if this Date is before the other Date, and
364 * a positive value otherwise.
365 * @exception ClassCastException if obj is not of type Date.
367 public int compareTo(Object obj)
369 return compareTo((Date) obj);
373 * Computes the hash code of this <code>Date</code> as the
374 * XOR of the most significant and the least significant
375 * 32 bits of the 64 bit milliseconds value.
377 * @return the hash code.
379 public int hashCode()
381 return (int) time ^ (int) (time >>> 32);
385 * <p>
386 * Returns a string representation of this date using
387 * the following date format:
388 * </p>
389 * <p>
390 * <code>day mon dd hh:mm:ss zz yyyy</code>
391 * </p>
392 * <p>where the fields used here are:
393 * <ul>
394 * <li>
395 * <code>day</code> -- the day of the week
396 * (Sunday through to Saturday).
397 * </li>
398 * <li>
399 * <code>mon</code> -- the month (Jan to Dec).
400 * </li>
401 * <li>
402 * <code>dd</code> -- the day of the month
403 * as two decimal digits (01 to 31).
404 * </li>
405 * <li>
406 * <code>hh</code> -- the hour of the day
407 * as two decimal digits in 24-hour clock notation
408 * (01 to 23).
409 * </li>
410 * <li>
411 * <code>mm</code> -- the minute of the day
412 * as two decimal digits (01 to 59).
413 * </li>
414 * <li>
415 * <code>ss</code> -- the second of the day
416 * as two decimal digits (01 to 61).
417 * </li>
418 * <li>
419 * <code>zz</code> -- the time zone information if available.
420 * The possible time zones used include the abbreviations
421 * recognised by <code>parse()</code> (e.g. GMT, CET, etc.)
422 * and may reflect the fact that daylight savings time is in
423 * effect. The empty string is used if there is no time zone
424 * information.
425 * </li>
426 * <li>
427 * <code>yyyy</code> -- the year as four decimal digits.
428 * </li>
429 * </ul>
430 * <p>
431 * The <code>DateFormat</code> class should now be
432 * preferred over using this method.
433 * </p>
435 * @return A string of the form 'day mon dd hh:mm:ss zz yyyy'
436 * @see #parse(String)
437 * @see DateFormat
439 public String toString()
441 Calendar cal = Calendar.getInstance();
442 cal.setTimeInMillis(time);
443 String day = "0" + cal.get(Calendar.DATE);
444 String hour = "0" + cal.get(Calendar.HOUR_OF_DAY);
445 String min = "0" + cal.get(Calendar.MINUTE);
446 String sec = "0" + cal.get(Calendar.SECOND);
447 String year = "000" + cal.get(Calendar.YEAR);
448 return weekNames[cal.get(Calendar.DAY_OF_WEEK) - 1] + " "
449 + monthNames[cal.get(Calendar.MONTH)] + " "
450 + day.substring(day.length() - 2) + " "
451 + hour.substring(hour.length() - 2) + ":"
452 + min.substring(min.length() - 2) + ":"
453 + sec.substring(sec.length() - 2) + " "
455 cal.getTimeZone().getDisplayName(cal.getTimeZone().inDaylightTime(this),
456 TimeZone.SHORT) + " " +
457 year.substring(year.length() - 4);
460 /**
461 * Returns a locale-dependent string representation of this
462 * <code>Date</code> object.
464 * @deprecated Use DateFormat.format(Date)
465 * @return A locale-dependent string representation.
466 * @see #parse(String)
467 * @see DateFormat
469 public String toLocaleString()
471 return java.text.DateFormat.getInstance().format(this);
474 /**
475 * <p>
476 * Returns a string representation of this <code>Date</code>
477 * object using GMT rather than the local timezone.
478 * The following date format is used:
479 * </p>
480 * <p>
481 * <code>d mon yyyy hh:mm:ss GMT</code>
482 * </p>
483 * <p>where the fields used here are:
484 * <ul>
485 * <li>
486 * <code>d</code> -- the day of the month
487 * as one or two decimal digits (1 to 31).
488 * </li>
489 * <li>
490 * <code>mon</code> -- the month (Jan to Dec).
491 * </li>
492 * <li>
493 * <code>yyyy</code> -- the year as four decimal digits.
494 * </li>
495 * <li>
496 * <code>hh</code> -- the hour of the day
497 * as two decimal digits in 24-hour clock notation
498 * (01 to 23).
499 * </li>
500 * <li>
501 * <code>mm</code> -- the minute of the day
502 * as two decimal digits (01 to 59).
503 * </li>
504 * <li>
505 * <code>ss</code> -- the second of the day
506 * as two decimal digits (01 to 61).
507 * </li>
508 * <li>
509 * <code>GMT</code> -- the literal string "GMT"
510 * indicating Greenwich Mean Time as opposed to
511 * the local timezone.
512 * </li>
513 * </ul>
515 * @deprecated Use DateFormat.format(Date) with a GMT TimeZone.
516 * @return A string of the form 'd mon yyyy hh:mm:ss GMT' using
517 * GMT as opposed to the local timezone.
518 * @see #parse(String)
519 * @see DateFormat
521 public String toGMTString()
523 java.text.DateFormat format = java.text.DateFormat.getInstance();
524 format.setTimeZone(TimeZone.getTimeZone("GMT"));
525 return format.format(this);
529 * Parses the time zone string.
531 * @param tok The token containing the time zone.
532 * @param sign The sign (+ or -) used by the time zone.
533 * @return An integer representing the number of minutes offset
534 * from GMT for the time zone.
536 private static int parseTz(String tok, char sign)
537 throws IllegalArgumentException
539 int num;
543 // parseInt doesn't handle '+' so strip off sign.
544 num = Integer.parseInt(tok.substring(1));
546 catch (NumberFormatException ex)
548 throw new IllegalArgumentException(tok);
551 // Convert hours to minutes.
552 if (num < 24)
553 num *= 60;
554 else
555 num = (num / 100) * 60 + num % 100;
557 return sign == '-' ? -num : num;
561 * Parses the month string.
563 * @param tok the token containing the month.
564 * @return An integer between 0 and 11, representing
565 * a month from January (0) to December (11),
566 * or -1 if parsing failed.
568 private static int parseMonth(String tok)
570 // Initialize strings for month names.
571 // We could possibly use the fields of DateFormatSymbols but that is
572 // localized and thus might not match the English words specified.
573 String months[] = { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY",
574 "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER",
575 "NOVEMBER", "DECEMBER" };
577 int i;
578 for (i = 0; i < 12; i++)
579 if (months[i].startsWith(tok))
580 return i;
582 // Return -1 if not found.
583 return -1;
587 * Parses the day of the week string.
589 * @param tok the token containing the day of the week.
590 * @return true if the token was parsed successfully.
592 private static boolean parseDayOfWeek(String tok)
594 // Initialize strings for days of the week names.
595 // We could possibly use the fields of DateFormatSymbols but that is
596 // localized and thus might not match the English words specified.
597 String daysOfWeek[] = { "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
598 "THURSDAY", "FRIDAY", "SATURDAY" };
600 int i;
601 for (i = 0; i < 7; i++)
602 if (daysOfWeek[i].startsWith(tok))
603 return true;
605 return false;
608 /**
609 * <p>
610 * Parses a String and returns the time, in milliseconds since the
611 * epoch, it represents. Most syntaxes are handled, including
612 * the IETF date standard "day, dd mon yyyy hh:mm:ss zz" (see
613 * <code>toString()</code> for definitions of these fields).
614 * Standard U.S. time zone abbreviations are recognised, in
615 * addition to time zone offsets in positive or negative minutes.
616 * If a time zone is specified, the specified time is assumed to
617 * be in UTC and the appropriate conversion is applied, following
618 * parsing, to convert this to the local time zone. If no zone
619 * is specified, the time is assumed to already be in the local
620 * time zone.
621 * </p>
622 * <p>
623 * The method parses the string progressively from left to right.
624 * At the end of the parsing process, either a time is returned
625 * or an <code>IllegalArgumentException</code> is thrown to signify
626 * failure. The ASCII characters A-Z, a-z, 0-9, and ',', '+', '-',
627 * ':' and '/' are the only characters permitted within the string,
628 * besides whitespace and characters enclosed within parantheses
629 * '(' and ')'.
630 * </p>
631 * <p>
632 * A sequence of consecutive digits are recognised as a number,
633 * and interpreted as follows:
634 * <ul>
635 * <li>
636 * A number preceded by a sign (+ or -) is taken to be a time zone
637 * offset. The time zone offset can be specified in either hours
638 * or minutes. The former is assumed if the number is less than 24.
639 * Otherwise, the offset is assumed to be in minutes. A - indicates
640 * a time zone west of GMT, while a + represents a time zone to the
641 * east of GMT. The time zones are always assumed to be relative
642 * to GMT, and a (redundant) specification of this can be included
643 * with the time zone. For example, '-9', 'utc-9' and 'GMT-9' all
644 * represent a time zone nine hours west of GMT. Similarly,
645 * '+4', 'ut+4' and 'UTC+4' all give 4 hours east of GMT.
646 * </li>
647 * <li>
648 * A number equal to or greater than 70 is regarded as a year specification.
649 * Values lower than 70 are only assumed to indicate a year if both the
650 * day of the month and the month itself have already been recognised.
651 * Year values less than 100 are interpreted as being relative to the current
652 * century when the <code>Date</code> class is initialised.. Given a century,
653 * x, the year is assumed to be within the range x - 80 to x + 19. The value
654 * itself is then used as a match against the two last digits of one of these
655 * years. For example, take x to be 2004. A two-digit year is assumed to fall
656 * within the range x - 80 (1924) and x + 19 (2023). Thus, any intepreted value
657 * between 0 and 23 is assumed to be 2000 to 2023 and values between 24 and 99
658 * are taken as being 1924 to 1999. This only applies for the case of 2004.
659 * With a different year, the values will be interpreted differently. 2005
660 * will used 0 to 24 as 2000 to 2024 and 25 to 99 as 1925 to 1999, for example.
661 * This behaviour differs from that of <code>SimpleDateFormat</code> and is
662 * time-dependent (a two-digit year will be interpreted differently depending
663 * on the time the code is run).
664 * </li>
665 * <li>
666 * Numbers followed by a colon are interpreted by first an hour, and then
667 * as a minute, once an hour has been found.
668 * </li>
669 * <li>
670 * <li>
671 * Numbers followed by a slash are regarded first as a month, and then as
672 * a day of the month once the month has been found. This follows the
673 * U.S. date format of mm/dd, rather than the European dd/mm. Months
674 * are converted to the recognised value - 1 before storage, in order
675 * to put the number within the range 0 to 11.
676 * </li>
677 * <li>
678 * Numbers followed by commas, whitespace, hyphens or the end of the string
679 * are interpreted in the following order: hour, minute, second, day of month.
680 * The first type not already recognised in the current string being parsed is
681 * assumed.
682 * </li>
683 * </ul>
684 * </p>
685 * <p>
686 * A sequence of consecutive alphabetic characters is recognised as a word,
687 * and interpreted as follows, in a case-insentive fashion:
688 * <ul>
689 * <li>
690 * The characters 'AM' or 'PM' restrict the hour value to a value between 0
691 * and 12. In the latter case, 12 is added to the hour value before storage.
692 * </li>
693 * <li>
694 * Any words which match any prefix of one of the days of the week ('Monday',
695 * 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' and 'Sunday'),
696 * are simply ignored.
697 * </li>
698 * <li>
699 * Any words which match any prefix of one of the months of the year ('January',
700 * 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September',
701 * 'October', 'November', 'December') are recognised and interpreted as the
702 * appropriate value between 0 and 11. The first match made against a
703 * month is the one used, in the order specified here. For example, 'Ma' is
704 * intepreted as 'March' (2) and not as 'May' (4). Similarly, 'Ju' is 'June',
705 * and not 'July'.
706 * </li>
707 * <li>
708 * The words 'GMT', 'UT' and 'UTC' are interpreted as specifying UTC as the
709 * time zone in use for this date.
710 * </li>
711 * <li>
712 * The word pairs 'EST'/'EDT', 'CST'/'CDT', 'MST'/'MDT' and 'PST'/'PDT' are
713 * interpreted as the appropriate U.S. time zone abbreviation. Each pair
714 * is the standard and daylight savings time zone specification, respectively,
715 * for each zone within the U.S, these being Eastern Standard/Daylight Time
716 * (-5), Central Standard/Daylight Time (-6), Mountain Standard/Daylight Time
717 * (-7) and Pacific Standard/Daylight Time (-8).
718 * </li>
719 * </ul>
721 * @param s The String to parse.
722 * @return The time in milliseconds since the epoch.
723 * @throws IllegalArgumentException if the string fails to parse.
724 * @deprecated Use DateFormat.parse(String)
725 * @see #toString()
726 * @see SimpleDateFormat
728 public static long parse(String string)
730 // Initialize date/time fields before parsing begins.
731 int year = -1;
732 int month = -1;
733 int day = -1;
734 int hour = -1;
735 int minute = -1;
736 int second = -1;
737 int timezone = 0;
738 boolean localTimezone = true;
740 // Trim out any nested stuff in parentheses now to make parsing easier.
741 StringBuffer buf = new StringBuffer();
742 int parenNesting = 0;
743 int len = string.length();
744 for (int i = 0; i < len; i++)
746 char ch = string.charAt(i);
747 if (ch >= 'a' && ch <= 'z')
748 ch -= 'a' - 'A';
749 if (ch == '(')
750 parenNesting++;
751 else if (parenNesting == 0)
752 buf.append(ch);
753 else if (ch == ')')
754 parenNesting--;
756 int tmpMonth;
758 // Make all chars upper case to simplify comparisons later.
759 // Also ignore commas; treat them as delimiters.
760 StringTokenizer strtok = new StringTokenizer(buf.toString(), " \t\n\r,");
762 while (strtok.hasMoreTokens())
764 String tok = strtok.nextToken();
765 char firstch = tok.charAt(0);
766 if ((firstch == '+' || firstch == '-') && year >= 0)
768 timezone = parseTz(tok, firstch);
769 localTimezone = false;
771 else if (firstch >= '0' && firstch <= '9')
773 while (tok != null && tok.length() > 0)
775 int punctOffset = tok.length();
776 int num = 0;
777 int punct;
778 for (int i = 0; ; i++)
780 if (i >= punctOffset)
782 punct = -1;
783 break;
785 else
787 punct = tok.charAt(i);
788 if (punct >= '0' && punct <= '9')
790 if (num > 999999999) // in case of overflow
791 throw new IllegalArgumentException(tok);
792 num = 10 * num + (punct - '0');
794 else
796 punctOffset = i;
797 break;
803 if (punct == ':')
805 if (hour < 0)
806 hour = num;
807 else
808 minute = num;
810 else if ((num >= 70
811 && (punct == ' ' || punct == ','
812 || punct == '/' || punct < 0))
813 || (num < 70 && day >= 0 && month >= 0 && year < 0))
815 if (num >= 100)
816 year = num;
817 else
819 int curYear = 1900 + new Date().getYear();
820 int firstYear = curYear - 80;
821 year = firstYear / 100 * 100 + num;
822 if (year < firstYear)
823 year += 100;
826 else if (punct == '/')
828 if (month < 0)
829 month = num - 1;
830 else
831 day = num;
833 else if (hour >= 0 && minute < 0)
834 minute = num;
835 else if (minute >= 0 && second < 0)
836 second = num;
837 else if (day < 0)
838 day = num;
839 else
840 throw new IllegalArgumentException(tok);
842 // Advance string if there's more to process in this token.
843 if (punct < 0 || punctOffset + 1 >= tok.length())
844 tok = null;
845 else
846 tok = tok.substring(punctOffset + 1);
849 else if (firstch >= 'A' && firstch <= 'Z')
851 if (tok.equals("AM"))
853 if (hour < 1 || hour > 12)
854 throw new IllegalArgumentException(tok);
855 if (hour == 12)
856 hour = 0;
858 else if (tok.equals("PM"))
860 if (hour < 1 || hour > 12)
861 throw new IllegalArgumentException(tok);
862 if (hour < 12)
863 hour += 12;
865 else if (parseDayOfWeek(tok))
866 ; // Ignore it; throw the token away.
867 else if (tok.equals("UT") || tok.equals("UTC") || tok.equals("GMT"))
868 localTimezone = false;
869 else if (tok.startsWith("UT") || tok.startsWith("GMT"))
871 int signOffset = 3;
872 if (tok.charAt(1) == 'T' && tok.charAt(2) != 'C')
873 signOffset = 2;
875 char sign = tok.charAt(signOffset);
876 if (sign != '+' && sign != '-')
877 throw new IllegalArgumentException(tok);
879 timezone = parseTz(tok.substring(signOffset), sign);
880 localTimezone = false;
882 else if ((tmpMonth = parseMonth(tok)) >= 0)
883 month = tmpMonth;
884 else if (tok.length() == 3 && tok.charAt(2) == 'T')
886 // Convert timezone offset from hours to minutes.
887 char ch = tok.charAt(0);
888 if (ch == 'E')
889 timezone = -5 * 60;
890 else if (ch == 'C')
891 timezone = -6 * 60;
892 else if (ch == 'M')
893 timezone = -7 * 60;
894 else if (ch == 'P')
895 timezone = -8 * 60;
896 else
897 throw new IllegalArgumentException(tok);
899 // Shift 60 minutes for Daylight Savings Time.
900 if (tok.charAt(1) == 'D')
901 timezone += 60;
902 else if (tok.charAt(1) != 'S')
903 throw new IllegalArgumentException(tok);
905 localTimezone = false;
907 else
908 throw new IllegalArgumentException(tok);
910 else
911 throw new IllegalArgumentException(tok);
914 // Unspecified hours, minutes, or seconds should default to 0.
915 if (hour < 0)
916 hour = 0;
917 if (minute < 0)
918 minute = 0;
919 if (second < 0)
920 second = 0;
922 // Throw exception if any other fields have not been recognized and set.
923 if (year < 0 || month < 0 || day < 0)
924 throw new IllegalArgumentException("Missing field");
926 // Return the time in either local time or relative to GMT as parsed.
927 // If no time-zone was specified, get the local one (in minutes) and
928 // convert to milliseconds before adding to the UTC.
929 GregorianCalendar cal
930 = new GregorianCalendar(year, month, day, hour, minute, second);
931 if (!localTimezone)
933 cal.set(Calendar.ZONE_OFFSET, timezone * 60 * 1000);
934 cal.set(Calendar.DST_OFFSET, 0);
936 return cal.getTimeInMillis();
940 * Returns the difference between the year represented by this
941 * <code>Date</code> object and 1900.
943 * @return the year minus 1900 represented by this date object.
944 * @deprecated Use Calendar instead of Date, and use get(Calendar.YEAR)
945 * instead. Note the 1900 difference in the year.
946 * @see Calendar
947 * @see #setYear(int)
949 public int getYear()
951 Calendar cal = Calendar.getInstance();
952 cal.setTimeInMillis(time);
953 return cal.get(Calendar.YEAR) - 1900;
957 * Sets the year to the specified year, plus 1900. The other
958 * fields are only altered as required to match the same date
959 * and time in the new year. Usually, this will mean that
960 * the fields are not changed at all, but in the case of
961 * a leap day or leap second, the fields will change in
962 * relation to the existence of such an event in the new year.
963 * For example, if the date specifies February the 29th, 2000,
964 * then this will become March the 1st if the year is changed
965 * to 2001, as 2001 is not a leap year. Similarly, a seconds
966 * value of 60 or 61 may result in the seconds becoming 0 and
967 * the minute increasing by 1, if the new time does not include
968 * a leap second.
970 * @param year the year minus 1900.
971 * @deprecated Use Calendar instead of Date, and use
972 * set(Calendar.YEAR, year) instead. Note about the 1900
973 * difference in year.
974 * @see #getYear()
975 * @see Calendar
977 public void setYear(int year)
979 Calendar cal = Calendar.getInstance();
980 cal.setTimeInMillis(time);
981 cal.set(Calendar.YEAR, 1900 + year);
982 time = cal.getTimeInMillis();
986 * Returns the month represented by this <code>Date</code> object,
987 * as a value between 0 (January) and 11 (December).
989 * @return the month represented by this date object (zero based).
990 * @deprecated Use Calendar instead of Date, and use get(Calendar.MONTH)
991 * instead.
992 * @see #setMonth(int)
993 * @see Calendar
995 public int getMonth()
997 Calendar cal = Calendar.getInstance();
998 cal.setTimeInMillis(time);
999 return cal.get(Calendar.MONTH);
1003 * Sets the month to the given value. The other
1004 * fields are only altered as necessary to match
1005 * the same date and time in the new month. In most
1006 * cases, the other fields won't change at all. However,
1007 * in the case of a shorter month or a leap second, values
1008 * may be adjusted. For example, if the day of the month
1009 * is currently 31, and the month value is changed from
1010 * January (0) to September (8), the date will become
1011 * October the 1st, as September only has 30 days. Similarly,
1012 * a seconds value of 60 or 61 (a leap second) may result
1013 * in the seconds value being reset to 0 and the minutes
1014 * value being incremented by 1, if the new time does
1015 * not include a leap second.
1017 * @param month the month, with a zero-based index
1018 * from January.
1019 * @deprecated Use Calendar instead of Date, and use
1020 * set(Calendar.MONTH, month) instead.
1021 * @see #getMonth()
1022 * @see Calendar
1024 public void setMonth(int month)
1026 Calendar cal = Calendar.getInstance();
1027 cal.setTimeInMillis(time);
1028 cal.set(Calendar.MONTH, month);
1029 time = cal.getTimeInMillis();
1033 * Returns the day of the month of this <code>Date</code>
1034 * object, as a value between 0 and 31.
1036 * @return the day of month represented by this date object.
1037 * @deprecated Use Calendar instead of Date, and use get(Calendar.DATE)
1038 * instead.
1039 * @see Calendar
1040 * @see #setDate(int)
1042 public int getDate()
1044 Calendar cal = Calendar.getInstance();
1045 cal.setTimeInMillis(time);
1046 return cal.get(Calendar.DATE);
1050 * Sets the date to the given value. The other
1051 * fields are only altered as necessary to match
1052 * the same date and time on the new day of the month. In most
1053 * cases, the other fields won't change at all. However,
1054 * in the case of a leap second or the day being out of
1055 * the range of the current month, values
1056 * may be adjusted. For example, if the day of the month
1057 * is currently 30 and the month is June, a new day of the
1058 * month value of 31 will cause the month to change to July,
1059 * as June only has 30 days . Similarly,
1060 * a seconds value of 60 or 61 (a leap second) may result
1061 * in the seconds value being reset to 0 and the minutes
1062 * value being incremented by 1, if the new time does
1063 * not include a leap second.
1065 * @param date the date.
1066 * @deprecated Use Calendar instead of Date, and use
1067 * set(Calendar.DATE, date) instead.
1068 * @see Calendar
1069 * @see #getDate()
1071 public void setDate(int date)
1073 Calendar cal = Calendar.getInstance();
1074 cal.setTimeInMillis(time);
1075 cal.set(Calendar.DATE, date);
1076 time = cal.getTimeInMillis();
1080 * Returns the day represented by this <code>Date</code>
1081 * object as an integer between 0 (Sunday) and 6 (Saturday).
1083 * @return the day represented by this date object.
1084 * @deprecated Use Calendar instead of Date, and use get(Calendar.DAY_OF_WEEK)
1085 * instead.
1086 * @see Calendar
1088 public int getDay()
1090 Calendar cal = Calendar.getInstance();
1091 cal.setTimeInMillis(time);
1092 // For Calendar, Sunday is 1. For Date, Sunday is 0.
1093 return cal.get(Calendar.DAY_OF_WEEK) - 1;
1097 * Returns the hours represented by this <code>Date</code>
1098 * object as an integer between 0 and 23.
1100 * @return the hours represented by this date object.
1101 * @deprecated Use Calendar instead of Date, and use get(Calendar.HOUR_OF_DAY)
1102 * instead.
1103 * @see Calendar
1104 * @see #setHours(int)
1106 public int getHours()
1108 Calendar cal = Calendar.getInstance();
1109 cal.setTimeInMillis(time);
1110 return cal.get(Calendar.HOUR_OF_DAY);
1114 * Sets the hours to the given value. The other
1115 * fields are only altered as necessary to match
1116 * the same date and time in the new hour. In most
1117 * cases, the other fields won't change at all. However,
1118 * in the case of a leap second, values
1119 * may be adjusted. For example,
1120 * a seconds value of 60 or 61 (a leap second) may result
1121 * in the seconds value being reset to 0 and the minutes
1122 * value being incremented by 1 if the new hour does
1123 * not contain a leap second.
1125 * @param hours the hours.
1126 * @deprecated Use Calendar instead of Date, and use
1127 * set(Calendar.HOUR_OF_DAY, hours) instead.
1128 * @see Calendar
1129 * @see #getHours()
1131 public void setHours(int hours)
1133 Calendar cal = Calendar.getInstance();
1134 cal.setTimeInMillis(time);
1135 cal.set(Calendar.HOUR_OF_DAY, hours);
1136 time = cal.getTimeInMillis();
1140 * Returns the number of minutes represented by the <code>Date</code>
1141 * object, as an integer between 0 and 59.
1143 * @return the minutes represented by this date object.
1144 * @deprecated Use Calendar instead of Date, and use get(Calendar.MINUTE)
1145 * instead.
1146 * @see Calendar
1147 * @see #setMinutes(int)
1149 public int getMinutes()
1151 Calendar cal = Calendar.getInstance();
1152 cal.setTimeInMillis(time);
1153 return cal.get(Calendar.MINUTE);
1157 * Sets the minutes to the given value. The other
1158 * fields are only altered as necessary to match
1159 * the same date and time in the new minute. In most
1160 * cases, the other fields won't change at all. However,
1161 * in the case of a leap second, values
1162 * may be adjusted. For example,
1163 * a seconds value of 60 or 61 (a leap second) may result
1164 * in the seconds value being reset to 0 and the minutes
1165 * value being incremented by 1 if the new minute does
1166 * not contain a leap second.
1168 * @param minutes the minutes.
1169 * @deprecated Use Calendar instead of Date, and use
1170 * set(Calendar.MINUTE, minutes) instead.
1171 * @see Calendar
1172 * @see #getMinutes()
1174 public void setMinutes(int minutes)
1176 Calendar cal = Calendar.getInstance();
1177 cal.setTimeInMillis(time);
1178 cal.set(Calendar.MINUTE, minutes);
1179 time = cal.getTimeInMillis();
1183 * Returns the number of seconds represented by the <code>Date</code>
1184 * object, as an integer between 0 and 61 (60 and 61 being leap seconds).
1186 * @return the seconds represented by this date object.
1187 * @deprecated Use Calendar instead of Date, and use get(Calendar.SECOND)
1188 * instead.
1189 * @see Calendar
1190 * @see #setSeconds(int)
1192 public int getSeconds()
1194 Calendar cal = Calendar.getInstance();
1195 cal.setTimeInMillis(time);
1196 return cal.get(Calendar.SECOND);
1200 * Sets the seconds to the given value. The other
1201 * fields are only altered as necessary to match
1202 * the same date and time in the new minute. In most
1203 * cases, the other fields won't change at all. However,
1204 * in the case of a leap second, values
1205 * may be adjusted. For example, setting the
1206 * seconds value to 60 or 61 (a leap second) may result
1207 * in the seconds value being reset to 0 and the minutes
1208 * value being incremented by 1, if the current time does
1209 * not contain a leap second.
1211 * @param seconds the seconds.
1212 * @deprecated Use Calendar instead of Date, and use
1213 * set(Calendar.SECOND, seconds) instead.
1214 * @see Calendar
1215 * @see #getSeconds()
1217 public void setSeconds(int seconds)
1219 Calendar cal = Calendar.getInstance();
1220 cal.setTimeInMillis(time);
1221 cal.set(Calendar.SECOND, seconds);
1222 time = cal.getTimeInMillis();
1226 * Deserializes a <code>Date</code> object from an
1227 * input stream, setting the time (in milliseconds
1228 * since the epoch) to the long value read from the
1229 * stream.
1231 * @param input the input stream.
1232 * @throws IOException if an I/O error occurs in the stream.
1233 * @throws ClassNotFoundException if the class of the
1234 * serialized object could not be found.
1236 private void readObject(ObjectInputStream input)
1237 throws IOException, ClassNotFoundException
1239 input.defaultReadObject();
1240 time = input.readLong();
1244 * Serializes a <code>Date</code> object to an output stream,
1245 * storing the time (in milliseconds since the epoch) as a long
1246 * value in the stream.
1248 * @serialdata A long value representing the offset from the epoch
1249 * in milliseconds. This is the same value that is returned by the
1250 * method getTime().
1251 * @param output the output stream.
1252 * @throws IOException if an I/O error occurs in the stream.
1254 private void writeObject(ObjectOutputStream output)
1255 throws IOException
1257 output.defaultWriteObject();
1258 output.writeLong(time);