2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / java / util / Date.java
blobe81d24aaeb64c73adf91d9eb87d484585c604f7b
1 /* java.util.Date
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)
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. */
39 package java.util;
41 /**
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.
54 * @see Calendar
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
62 /**
63 * This is the serialization UID for this class
65 private static final long serialVersionUID = 7523967970034938905L;
67 /**
68 * The time in milliseconds since the epoch.
70 private transient long time;
72 /**
73 * Creates a new Date Object representing the current time.
75 public Date()
77 time = System.currentTimeMillis();
80 /**
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)
86 this.time = time;
89 /**
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();
99 /**
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)
106 time =
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)
118 time =
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>
126 * @see #parse
127 * @deprecated use <code>java.text.DateFormat.parse(s)</code> instead.
129 public Date(String s)
131 time = parse(s);
134 public Object clone()
138 return super.clone();
140 catch (CloneNotSupportedException ex)
142 return null;
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()
166 return time;
170 * @deprecated use
171 * Calendar.get(Calendar.ZONE_OFFSET)+Calendar.get(Calendar.DST_OFFSET)
172 * instead.
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)
190 this.time = 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
220 * object.
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 skipParens(String string, int offset)
309 int len = string.length();
310 int p = 0;
311 int i;
313 for (i = offset; i < len; ++i)
315 if (string.charAt(i) == '(')
316 ++p;
317 else if (string.charAt(i) == ')')
319 --p;
320 if (p == 0)
321 return i + 1;
322 // If we've encounted unbalanced parens, just return the
323 // leftover one as an ordinary character. It will be
324 // caught later in parsing and cause an
325 // IllegalArgumentException.
326 if (p < 0)
327 return i;
331 // Not sure what to do if `p != 0' here.
332 return i;
335 private static int parseTz(String tok, char sign)
336 throws IllegalArgumentException
338 int num;
342 // parseInt doesn't handle '+' so strip off sign.
343 num = Integer.parseInt(tok.substring(1));
345 catch (NumberFormatException ex)
347 throw new IllegalArgumentException(tok);
350 // Convert hours to minutes.
351 if (num < 24)
352 num *= 60;
353 else
354 num = (num / 100) * 60 + num % 100;
356 return sign == '-' ? -num : num;
359 private static int parseMonth(String tok)
361 // Initialize strings for month names.
362 // We could possibly use the fields of DateFormatSymbols but that is
363 // localized and thus might not match the English words specified.
364 String months[] = { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY",
365 "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER",
366 "NOVEMBER", "DECEMBER" };
368 int i;
369 for (i = 0; i < 12; i++)
370 if (months[i].startsWith(tok))
371 return i;
373 // Return -1 if not found.
374 return -1;
377 private static boolean parseDayOfWeek(String tok)
379 // Initialize strings for days of the week names.
380 // We could possibly use the fields of DateFormatSymbols but that is
381 // localized and thus might not match the English words specified.
382 String daysOfWeek[] = { "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
383 "THURSDAY", "FRIDAY", "SATURDAY" };
385 int i;
386 for (i = 0; i < 7; i++)
387 if (daysOfWeek[i].startsWith(tok))
388 return true;
390 return false;
393 /** Parse a String and return the time it represents.
394 * @param s The String to parse.
395 * @deprecated Use DateFormat.parse(String)
397 public static long parse(String string)
399 // Initialize date/time fields before parsing begins.
400 int year = -1;
401 int month = -1;
402 int day = -1;
403 int hour = -1;
404 int minute = -1;
405 int second = -1;
406 int timezone = 0;
407 boolean localTimezone = true;
409 // Trim out any nested stuff in parentheses now to make parsing easier.
410 StringBuffer buf = new StringBuffer();
411 int off = 0;
412 int openParenOffset, tmpMonth;
413 while ((openParenOffset = string.indexOf('(', off)) >= 0)
415 // Copy part of string leading up to open paren.
416 buf.append(string.substring(off, openParenOffset));
417 off = skipParens(string, openParenOffset);
419 buf.append(string.substring(off));
421 // Make all chars upper case to simplify comparisons later.
422 // Also ignore commas; treat them as delimiters.
423 StringTokenizer strtok =
424 new StringTokenizer(buf.toString().toUpperCase(), " \t\n\r,");
426 while (strtok.hasMoreTokens())
428 String tok = strtok.nextToken();
429 char firstch = tok.charAt(0);
430 if ((firstch == '+' || firstch == '-') && year >= 0)
432 timezone = parseTz(tok, firstch);
433 localTimezone = false;
435 else if (firstch >= '0' && firstch <= '9')
437 while (tok != null && tok.length() > 0)
439 // A colon or slash may be valid in the number.
440 // Find the first of these before calling parseInt.
441 int colon = tok.indexOf(':');
442 int slash = tok.indexOf('/');
443 int hyphen = tok.indexOf('-');
444 // We choose tok.length initially because it makes
445 // processing simpler.
446 int punctOffset = tok.length();
447 if (colon >= 0)
448 punctOffset = Math.min(punctOffset, colon);
449 if (slash >= 0)
450 punctOffset = Math.min(punctOffset, slash);
451 if (hyphen >= 0)
452 punctOffset = Math.min(punctOffset, hyphen);
453 // Following code relies on -1 being the exceptional
454 // case.
455 if (punctOffset == tok.length())
456 punctOffset = -1;
458 int num;
461 num = Integer.parseInt(punctOffset < 0 ? tok :
462 tok.substring(0, punctOffset));
464 catch (NumberFormatException ex)
466 throw new IllegalArgumentException(tok);
469 // TBD: Spec says year can be followed by a slash. That might
470 // make sense if using YY/MM/DD formats, but it would fail in
471 // that format for years <= 70. Also, what about 1900? That
472 // is interpreted as the year 3800; seems that the comparison
473 // should be num >= 1900 rather than just > 1900.
474 // What about a year of 62 - 70? (61 or less could be a (leap)
475 // second). 70/MM/DD cause an exception but 71/MM/DD is ok
476 // even though there's no ambiguity in either case.
477 // For the parse method, the spec as written seems too loose.
478 // Until shown otherwise, we'll follow the spec as written.
479 if (num > 70 && (punctOffset < 0 || punctOffset == slash))
480 year = num > 1900 ? num - 1900 : num;
481 else if (punctOffset > 0 && punctOffset == colon)
483 if (hour < 0)
484 hour = num;
485 else
486 minute = num;
488 else if (punctOffset > 0 && punctOffset == slash)
490 if (month < 0)
491 month = num - 1;
492 else
493 day = num;
495 else if (hour >= 0 && minute < 0)
496 minute = num;
497 else if (minute >= 0 && second < 0)
498 second = num;
499 else if (day < 0)
500 day = num;
501 else
502 throw new IllegalArgumentException(tok);
504 // Advance string if there's more to process in this token.
505 if (punctOffset < 0 || punctOffset + 1 >= tok.length())
506 tok = null;
507 else
508 tok = tok.substring(punctOffset + 1);
511 else if (firstch >= 'A' && firstch <= 'Z')
513 if (tok.equals("AM"))
515 if (hour < 1 || hour > 12)
516 throw new IllegalArgumentException(tok);
517 if (hour == 12)
518 hour = 0;
520 else if (tok.equals("PM"))
522 if (hour < 1 || hour > 12)
523 throw new IllegalArgumentException(tok);
524 if (hour < 12)
525 hour += 12;
527 else if (parseDayOfWeek(tok))
528 ; // Ignore it; throw the token away.
529 else if (tok.equals("UT") || tok.equals("UTC") || tok.equals("GMT"))
530 localTimezone = false;
531 else if (tok.startsWith("UT") || tok.startsWith("GMT"))
533 int signOffset = 3;
534 if (tok.charAt(1) == 'T' && tok.charAt(2) != 'C')
535 signOffset = 2;
537 char sign = tok.charAt(signOffset);
538 if (sign != '+' && sign != '-')
539 throw new IllegalArgumentException(tok);
541 timezone = parseTz(tok.substring(signOffset), sign);
542 localTimezone = false;
544 else if ((tmpMonth = parseMonth(tok)) >= 0)
545 month = tmpMonth;
546 else if (tok.length() == 3 && tok.charAt(2) == 'T')
548 // Convert timezone offset from hours to minutes.
549 char ch = tok.charAt(0);
550 if (ch == 'E')
551 timezone = -5 * 60;
552 else if (ch == 'C')
553 timezone = -6 * 60;
554 else if (ch == 'M')
555 timezone = -7 * 60;
556 else if (ch == 'P')
557 timezone = -8 * 60;
558 else
559 throw new IllegalArgumentException(tok);
561 // Shift 60 minutes for Daylight Savings Time.
562 if (tok.charAt(1) == 'D')
563 timezone += 60;
564 else if (tok.charAt(1) != 'S')
565 throw new IllegalArgumentException(tok);
567 localTimezone = false;
569 else
570 throw new IllegalArgumentException(tok);
572 else
573 throw new IllegalArgumentException(tok);
576 // Unspecified minutes and seconds should default to 0.
577 if (minute < 0)
578 minute = 0;
579 if (second < 0)
580 second = 0;
582 // Throw exception if any other fields have not been recognized and set.
583 if (year < 0 || month < 0 || day < 0 || hour < 0)
584 throw new IllegalArgumentException("Missing field");
586 // Return the time in either local time or relative to GMT as parsed.
587 // If no time-zone was specified, get the local one (in minutes) and
588 // convert to milliseconds before adding to the UTC.
589 return UTC(year, month, day, hour, minute, second) + (localTimezone ?
590 new Date(year, month, day).getTimezoneOffset() * 60 * 1000:
591 -timezone * 60 * 1000);
595 * @return the year minus 1900 represented by this date object.
596 * @deprecated Use Calendar instead of Date, and use get(Calendar.YEAR)
597 * instead. Note about the 1900 difference in year.
599 public int getYear()
601 Calendar cal = Calendar.getInstance();
602 cal.setTimeInMillis(time);
603 return cal.get(Calendar.YEAR) - 1900;
607 * Sets the year to year minus 1900, not changing the other fields.
608 * @param year the year minus 1900.
609 * @deprecated Use Calendar instead of Date, and use
610 * set(Calendar.YEAR, year) instead. Note about the 1900
611 * difference in year.
613 public void setYear(int year)
615 Calendar cal = Calendar.getInstance();
616 cal.setTimeInMillis(time);
617 cal.set(Calendar.YEAR, 1900 + year);
618 time = cal.getTimeInMillis();
622 * @return the month represented by this date object (zero based).
623 * @deprecated Use Calendar instead of Date, and use get(Calendar.MONTH)
624 * instead.
626 public int getMonth()
628 Calendar cal = Calendar.getInstance();
629 cal.setTimeInMillis(time);
630 return cal.get(Calendar.MONTH);
634 * Sets the month to the given value, not changing the other fields.
635 * @param month the month, zero based.
636 * @deprecated Use Calendar instead of Date, and use
637 * set(Calendar.MONTH, month) instead.
639 public void setMonth(int month)
641 Calendar cal = Calendar.getInstance();
642 cal.setTimeInMillis(time);
643 cal.set(Calendar.MONTH, month);
644 time = cal.getTimeInMillis();
648 * @return the day of month represented by this date object.
649 * @deprecated Use Calendar instead of Date, and use get(Calendar.DATE)
650 * instead.
652 public int getDate()
654 Calendar cal = Calendar.getInstance();
655 cal.setTimeInMillis(time);
656 return cal.get(Calendar.DATE);
660 * Sets the date to the given value, not changing the other fields.
661 * @param date the date.
662 * @deprecated Use Calendar instead of Date, and use
663 * set(Calendar.DATE, date) instead.
665 public void setDate(int date)
667 Calendar cal = Calendar.getInstance();
668 cal.setTimeInMillis(time);
669 cal.set(Calendar.DATE, date);
670 time = cal.getTimeInMillis();
674 * @return the day represented by this date object.
675 * @deprecated Use Calendar instead of Date, and use get(Calendar.DAY_OF_WEEK)
676 * instead.
678 public int getDay()
680 Calendar cal = Calendar.getInstance();
681 cal.setTimeInMillis(time);
682 // For Calendar, Sunday is 1. For Date, Sunday is 0.
683 return cal.get(Calendar.DAY_OF_WEEK) - 1;
687 * @return the hours represented by this date object.
688 * @deprecated Use Calendar instead of Date, and use get(Calendar.HOUR_OF_DAY)
689 * instead.
691 public int getHours()
693 Calendar cal = Calendar.getInstance();
694 cal.setTimeInMillis(time);
695 return cal.get(Calendar.HOUR_OF_DAY);
699 * Sets the hours to the given value, not changing the other fields.
700 * @param hours the hours.
701 * @deprecated Use Calendar instead of Date, and use
702 * set(Calendar.HOUR_OF_DAY, hours) instead.
704 public void setHours(int hours)
706 Calendar cal = Calendar.getInstance();
707 cal.setTimeInMillis(time);
708 cal.set(Calendar.HOUR_OF_DAY, hours);
709 time = cal.getTimeInMillis();
713 * @return the minutes represented by this date object.
714 * @deprecated Use Calendar instead of Date, and use get(Calendar.MINUTE)
715 * instead.
717 public int getMinutes()
719 Calendar cal = Calendar.getInstance();
720 cal.setTimeInMillis(time);
721 return cal.get(Calendar.MINUTE);
725 * Sets the minutes to the given value, not changing the other fields.
726 * @param minutes the minutes.
727 * @deprecated Use Calendar instead of Date, and use
728 * set(Calendar.MINUTE, minutes) instead.
730 public void setMinutes(int minutes)
732 Calendar cal = Calendar.getInstance();
733 cal.setTimeInMillis(time);
734 cal.set(Calendar.MINUTE, minutes);
735 time = cal.getTimeInMillis();
739 * @return the seconds represented by this date object.
740 * @deprecated Use Calendar instead of Date, and use get(Calendar.SECOND)
741 * instead.
743 public int getSeconds()
745 Calendar cal = Calendar.getInstance();
746 cal.setTimeInMillis(time);
747 return cal.get(Calendar.SECOND);
751 * Sets the seconds to the given value, not changing the other fields.
752 * @param seconds the seconds.
753 * @deprecated Use Calendar instead of Date, and use
754 * set(Calendar.SECOND, seconds) instead.
756 public void setSeconds(int seconds)
758 Calendar cal = Calendar.getInstance();
759 cal.setTimeInMillis(time);
760 cal.set(Calendar.SECOND, seconds);
761 time = cal.getTimeInMillis();
765 * Reads an Object from the stream.
767 private void readObject(java.io.ObjectInputStream input)
768 throws java.io.IOException, ClassNotFoundException
770 input.defaultReadObject();
771 time = input.readLong();
775 * Writes an Object to the stream.
776 * @serialdata A long value representing the offset from the epoch
777 * in milliseconds. This is the same value that is returned by the
778 * method getTime().
780 private void writeObject(java.io.ObjectOutputStream output)
781 throws java.io.IOException
783 output.defaultWriteObject();
784 output.writeLong(time);