2 Copyright (C) 1998, 1999, 2000, 2001 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)
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
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
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. */
42 * This class represents a specific time in milliseconds since the epoch.
43 * The epoch is 1970, January 1 00:00:00.0000 UTC.
45 * Date is intended to reflect universal time coordinate (UTC), but doesn't
46 * handle the leap seconds.
48 * Prior to jdk 1.1 this class was the sole Time class and had also
49 * calendar functionality. But this can't be localized, so a new Calendar
50 * class was created, that you should use instead. The functions which
51 * get or return a year, month, day etc. are all deprecated and shouldn't be
52 * used. Use Calendar instead.
55 * @see GregorianCalendar
56 * @see java.text.DateFormat
57 * @author Jochen Hoenicke
58 * @author Per Bothner <bothner@cygnus.com>
60 public class Date implements Cloneable, Comparable, java.io.Serializable
63 * This is the serialization UID for this class
65 private static final long serialVersionUID = 7523967970034938905L;
68 * The time in milliseconds since the epoch.
70 private transient long time;
73 * Creates a new Date Object representing the current time.
77 time = System.currentTimeMillis();
81 * Creates a new Date Object representing the given time.
82 * @param time the time in milliseconds since the epoch.
84 public Date(long time)
90 * Creates a new Date Object representing the given time.
91 * @deprecated use <code>new GregorianCalendar(year+1900, month,
92 * day)</code> instead.
94 public Date(int year, int month, int day)
96 time = new GregorianCalendar(year + 1900, month, day).getTimeInMillis();
100 * Creates a new Date Object representing the given time.
101 * @deprecated use <code>new GregorianCalendar(year+1900, month,
102 * day, hour, min)</code> instead.
104 public Date(int year, int month, int day, int hour, int min)
107 new GregorianCalendar(year + 1900, month, day, hour,
108 min).getTimeInMillis();
112 * Creates a new Date Object representing the given time.
113 * @deprecated use <code>new GregorianCalendar(year+1900, month,
114 * day)</code> instead.
116 public Date(int year, int month, int day, int hour, int min, int sec)
119 new GregorianCalendar(year + 1900, month, day, hour, min,
120 sec).getTimeInMillis();
124 * Creates a new Date from the given string representation. This
125 * does the same as <code>new Date(Date.parse(s))</code>
127 * @deprecated use <code>java.text.DateFormat.parse(s)</code> instead.
129 public Date(String s)
134 public Object clone()
138 return super.clone();
140 catch (CloneNotSupportedException ex)
147 * @deprecated Use Calendar with a UTC TimeZone instead.
148 * @return the time in millis since the epoch.
150 public static long UTC(int year, int month, int date,
151 int hrs, int min, int sec)
153 GregorianCalendar cal =
154 new GregorianCalendar(year + 1900, month, date, hrs, min, sec);
155 cal.set(Calendar.ZONE_OFFSET, 0);
156 cal.set(Calendar.DST_OFFSET, 0);
157 return cal.getTimeInMillis();
161 * Gets the time represented by this Object
162 * @return the time in milliseconds since the epoch.
164 public long getTime()
171 * Calendar.get(Calendar.ZONE_OFFSET)+Calendar.get(Calendar.DST_OFFSET)
173 * @return The time zone offset in minutes of the local time zone
174 * relative to UTC. The time represented by this object is used to
175 * determine if we should use daylight savings.
177 public int getTimezoneOffset()
179 Calendar cal = Calendar.getInstance();
180 cal.setTimeInMillis(time);
181 return (cal.get(Calendar.ZONE_OFFSET)
182 + cal.get(Calendar.DST_OFFSET)) / (60 * 1000);
186 * Sets the time which this Object should represented.
187 * @param time the time in milliseconds since the epoch. */
188 public void setTime(long time)
194 * Tests if this date is after the specified date.
195 * @param when the other date
196 * @return true, if the date represented by this Object is
197 * strictly later than the time represented by when.
199 public boolean after(Date when)
201 return time > when.time;
205 * Tests if this date is before the specified date.
206 * @param when the other date
207 * @return true, if the date represented by when is strictly later
208 * than the time represented by this object.
210 public boolean before(Date when)
212 return time < when.time;
216 * Compares two dates for equality.
217 * @param obj the object to compare.
218 * @return true, if obj is a Date object and the date represented
219 * by obj is exactly the same as the time represented by this
222 public boolean equals(Object obj)
224 return (obj instanceof Date && time == ((Date) obj).time);
228 * Compares two dates.
229 * @param when the other date.
230 * @return 0, if the date represented
231 * by obj is exactly the same as the time represented by this
232 * object, a negative if this Date is before the other Date, and
233 * a positive value otherwise.
235 public int compareTo(Date when)
237 return (time < when.time) ? -1 : (time == when.time) ? 0 : 1;
241 * Compares this Date to another. This behaves like
242 * <code>compareTo(Date)</code>, but it may throw a
243 * <code>ClassCastException</code>
244 * @param obj the other date.
245 * @return 0, if the date represented
246 * by obj is exactly the same as the time represented by this
247 * object, a negative if this Date is before the other Date, and
248 * a positive value otherwise.
249 * @exception ClassCastException if obj is not of type Date.
251 public int compareTo(Object obj)
253 return compareTo((Date) obj);
256 public int hashCode()
258 return (int) time ^ (int) (time >>> 32);
261 private static final String[] weekNames = { "Sun", "Mon", "Tue", "Wed",
262 "Thu", "Fri", "Sat" };
264 private static final String[] monthNames = { "Jan", "Feb", "Mar", "Apr",
265 "May", "Jun", "Jul", "Aug",
266 "Sep", "Oct", "Nov", "Dec" };
268 public String toString()
270 Calendar cal = Calendar.getInstance();
271 cal.setTimeInMillis(time);
272 String day = "0" + cal.get(Calendar.DATE);
273 String hour = "0" + cal.get(Calendar.HOUR_OF_DAY);
274 String min = "0" + cal.get(Calendar.MINUTE);
275 String sec = "0" + cal.get(Calendar.SECOND);
276 String year = "000" + cal.get(Calendar.YEAR);
277 return weekNames[cal.get(Calendar.DAY_OF_WEEK) - 1] + " "
278 + monthNames[cal.get(Calendar.MONTH)] + " "
279 + day.substring(day.length() - 2) + " "
280 + hour.substring(hour.length() - 2) + ":"
281 + min.substring(min.length() - 2) + ":"
282 + sec.substring(sec.length() - 2) + " "
284 cal.getTimeZone().getDisplayName(cal.getTimeZone().inDaylightTime(this),
285 TimeZone.SHORT) + " " +
286 year.substring(year.length() - 4);
289 /** Format this object in a locale-specific way.
290 * @deprecated Use DateFormat.format(Date)
292 public String toLocaleString()
294 return java.text.DateFormat.getInstance().format(this);
297 /** Format this object in a standard format in the GMT timezone.
298 * @deprecated Use DateFormat.format(Date) with a GMT TimeZone.
300 public String toGMTString()
302 java.text.DateFormat format = java.text.DateFormat.getInstance();
303 format.setTimeZone(TimeZone.getTimeZone("GMT"));
304 return format.format(this);
307 private static int parseTz(String tok, char sign)
308 throws IllegalArgumentException
314 // parseInt doesn't handle '+' so strip off sign.
315 num = Integer.parseInt(tok.substring(1));
317 catch (NumberFormatException ex)
319 throw new IllegalArgumentException(tok);
322 // Convert hours to minutes.
326 num = (num / 100) * 60 + num % 100;
328 return sign == '-' ? -num : num;
331 private static int parseMonth(String tok)
333 // Initialize strings for month names.
334 // We could possibly use the fields of DateFormatSymbols but that is
335 // localized and thus might not match the English words specified.
336 String months[] = { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY",
337 "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER",
338 "NOVEMBER", "DECEMBER" };
341 for (i = 0; i < 12; i++)
342 if (months[i].startsWith(tok))
345 // Return -1 if not found.
349 private static boolean parseDayOfWeek(String tok)
351 // Initialize strings for days of the week names.
352 // We could possibly use the fields of DateFormatSymbols but that is
353 // localized and thus might not match the English words specified.
354 String daysOfWeek[] = { "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
355 "THURSDAY", "FRIDAY", "SATURDAY" };
358 for (i = 0; i < 7; i++)
359 if (daysOfWeek[i].startsWith(tok))
365 /** Parse a String and return the time it represents.
366 * @param s The String to parse.
367 * @deprecated Use DateFormat.parse(String)
369 public static long parse(String string)
371 // Initialize date/time fields before parsing begins.
379 boolean localTimezone = true;
381 // Trim out any nested stuff in parentheses now to make parsing easier.
382 StringBuffer buf = new StringBuffer();
383 int parenNesting = 0;
384 int len = string.length();
385 for (int i = 0; i < len; i++)
387 char ch = string.charAt(i);
388 if (ch >= 'a' && ch <= 'z')
392 else if (parenNesting == 0)
399 // Make all chars upper case to simplify comparisons later.
400 // Also ignore commas; treat them as delimiters.
401 StringTokenizer strtok = new StringTokenizer(buf.toString(), " \t\n\r,");
403 while (strtok.hasMoreTokens())
405 String tok = strtok.nextToken();
406 char firstch = tok.charAt(0);
407 if ((firstch == '+' || firstch == '-') && year >= 0)
409 timezone = parseTz(tok, firstch);
410 localTimezone = false;
412 else if (firstch >= '0' && firstch <= '9')
414 while (tok != null && tok.length() > 0)
416 int punctOffset = tok.length();
419 for (int i = 0; ; i++)
421 if (i >= punctOffset)
428 punct = tok.charAt(i);
429 if (punct >= '0' && punct <= '9')
431 if (num > 999999999) // in case of overflow
432 throw new IllegalArgumentException(tok);
433 num = 10 * num + (punct - '0');
452 && (punct == ' ' || punct == ','
453 || punct == '/' || punct < 0))
454 || (num < 70 && day >= 0 && month >= 0 && year < 0))
460 int curYear = 1900 + new Date().getYear();
461 int firstYear = curYear - 80;
462 year = firstYear / 100 * 100 + num;
463 if (year < firstYear)
467 else if (punct == '/')
474 else if (hour >= 0 && minute < 0)
476 else if (minute >= 0 && second < 0)
481 throw new IllegalArgumentException(tok);
483 // Advance string if there's more to process in this token.
484 if (punct < 0 || punctOffset + 1 >= tok.length())
487 tok = tok.substring(punctOffset + 1);
490 else if (firstch >= 'A' && firstch <= 'Z')
492 if (tok.equals("AM"))
494 if (hour < 1 || hour > 12)
495 throw new IllegalArgumentException(tok);
499 else if (tok.equals("PM"))
501 if (hour < 1 || hour > 12)
502 throw new IllegalArgumentException(tok);
506 else if (parseDayOfWeek(tok))
507 ; // Ignore it; throw the token away.
508 else if (tok.equals("UT") || tok.equals("UTC") || tok.equals("GMT"))
509 localTimezone = false;
510 else if (tok.startsWith("UT") || tok.startsWith("GMT"))
513 if (tok.charAt(1) == 'T' && tok.charAt(2) != 'C')
516 char sign = tok.charAt(signOffset);
517 if (sign != '+' && sign != '-')
518 throw new IllegalArgumentException(tok);
520 timezone = parseTz(tok.substring(signOffset), sign);
521 localTimezone = false;
523 else if ((tmpMonth = parseMonth(tok)) >= 0)
525 else if (tok.length() == 3 && tok.charAt(2) == 'T')
527 // Convert timezone offset from hours to minutes.
528 char ch = tok.charAt(0);
538 throw new IllegalArgumentException(tok);
540 // Shift 60 minutes for Daylight Savings Time.
541 if (tok.charAt(1) == 'D')
543 else if (tok.charAt(1) != 'S')
544 throw new IllegalArgumentException(tok);
546 localTimezone = false;
549 throw new IllegalArgumentException(tok);
552 throw new IllegalArgumentException(tok);
555 // Unspecified hours, minutes, or seconds should default to 0.
563 // Throw exception if any other fields have not been recognized and set.
564 if (year < 0 || month < 0 || day < 0)
565 throw new IllegalArgumentException("Missing field");
567 // Return the time in either local time or relative to GMT as parsed.
568 // If no time-zone was specified, get the local one (in minutes) and
569 // convert to milliseconds before adding to the UTC.
570 GregorianCalendar cal
571 = new GregorianCalendar(year, month, day, hour, minute, second);
574 cal.set(Calendar.ZONE_OFFSET, timezone * 60 * 1000);
575 cal.set(Calendar.DST_OFFSET, 0);
577 return cal.getTimeInMillis();
581 * @return the year minus 1900 represented by this date object.
582 * @deprecated Use Calendar instead of Date, and use get(Calendar.YEAR)
583 * instead. Note about the 1900 difference in year.
587 Calendar cal = Calendar.getInstance();
588 cal.setTimeInMillis(time);
589 return cal.get(Calendar.YEAR) - 1900;
593 * Sets the year to year minus 1900, not changing the other fields.
594 * @param year the year minus 1900.
595 * @deprecated Use Calendar instead of Date, and use
596 * set(Calendar.YEAR, year) instead. Note about the 1900
597 * difference in year.
599 public void setYear(int year)
601 Calendar cal = Calendar.getInstance();
602 cal.setTimeInMillis(time);
603 cal.set(Calendar.YEAR, 1900 + year);
604 time = cal.getTimeInMillis();
608 * @return the month represented by this date object (zero based).
609 * @deprecated Use Calendar instead of Date, and use get(Calendar.MONTH)
612 public int getMonth()
614 Calendar cal = Calendar.getInstance();
615 cal.setTimeInMillis(time);
616 return cal.get(Calendar.MONTH);
620 * Sets the month to the given value, not changing the other fields.
621 * @param month the month, zero based.
622 * @deprecated Use Calendar instead of Date, and use
623 * set(Calendar.MONTH, month) instead.
625 public void setMonth(int month)
627 Calendar cal = Calendar.getInstance();
628 cal.setTimeInMillis(time);
629 cal.set(Calendar.MONTH, month);
630 time = cal.getTimeInMillis();
634 * @return the day of month represented by this date object.
635 * @deprecated Use Calendar instead of Date, and use get(Calendar.DATE)
640 Calendar cal = Calendar.getInstance();
641 cal.setTimeInMillis(time);
642 return cal.get(Calendar.DATE);
646 * Sets the date to the given value, not changing the other fields.
647 * @param date the date.
648 * @deprecated Use Calendar instead of Date, and use
649 * set(Calendar.DATE, date) instead.
651 public void setDate(int date)
653 Calendar cal = Calendar.getInstance();
654 cal.setTimeInMillis(time);
655 cal.set(Calendar.DATE, date);
656 time = cal.getTimeInMillis();
660 * @return the day represented by this date object.
661 * @deprecated Use Calendar instead of Date, and use get(Calendar.DAY_OF_WEEK)
666 Calendar cal = Calendar.getInstance();
667 cal.setTimeInMillis(time);
668 // For Calendar, Sunday is 1. For Date, Sunday is 0.
669 return cal.get(Calendar.DAY_OF_WEEK) - 1;
673 * @return the hours represented by this date object.
674 * @deprecated Use Calendar instead of Date, and use get(Calendar.HOUR_OF_DAY)
677 public int getHours()
679 Calendar cal = Calendar.getInstance();
680 cal.setTimeInMillis(time);
681 return cal.get(Calendar.HOUR_OF_DAY);
685 * Sets the hours to the given value, not changing the other fields.
686 * @param hours the hours.
687 * @deprecated Use Calendar instead of Date, and use
688 * set(Calendar.HOUR_OF_DAY, hours) instead.
690 public void setHours(int hours)
692 Calendar cal = Calendar.getInstance();
693 cal.setTimeInMillis(time);
694 cal.set(Calendar.HOUR_OF_DAY, hours);
695 time = cal.getTimeInMillis();
699 * @return the minutes represented by this date object.
700 * @deprecated Use Calendar instead of Date, and use get(Calendar.MINUTE)
703 public int getMinutes()
705 Calendar cal = Calendar.getInstance();
706 cal.setTimeInMillis(time);
707 return cal.get(Calendar.MINUTE);
711 * Sets the minutes to the given value, not changing the other fields.
712 * @param minutes the minutes.
713 * @deprecated Use Calendar instead of Date, and use
714 * set(Calendar.MINUTE, minutes) instead.
716 public void setMinutes(int minutes)
718 Calendar cal = Calendar.getInstance();
719 cal.setTimeInMillis(time);
720 cal.set(Calendar.MINUTE, minutes);
721 time = cal.getTimeInMillis();
725 * @return the seconds represented by this date object.
726 * @deprecated Use Calendar instead of Date, and use get(Calendar.SECOND)
729 public int getSeconds()
731 Calendar cal = Calendar.getInstance();
732 cal.setTimeInMillis(time);
733 return cal.get(Calendar.SECOND);
737 * Sets the seconds to the given value, not changing the other fields.
738 * @param seconds the seconds.
739 * @deprecated Use Calendar instead of Date, and use
740 * set(Calendar.SECOND, seconds) instead.
742 public void setSeconds(int seconds)
744 Calendar cal = Calendar.getInstance();
745 cal.setTimeInMillis(time);
746 cal.set(Calendar.SECOND, seconds);
747 time = cal.getTimeInMillis();
751 * Reads an Object from the stream.
753 private void readObject(java.io.ObjectInputStream input)
754 throws java.io.IOException, ClassNotFoundException
756 input.defaultReadObject();
757 time = input.readLong();
761 * Writes an Object to the stream.
762 * @serialdata A long value representing the offset from the epoch
763 * in milliseconds. This is the same value that is returned by the
766 private void writeObject(java.io.ObjectOutputStream output)
767 throws java.io.IOException
769 output.defaultWriteObject();
770 output.writeLong(time);