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;
464 if (year < firstYear)
468 else if (punct == '/')
475 else if (hour >= 0 && minute < 0)
477 else if (minute >= 0 && second < 0)
482 throw new IllegalArgumentException(tok);
484 // Advance string if there's more to process in this token.
485 if (punct < 0 || punctOffset + 1 >= tok.length())
488 tok = tok.substring(punctOffset + 1);
491 else if (firstch >= 'A' && firstch <= 'Z')
493 if (tok.equals("AM"))
495 if (hour < 1 || hour > 12)
496 throw new IllegalArgumentException(tok);
500 else if (tok.equals("PM"))
502 if (hour < 1 || hour > 12)
503 throw new IllegalArgumentException(tok);
507 else if (parseDayOfWeek(tok))
508 ; // Ignore it; throw the token away.
509 else if (tok.equals("UT") || tok.equals("UTC") || tok.equals("GMT"))
510 localTimezone = false;
511 else if (tok.startsWith("UT") || tok.startsWith("GMT"))
514 if (tok.charAt(1) == 'T' && tok.charAt(2) != 'C')
517 char sign = tok.charAt(signOffset);
518 if (sign != '+' && sign != '-')
519 throw new IllegalArgumentException(tok);
521 timezone = parseTz(tok.substring(signOffset), sign);
522 localTimezone = false;
524 else if ((tmpMonth = parseMonth(tok)) >= 0)
526 else if (tok.length() == 3 && tok.charAt(2) == 'T')
528 // Convert timezone offset from hours to minutes.
529 char ch = tok.charAt(0);
539 throw new IllegalArgumentException(tok);
541 // Shift 60 minutes for Daylight Savings Time.
542 if (tok.charAt(1) == 'D')
544 else if (tok.charAt(1) != 'S')
545 throw new IllegalArgumentException(tok);
547 localTimezone = false;
550 throw new IllegalArgumentException(tok);
553 throw new IllegalArgumentException(tok);
556 // Unspecified hours, minutes, or seconds should default to 0.
564 // Throw exception if any other fields have not been recognized and set.
565 if (year < 0 || month < 0 || day < 0)
566 throw new IllegalArgumentException("Missing field");
568 // Return the time in either local time or relative to GMT as parsed.
569 // If no time-zone was specified, get the local one (in minutes) and
570 // convert to milliseconds before adding to the UTC.
571 GregorianCalendar cal
572 = new GregorianCalendar(year, month, day, hour, minute, second);
575 cal.set(Calendar.ZONE_OFFSET, timezone * 60 * 1000);
576 cal.set(Calendar.DST_OFFSET, 0);
578 return cal.getTimeInMillis();
582 * @return the year minus 1900 represented by this date object.
583 * @deprecated Use Calendar instead of Date, and use get(Calendar.YEAR)
584 * instead. Note about the 1900 difference in year.
588 Calendar cal = Calendar.getInstance();
589 cal.setTimeInMillis(time);
590 return cal.get(Calendar.YEAR) - 1900;
594 * Sets the year to year minus 1900, not changing the other fields.
595 * @param year the year minus 1900.
596 * @deprecated Use Calendar instead of Date, and use
597 * set(Calendar.YEAR, year) instead. Note about the 1900
598 * difference in year.
600 public void setYear(int year)
602 Calendar cal = Calendar.getInstance();
603 cal.setTimeInMillis(time);
604 cal.set(Calendar.YEAR, 1900 + year);
605 time = cal.getTimeInMillis();
609 * @return the month represented by this date object (zero based).
610 * @deprecated Use Calendar instead of Date, and use get(Calendar.MONTH)
613 public int getMonth()
615 Calendar cal = Calendar.getInstance();
616 cal.setTimeInMillis(time);
617 return cal.get(Calendar.MONTH);
621 * Sets the month to the given value, not changing the other fields.
622 * @param month the month, zero based.
623 * @deprecated Use Calendar instead of Date, and use
624 * set(Calendar.MONTH, month) instead.
626 public void setMonth(int month)
628 Calendar cal = Calendar.getInstance();
629 cal.setTimeInMillis(time);
630 cal.set(Calendar.MONTH, month);
631 time = cal.getTimeInMillis();
635 * @return the day of month represented by this date object.
636 * @deprecated Use Calendar instead of Date, and use get(Calendar.DATE)
641 Calendar cal = Calendar.getInstance();
642 cal.setTimeInMillis(time);
643 return cal.get(Calendar.DATE);
647 * Sets the date to the given value, not changing the other fields.
648 * @param date the date.
649 * @deprecated Use Calendar instead of Date, and use
650 * set(Calendar.DATE, date) instead.
652 public void setDate(int date)
654 Calendar cal = Calendar.getInstance();
655 cal.setTimeInMillis(time);
656 cal.set(Calendar.DATE, date);
657 time = cal.getTimeInMillis();
661 * @return the day represented by this date object.
662 * @deprecated Use Calendar instead of Date, and use get(Calendar.DAY_OF_WEEK)
667 Calendar cal = Calendar.getInstance();
668 cal.setTimeInMillis(time);
669 // For Calendar, Sunday is 1. For Date, Sunday is 0.
670 return cal.get(Calendar.DAY_OF_WEEK) - 1;
674 * @return the hours represented by this date object.
675 * @deprecated Use Calendar instead of Date, and use get(Calendar.HOUR_OF_DAY)
678 public int getHours()
680 Calendar cal = Calendar.getInstance();
681 cal.setTimeInMillis(time);
682 return cal.get(Calendar.HOUR_OF_DAY);
686 * Sets the hours to the given value, not changing the other fields.
687 * @param hours the hours.
688 * @deprecated Use Calendar instead of Date, and use
689 * set(Calendar.HOUR_OF_DAY, hours) instead.
691 public void setHours(int hours)
693 Calendar cal = Calendar.getInstance();
694 cal.setTimeInMillis(time);
695 cal.set(Calendar.HOUR_OF_DAY, hours);
696 time = cal.getTimeInMillis();
700 * @return the minutes represented by this date object.
701 * @deprecated Use Calendar instead of Date, and use get(Calendar.MINUTE)
704 public int getMinutes()
706 Calendar cal = Calendar.getInstance();
707 cal.setTimeInMillis(time);
708 return cal.get(Calendar.MINUTE);
712 * Sets the minutes to the given value, not changing the other fields.
713 * @param minutes the minutes.
714 * @deprecated Use Calendar instead of Date, and use
715 * set(Calendar.MINUTE, minutes) instead.
717 public void setMinutes(int minutes)
719 Calendar cal = Calendar.getInstance();
720 cal.setTimeInMillis(time);
721 cal.set(Calendar.MINUTE, minutes);
722 time = cal.getTimeInMillis();
726 * @return the seconds represented by this date object.
727 * @deprecated Use Calendar instead of Date, and use get(Calendar.SECOND)
730 public int getSeconds()
732 Calendar cal = Calendar.getInstance();
733 cal.setTimeInMillis(time);
734 return cal.get(Calendar.SECOND);
738 * Sets the seconds to the given value, not changing the other fields.
739 * @param seconds the seconds.
740 * @deprecated Use Calendar instead of Date, and use
741 * set(Calendar.SECOND, seconds) instead.
743 public void setSeconds(int seconds)
745 Calendar cal = Calendar.getInstance();
746 cal.setTimeInMillis(time);
747 cal.set(Calendar.SECOND, seconds);
748 time = cal.getTimeInMillis();
752 * Reads an Object from the stream.
754 private void readObject(java.io.ObjectInputStream input)
755 throws java.io.IOException, ClassNotFoundException
757 input.defaultReadObject();
758 time = input.readLong();
762 * Writes an Object to the stream.
763 * @serialdata A long value representing the offset from the epoch
764 * in milliseconds. This is the same value that is returned by the
767 private void writeObject(java.io.ObjectOutputStream output)
768 throws java.io.IOException
770 output.defaultWriteObject();
771 output.writeLong(time);