Frames | No Frames |
1: /* java.util.Date 2: Copyright (C) 1998, 1999, 2000, 2001, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: package java.util; 39: 40: import java.io.IOException; 41: import java.io.ObjectInputStream; 42: import java.io.ObjectOutputStream; 43: import java.io.Serializable; 44: import java.text.DateFormat; 45: import java.text.SimpleDateFormat; 46: 47: /** 48: * <p> 49: * This class represents a specific time in milliseconds since the epoch. 50: * The epoch is 1970, January 1 00:00:00.0000 UTC. 51: * </p> 52: * <p> 53: * <code>Date</code> is intended to reflect universal time coordinate (UTC), 54: * but this depends on the underlying host environment. Most operating systems 55: * don't handle the leap second, which occurs about once every year or 56: * so. The leap second is added to the last minute of the day on either 57: * the 30th of June or the 31st of December, creating a minute 61 seconds 58: * in length. 59: * </p> 60: * <p> 61: * The representations of the date fields are as follows: 62: * <ul> 63: * <li> 64: * Years are specified as the difference between the year 65: * and 1900. Thus, the final year used is equal to 66: * 1900 + y, where y is the input value. 67: * </li> 68: * <li> 69: * Months are represented using zero-based indexing, 70: * making 0 January and 11 December. 71: * </li> 72: * <li> 73: * Dates are represented with the usual values of 74: * 1 through to 31. 75: * </li> 76: * <li> 77: * Hours are represented in the twenty-four hour clock, 78: * with integer values from 0 to 23. 12am is 0, and 79: * 12pm is 12. 80: * </li> 81: * <li> 82: * Minutes are again as usual, with values from 0 to 59. 83: * </li> 84: * <li> 85: * Seconds are represented with the values 0 through to 61, 86: * with 60 and 61 being leap seconds (as per the ISO C standard). 87: * </li> 88: * </ul> 89: * </p> 90: * <p> 91: * Prior to JDK 1.1, this class was the sole class handling date and time 92: * related functionality. However, this particular solution was not 93: * amenable to internationalization. The new <code>Calendar</code> 94: * class should now be used to handle dates and times, with <code>Date</code> 95: * being used only for values in milliseconds since the epoch. The 96: * <code>Calendar</code> class, and its concrete implementations, handle 97: * the interpretation of these values into minutes, hours, days, months 98: * and years. The formatting and parsing of dates is left to the 99: * <code>DateFormat</code> class, which is able to handle the different 100: * types of date format which occur in different locales. 101: * </p> 102: * 103: * @see Calendar 104: * @see GregorianCalendar 105: * @see java.text.DateFormat 106: * @author Jochen Hoenicke 107: * @author Per Bothner (bothner@cygnus.com) 108: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 109: */ 110: public class Date 111: implements Cloneable, Comparable, Serializable 112: { 113: /** 114: * This is the serialization UID for this class 115: * for compatability with Sun's JDK. 116: */ 117: private static final long serialVersionUID = 7523967970034938905L; 118: 119: /** 120: * The time in milliseconds since the epoch. 121: */ 122: private transient long time; 123: 124: /** 125: * An array of week names used to map names to integer values. 126: */ 127: private static final String[] weekNames = { "Sun", "Mon", "Tue", "Wed", 128: "Thu", "Fri", "Sat" }; 129: /** 130: * An array of month names used to map names to integer values. 131: */ 132: private static final String[] monthNames = { "Jan", "Feb", "Mar", "Apr", 133: "May", "Jun", "Jul", "Aug", 134: "Sep", "Oct", "Nov", "Dec" }; 135: /** 136: * Creates a new Date Object representing the current time. 137: */ 138: public Date() 139: { 140: time = System.currentTimeMillis(); 141: } 142: 143: /** 144: * Creates a new Date Object representing the given time. 145: * 146: * @param time the time in milliseconds since the epoch. 147: */ 148: public Date(long time) 149: { 150: this.time = time; 151: } 152: 153: /** 154: * Creates a new Date Object representing the given time. 155: * 156: * @deprecated use <code>new GregorianCalendar(year+1900, month, 157: * day)</code> instead. 158: * @param year the difference between the required year and 1900. 159: * @param month the month as a value between 0 and 11. 160: * @param day the day as a value between 0 and 31. 161: */ 162: public Date(int year, int month, int day) 163: { 164: this(year, month, day, 0, 0, 0); 165: } 166: 167: /** 168: * Creates a new Date Object representing the given time. 169: * 170: * @deprecated use <code>new GregorianCalendar(year+1900, month, 171: * day, hour, min)</code> instead. 172: * @param year the difference between the required year and 1900. 173: * @param month the month as a value between 0 and 11. 174: * @param day the day as a value between 0 and 31. 175: * @param hour the hour as a value between 0 and 23, in 24-hour 176: * clock notation. 177: * @param min the minute as a value between 0 and 59. 178: */ 179: public Date(int year, int month, int day, int hour, int min) 180: { 181: this(year, month, day, hour, min, 0); 182: } 183: 184: /** 185: * Creates a new Date Object representing the given time. 186: * 187: * @deprecated use <code>new GregorianCalendar(year+1900, month, 188: * day, hour, min, sec)</code> instead. 189: * @param year the difference between the required year and 1900. 190: * @param month the month as a value between 0 and 11. 191: * @param day the day as a value between 0 and 31. 192: * @param hour the hour as a value between 0 and 23, in 24-hour 193: * clock notation. 194: * @param min the minute as a value between 0 and 59. 195: * @param sec the second as a value between 0 and 61 (with 60 196: * and 61 being leap seconds). 197: */ 198: public Date(int year, int month, int day, int hour, int min, int sec) 199: { 200: GregorianCalendar cal = 201: new GregorianCalendar(year + 1900, month, day, hour, min, sec); 202: time = cal.getTimeInMillis(); 203: } 204: 205: /** 206: * Creates a new Date from the given string representation. This 207: * does the same as <code>new Date(Date.parse(s))</code> 208: * @see #parse 209: * @deprecated use <code>java.text.DateFormat.parse(s)</code> instead. 210: */ 211: public Date(String s) 212: { 213: time = parse(s); 214: } 215: 216: /** 217: * Returns a copy of this <code>Date</code> object. 218: * 219: * @return a copy, or null if the object couldn't be 220: * cloned. 221: * @see Object#clone() 222: */ 223: public Object clone() 224: { 225: try 226: { 227: return super.clone(); 228: } 229: catch (CloneNotSupportedException ex) 230: { 231: return null; 232: } 233: } 234: 235: /** 236: * Returns the number of milliseconds since the epoch 237: * specified by the given arguments. The arguments are 238: * interpreted relative to UTC rather than the local 239: * time zone. 240: * 241: * @deprecated Use <code>Calendar</code> with a UTC 242: * <code>TimeZone</code> instead. 243: * @param year the difference between the required year and 1900. 244: * @param month the month as a value between 0 and 11. 245: * @param date the day as a value between 0 and 31. 246: * @param hrs the hour as a value between 0 and 23, in 24-hour 247: * clock notation. 248: * @param min the minute as a value between 0 and 59. 249: * @param sec the second as a value between 0 and 61 (with 60 250: * and 61 being leap seconds). 251: * @return the time in milliseconds since the epoch. 252: */ 253: public static long UTC(int year, int month, int date, 254: int hrs, int min, int sec) 255: { 256: GregorianCalendar cal = 257: new GregorianCalendar(year + 1900, month, date, hrs, min, sec); 258: cal.set(Calendar.ZONE_OFFSET, 0); 259: cal.set(Calendar.DST_OFFSET, 0); 260: return cal.getTimeInMillis(); 261: } 262: 263: /** 264: * Gets the time represented by this object. 265: * 266: * @return the time in milliseconds since the epoch. 267: */ 268: public long getTime() 269: { 270: return time; 271: } 272: 273: /** 274: * Returns the number of minutes offset used with UTC to give the time 275: * represented by this object in the current time zone. The date information 276: * from this object is also used to determine whether or not daylight savings 277: * time is in effect. For example, the offset for the UK would be 0 if the 278: * month of the date object was January, and 1 if the month was August. 279: * 280: * @deprecated use 281: * <code>Calendar.get(Calendar.ZONE_OFFSET)+Calendar.get(Calendar.DST_OFFSET)</code> 282: * instead. 283: * @return The time zone offset in minutes of the local time zone 284: * relative to UTC. The time represented by this object is used to 285: * determine if we should use daylight savings. 286: */ 287: public int getTimezoneOffset() 288: { 289: Calendar cal = Calendar.getInstance(); 290: cal.setTimeInMillis(time); 291: return - (cal.get(Calendar.ZONE_OFFSET) 292: + cal.get(Calendar.DST_OFFSET)) / (60 * 1000); 293: } 294: 295: /** 296: * Sets the time which this object should represent. 297: * 298: * @param time the time in milliseconds since the epoch. 299: */ 300: public void setTime(long time) 301: { 302: this.time = time; 303: } 304: 305: /** 306: * Tests if this date is after the specified date. 307: * 308: * @param when the other date 309: * @return true, if the date represented by this object is 310: * strictly later than the time represented by when. 311: */ 312: public boolean after(Date when) 313: { 314: return time > when.time; 315: } 316: 317: /** 318: * Tests if this date is before the specified date. 319: * 320: * @param when the other date 321: * @return true, if the date represented by when is strictly later 322: * than the time represented by this object. 323: */ 324: public boolean before(Date when) 325: { 326: return time < when.time; 327: } 328: 329: /** 330: * Compares two dates for equality. 331: * 332: * @param obj the object to compare. 333: * @return true, if obj is a Date object and the time represented 334: * by obj is exactly the same as the time represented by this 335: * object. 336: */ 337: public boolean equals(Object obj) 338: { 339: return (obj instanceof Date && time == ((Date) obj).time); 340: } 341: 342: /** 343: * Compares two dates. 344: * 345: * @param when the other date. 346: * @return 0, if the date represented 347: * by obj is exactly the same as the time represented by this 348: * object, a negative if this Date is before the other Date, and 349: * a positive value otherwise. 350: */ 351: public int compareTo(Date when) 352: { 353: return (time < when.time) ? -1 : (time == when.time) ? 0 : 1; 354: } 355: 356: /** 357: * Compares this Date to another object. This behaves like 358: * <code>compareTo(Date)</code>, but it takes a generic object 359: * and throws a <code>ClassCastException</code> if obj is 360: * not a <code>Date</code>. 361: * 362: * @param obj the other date. 363: * @return 0, if the date represented 364: * by obj is exactly the same as the time represented by this 365: * object, a negative if this Date is before the other Date, and 366: * a positive value otherwise. 367: * @exception ClassCastException if obj is not of type Date. 368: */ 369: public int compareTo(Object obj) 370: { 371: return compareTo((Date) obj); 372: } 373: 374: /** 375: * Computes the hash code of this <code>Date</code> as the 376: * XOR of the most significant and the least significant 377: * 32 bits of the 64 bit milliseconds value. 378: * 379: * @return the hash code. 380: */ 381: public int hashCode() 382: { 383: return (int) time ^ (int) (time >>> 32); 384: } 385: 386: /** 387: * <p> 388: * Returns a string representation of this date using 389: * the following date format: 390: * </p> 391: * <p> 392: * <code>day mon dd hh:mm:ss zz yyyy</code> 393: * </p> 394: * <p>where the fields used here are: 395: * <ul> 396: * <li> 397: * <code>day</code> -- the day of the week 398: * (Sunday through to Saturday). 399: * </li> 400: * <li> 401: * <code>mon</code> -- the month (Jan to Dec). 402: * </li> 403: * <li> 404: * <code>dd</code> -- the day of the month 405: * as two decimal digits (01 to 31). 406: * </li> 407: * <li> 408: * <code>hh</code> -- the hour of the day 409: * as two decimal digits in 24-hour clock notation 410: * (01 to 23). 411: * </li> 412: * <li> 413: * <code>mm</code> -- the minute of the day 414: * as two decimal digits (01 to 59). 415: * </li> 416: * <li> 417: * <code>ss</code> -- the second of the day 418: * as two decimal digits (01 to 61). 419: * </li> 420: * <li> 421: * <code>zz</code> -- the time zone information if available. 422: * The possible time zones used include the abbreviations 423: * recognised by <code>parse()</code> (e.g. GMT, CET, etc.) 424: * and may reflect the fact that daylight savings time is in 425: * effect. The empty string is used if there is no time zone 426: * information. 427: * </li> 428: * <li> 429: * <code>yyyy</code> -- the year as four decimal digits. 430: * </li> 431: * </ul> 432: * <p> 433: * The <code>DateFormat</code> class should now be 434: * preferred over using this method. 435: * </p> 436: * 437: * @return A string of the form 'day mon dd hh:mm:ss zz yyyy' 438: * @see #parse(String) 439: * @see DateFormat 440: */ 441: public String toString() 442: { 443: Calendar cal = Calendar.getInstance(); 444: cal.setTimeInMillis(time); 445: String day = "0" + cal.get(Calendar.DATE); 446: String hour = "0" + cal.get(Calendar.HOUR_OF_DAY); 447: String min = "0" + cal.get(Calendar.MINUTE); 448: String sec = "0" + cal.get(Calendar.SECOND); 449: String year = "000" + cal.get(Calendar.YEAR); 450: return weekNames[cal.get(Calendar.DAY_OF_WEEK) - 1] + " " 451: + monthNames[cal.get(Calendar.MONTH)] + " " 452: + day.substring(day.length() - 2) + " " 453: + hour.substring(hour.length() - 2) + ":" 454: + min.substring(min.length() - 2) + ":" 455: + sec.substring(sec.length() - 2) + " " 456: + 457: cal.getTimeZone().getDisplayName(cal.getTimeZone().inDaylightTime(this), 458: TimeZone.SHORT) + " " + 459: year.substring(year.length() - 4); 460: } 461: 462: /** 463: * Returns a locale-dependent string representation of this 464: * <code>Date</code> object. 465: * 466: * @deprecated Use DateFormat.format(Date) 467: * @return A locale-dependent string representation. 468: * @see #parse(String) 469: * @see DateFormat 470: */ 471: public String toLocaleString() 472: { 473: return java.text.DateFormat.getInstance().format(this); 474: } 475: 476: /** 477: * <p> 478: * Returns a string representation of this <code>Date</code> 479: * object using GMT rather than the local timezone. 480: * The following date format is used: 481: * </p> 482: * <p> 483: * <code>d mon yyyy hh:mm:ss GMT</code> 484: * </p> 485: * <p>where the fields used here are: 486: * <ul> 487: * <li> 488: * <code>d</code> -- the day of the month 489: * as one or two decimal digits (1 to 31). 490: * </li> 491: * <li> 492: * <code>mon</code> -- the month (Jan to Dec). 493: * </li> 494: * <li> 495: * <code>yyyy</code> -- the year as four decimal digits. 496: * </li> 497: * <li> 498: * <code>hh</code> -- the hour of the day 499: * as two decimal digits in 24-hour clock notation 500: * (01 to 23). 501: * </li> 502: * <li> 503: * <code>mm</code> -- the minute of the day 504: * as two decimal digits (01 to 59). 505: * </li> 506: * <li> 507: * <code>ss</code> -- the second of the day 508: * as two decimal digits (01 to 61). 509: * </li> 510: * <li> 511: * <code>GMT</code> -- the literal string "GMT" 512: * indicating Greenwich Mean Time as opposed to 513: * the local timezone. 514: * </li> 515: * </ul> 516: * 517: * @deprecated Use DateFormat.format(Date) with a GMT TimeZone. 518: * @return A string of the form 'd mon yyyy hh:mm:ss GMT' using 519: * GMT as opposed to the local timezone. 520: * @see #parse(String) 521: * @see DateFormat 522: */ 523: public String toGMTString() 524: { 525: java.text.DateFormat format = java.text.DateFormat.getInstance(); 526: format.setTimeZone(TimeZone.getTimeZone("GMT")); 527: return format.format(this); 528: } 529: 530: /** 531: * Parses the time zone string. 532: * 533: * @param tok The token containing the time zone. 534: * @param sign The sign (+ or -) used by the time zone. 535: * @return An integer representing the number of minutes offset 536: * from GMT for the time zone. 537: */ 538: private static int parseTz(String tok, char sign) 539: throws IllegalArgumentException 540: { 541: int num; 542: 543: try 544: { 545: // parseInt doesn't handle '+' so strip off sign. 546: num = Integer.parseInt(tok.substring(1)); 547: } 548: catch (NumberFormatException ex) 549: { 550: throw new IllegalArgumentException(tok); 551: } 552: 553: // Convert hours to minutes. 554: if (num < 24) 555: num *= 60; 556: else 557: num = (num / 100) * 60 + num % 100; 558: 559: return sign == '-' ? -num : num; 560: } 561: 562: /** 563: * Parses the month string. 564: * 565: * @param tok the token containing the month. 566: * @return An integer between 0 and 11, representing 567: * a month from January (0) to December (11), 568: * or -1 if parsing failed. 569: */ 570: private static int parseMonth(String tok) 571: { 572: // Initialize strings for month names. 573: // We could possibly use the fields of DateFormatSymbols but that is 574: // localized and thus might not match the English words specified. 575: String months[] = { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", 576: "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", 577: "NOVEMBER", "DECEMBER" }; 578: 579: int i; 580: for (i = 0; i < 12; i++) 581: if (months[i].startsWith(tok)) 582: return i; 583: 584: // Return -1 if not found. 585: return -1; 586: } 587: 588: /** 589: * Parses the day of the week string. 590: * 591: * @param tok the token containing the day of the week. 592: * @return true if the token was parsed successfully. 593: */ 594: private static boolean parseDayOfWeek(String tok) 595: { 596: // Initialize strings for days of the week names. 597: // We could possibly use the fields of DateFormatSymbols but that is 598: // localized and thus might not match the English words specified. 599: String daysOfWeek[] = { "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", 600: "THURSDAY", "FRIDAY", "SATURDAY" }; 601: 602: int i; 603: for (i = 0; i < 7; i++) 604: if (daysOfWeek[i].startsWith(tok)) 605: return true; 606: 607: return false; 608: } 609: 610: /** 611: * <p> 612: * Parses a String and returns the time, in milliseconds since the 613: * epoch, it represents. Most syntaxes are handled, including 614: * the IETF date standard "day, dd mon yyyy hh:mm:ss zz" (see 615: * <code>toString()</code> for definitions of these fields). 616: * Standard U.S. time zone abbreviations are recognised, in 617: * addition to time zone offsets in positive or negative minutes. 618: * If a time zone is specified, the specified time is assumed to 619: * be in UTC and the appropriate conversion is applied, following 620: * parsing, to convert this to the local time zone. If no zone 621: * is specified, the time is assumed to already be in the local 622: * time zone. 623: * </p> 624: * <p> 625: * The method parses the string progressively from left to right. 626: * At the end of the parsing process, either a time is returned 627: * or an <code>IllegalArgumentException</code> is thrown to signify 628: * failure. The ASCII characters A-Z, a-z, 0-9, and ',', '+', '-', 629: * ':' and '/' are the only characters permitted within the string, 630: * besides whitespace and characters enclosed within parantheses 631: * '(' and ')'. 632: * </p> 633: * <p> 634: * A sequence of consecutive digits are recognised as a number, 635: * and interpreted as follows: 636: * <ul> 637: * <li> 638: * A number preceded by a sign (+ or -) is taken to be a time zone 639: * offset. The time zone offset can be specified in either hours 640: * or minutes. The former is assumed if the number is less than 24. 641: * Otherwise, the offset is assumed to be in minutes. A - indicates 642: * a time zone west of GMT, while a + represents a time zone to the 643: * east of GMT. The time zones are always assumed to be relative 644: * to GMT, and a (redundant) specification of this can be included 645: * with the time zone. For example, '-9', 'utc-9' and 'GMT-9' all 646: * represent a time zone nine hours west of GMT. Similarly, 647: * '+4', 'ut+4' and 'UTC+4' all give 4 hours east of GMT. 648: * </li> 649: * <li> 650: * A number equal to or greater than 70 is regarded as a year specification. 651: * Values lower than 70 are only assumed to indicate a year if both the 652: * day of the month and the month itself have already been recognised. 653: * Year values less than 100 are interpreted as being relative to the current 654: * century when the <code>Date</code> class is initialised.. Given a century, 655: * x, the year is assumed to be within the range x - 80 to x + 19. The value 656: * itself is then used as a match against the two last digits of one of these 657: * years. For example, take x to be 2004. A two-digit year is assumed to fall 658: * within the range x - 80 (1924) and x + 19 (2023). Thus, any intepreted value 659: * between 0 and 23 is assumed to be 2000 to 2023 and values between 24 and 99 660: * are taken as being 1924 to 1999. This only applies for the case of 2004. 661: * With a different year, the values will be interpreted differently. 2005 662: * will used 0 to 24 as 2000 to 2024 and 25 to 99 as 1925 to 1999, for example. 663: * This behaviour differs from that of <code>SimpleDateFormat</code> and is 664: * time-dependent (a two-digit year will be interpreted differently depending 665: * on the time the code is run). 666: * </li> 667: * <li> 668: * Numbers followed by a colon are interpreted by first an hour, and then 669: * as a minute, once an hour has been found. 670: * </li> 671: * <li> 672: * <li> 673: * Numbers followed by a slash are regarded first as a month, and then as 674: * a day of the month once the month has been found. This follows the 675: * U.S. date format of mm/dd, rather than the European dd/mm. Months 676: * are converted to the recognised value - 1 before storage, in order 677: * to put the number within the range 0 to 11. 678: * </li> 679: * <li> 680: * Numbers followed by commas, whitespace, hyphens or the end of the string 681: * are interpreted in the following order: hour, minute, second, day of month. 682: * The first type not already recognised in the current string being parsed is 683: * assumed. 684: * </li> 685: * </ul> 686: * </p> 687: * <p> 688: * A sequence of consecutive alphabetic characters is recognised as a word, 689: * and interpreted as follows, in a case-insentive fashion: 690: * <ul> 691: * <li> 692: * The characters 'AM' or 'PM' restrict the hour value to a value between 0 693: * and 12. In the latter case, 12 is added to the hour value before storage. 694: * </li> 695: * <li> 696: * Any words which match any prefix of one of the days of the week ('Monday', 697: * 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' and 'Sunday'), 698: * are simply ignored. 699: * </li> 700: * <li> 701: * Any words which match any prefix of one of the months of the year ('January', 702: * 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 703: * 'October', 'November', 'December') are recognised and interpreted as the 704: * appropriate value between 0 and 11. The first match made against a 705: * month is the one used, in the order specified here. For example, 'Ma' is 706: * intepreted as 'March' (2) and not as 'May' (4). Similarly, 'Ju' is 'June', 707: * and not 'July'. 708: * </li> 709: * <li> 710: * The words 'GMT', 'UT' and 'UTC' are interpreted as specifying UTC as the 711: * time zone in use for this date. 712: * </li> 713: * <li> 714: * The word pairs 'EST'/'EDT', 'CST'/'CDT', 'MST'/'MDT' and 'PST'/'PDT' are 715: * interpreted as the appropriate U.S. time zone abbreviation. Each pair 716: * is the standard and daylight savings time zone specification, respectively, 717: * for each zone within the U.S, these being Eastern Standard/Daylight Time 718: * (-5), Central Standard/Daylight Time (-6), Mountain Standard/Daylight Time 719: * (-7) and Pacific Standard/Daylight Time (-8). 720: * </li> 721: * </ul> 722: * 723: * @param string The String to parse. 724: * @return The time in milliseconds since the epoch. 725: * @throws IllegalArgumentException if the string fails to parse. 726: * @deprecated Use DateFormat.parse(String) 727: * @see #toString() 728: * @see SimpleDateFormat 729: */ 730: public static long parse(String string) 731: { 732: // Initialize date/time fields before parsing begins. 733: int year = -1; 734: int month = -1; 735: int day = -1; 736: int hour = -1; 737: int minute = -1; 738: int second = -1; 739: int timezone = 0; 740: boolean localTimezone = true; 741: 742: // Trim out any nested stuff in parentheses now to make parsing easier. 743: StringBuffer buf = new StringBuffer(); 744: int parenNesting = 0; 745: int len = string.length(); 746: for (int i = 0; i < len; i++) 747: { 748: char ch = string.charAt(i); 749: if (ch >= 'a' && ch <= 'z') 750: ch -= 'a' - 'A'; 751: if (ch == '(') 752: parenNesting++; 753: else if (parenNesting == 0) 754: buf.append(ch); 755: else if (ch == ')') 756: parenNesting--; 757: } 758: int tmpMonth; 759: 760: // Make all chars upper case to simplify comparisons later. 761: // Also ignore commas; treat them as delimiters. 762: StringTokenizer strtok = new StringTokenizer(buf.toString(), " \t\n\r,"); 763: 764: while (strtok.hasMoreTokens()) 765: { 766: String tok = strtok.nextToken(); 767: char firstch = tok.charAt(0); 768: if ((firstch == '+' || firstch == '-') && year >= 0) 769: { 770: timezone = parseTz(tok, firstch); 771: localTimezone = false; 772: } 773: else if (firstch >= '0' && firstch <= '9') 774: { 775: int lastPunct = -1; 776: while (tok != null && tok.length() > 0) 777: { 778: int punctOffset = tok.length(); 779: int num = 0; 780: int punct; 781: for (int i = 0; ; i++) 782: { 783: if (i >= punctOffset) 784: { 785: punct = -1; 786: break; 787: } 788: else 789: { 790: punct = tok.charAt(i); 791: if (punct >= '0' && punct <= '9') 792: { 793: if (num > 999999999) // in case of overflow 794: throw new IllegalArgumentException(tok); 795: num = 10 * num + (punct - '0'); 796: } 797: else 798: { 799: punctOffset = i; 800: break; 801: } 802: } 803: 804: } 805: 806: if (punct == ':') 807: { 808: if (hour < 0) 809: hour = num; 810: else 811: minute = num; 812: } 813: else if (lastPunct == ':' && hour >= 0 && (minute < 0 || second < 0)) 814: { 815: if (minute < 0) 816: minute = num; 817: else 818: second = num; 819: } 820: else if ((num >= 70 821: && (punct == ' ' || punct == ',' 822: || punct == '/' || punct < 0)) 823: || (num < 70 && day >= 0 && month >= 0 && year < 0)) 824: { 825: if (num >= 100) 826: year = num; 827: else 828: { 829: int curYear = 1900 + new Date().getYear(); 830: int firstYear = curYear - 80; 831: year = firstYear / 100 * 100 + num; 832: if (year < firstYear) 833: year += 100; 834: } 835: } 836: else if (punct == '/') 837: { 838: if (month < 0) 839: month = num - 1; 840: else 841: day = num; 842: } 843: else if (hour >= 0 && minute < 0) 844: minute = num; 845: else if (minute >= 0 && second < 0) 846: second = num; 847: else if (day < 0) 848: day = num; 849: else 850: throw new IllegalArgumentException(tok); 851: 852: // Advance string if there's more to process in this token. 853: if (punct < 0 || punctOffset + 1 >= tok.length()) 854: tok = null; 855: else 856: tok = tok.substring(punctOffset + 1); 857: lastPunct = punct; 858: } 859: } 860: else if (firstch >= 'A' && firstch <= 'Z') 861: { 862: if (tok.equals("AM")) 863: { 864: if (hour < 1 || hour > 12) 865: throw new IllegalArgumentException(tok); 866: if (hour == 12) 867: hour = 0; 868: } 869: else if (tok.equals("PM")) 870: { 871: if (hour < 1 || hour > 12) 872: throw new IllegalArgumentException(tok); 873: if (hour < 12) 874: hour += 12; 875: } 876: else if (parseDayOfWeek(tok)) 877: ; // Ignore it; throw the token away. 878: else if (tok.equals("UT") || tok.equals("UTC") || tok.equals("GMT")) 879: localTimezone = false; 880: else if (tok.startsWith("UT") || tok.startsWith("GMT")) 881: { 882: int signOffset = 3; 883: if (tok.charAt(1) == 'T' && tok.charAt(2) != 'C') 884: signOffset = 2; 885: 886: char sign = tok.charAt(signOffset); 887: if (sign != '+' && sign != '-') 888: throw new IllegalArgumentException(tok); 889: 890: timezone = parseTz(tok.substring(signOffset), sign); 891: localTimezone = false; 892: } 893: else if ((tmpMonth = parseMonth(tok)) >= 0) 894: month = tmpMonth; 895: else if (tok.length() == 3 && tok.charAt(2) == 'T') 896: { 897: // Convert timezone offset from hours to minutes. 898: char ch = tok.charAt(0); 899: if (ch == 'E') 900: timezone = -5 * 60; 901: else if (ch == 'C') 902: timezone = -6 * 60; 903: else if (ch == 'M') 904: timezone = -7 * 60; 905: else if (ch == 'P') 906: timezone = -8 * 60; 907: else 908: throw new IllegalArgumentException(tok); 909: 910: // Shift 60 minutes for Daylight Savings Time. 911: if (tok.charAt(1) == 'D') 912: timezone += 60; 913: else if (tok.charAt(1) != 'S') 914: throw new IllegalArgumentException(tok); 915: 916: localTimezone = false; 917: } 918: else 919: throw new IllegalArgumentException(tok); 920: } 921: else 922: throw new IllegalArgumentException(tok); 923: } 924: 925: // Unspecified hours, minutes, or seconds should default to 0. 926: if (hour < 0) 927: hour = 0; 928: if (minute < 0) 929: minute = 0; 930: if (second < 0) 931: second = 0; 932: 933: // Throw exception if any other fields have not been recognized and set. 934: if (year < 0 || month < 0 || day < 0) 935: throw new IllegalArgumentException("Missing field"); 936: 937: // Return the time in either local time or relative to GMT as parsed. 938: // If no time-zone was specified, get the local one (in minutes) and 939: // convert to milliseconds before adding to the UTC. 940: GregorianCalendar cal 941: = new GregorianCalendar(year, month, day, hour, minute, second); 942: if (!localTimezone) 943: { 944: cal.set(Calendar.ZONE_OFFSET, timezone * 60 * 1000); 945: cal.set(Calendar.DST_OFFSET, 0); 946: } 947: return cal.getTimeInMillis(); 948: } 949: 950: /** 951: * Returns the difference between the year represented by this 952: * <code>Date</code> object and 1900. 953: * 954: * @return the year minus 1900 represented by this date object. 955: * @deprecated Use Calendar instead of Date, and use get(Calendar.YEAR) 956: * instead. Note the 1900 difference in the year. 957: * @see Calendar 958: * @see #setYear(int) 959: */ 960: public int getYear() 961: { 962: Calendar cal = Calendar.getInstance(); 963: cal.setTimeInMillis(time); 964: return cal.get(Calendar.YEAR) - 1900; 965: } 966: 967: /** 968: * Sets the year to the specified year, plus 1900. The other 969: * fields are only altered as required to match the same date 970: * and time in the new year. Usually, this will mean that 971: * the fields are not changed at all, but in the case of 972: * a leap day or leap second, the fields will change in 973: * relation to the existence of such an event in the new year. 974: * For example, if the date specifies February the 29th, 2000, 975: * then this will become March the 1st if the year is changed 976: * to 2001, as 2001 is not a leap year. Similarly, a seconds 977: * value of 60 or 61 may result in the seconds becoming 0 and 978: * the minute increasing by 1, if the new time does not include 979: * a leap second. 980: * 981: * @param year the year minus 1900. 982: * @deprecated Use Calendar instead of Date, and use 983: * set(Calendar.YEAR, year) instead. Note about the 1900 984: * difference in year. 985: * @see #getYear() 986: * @see Calendar 987: */ 988: public void setYear(int year) 989: { 990: Calendar cal = Calendar.getInstance(); 991: cal.setTimeInMillis(time); 992: cal.set(Calendar.YEAR, 1900 + year); 993: time = cal.getTimeInMillis(); 994: } 995: 996: /** 997: * Returns the month represented by this <code>Date</code> object, 998: * as a value between 0 (January) and 11 (December). 999: * 1000: * @return the month represented by this date object (zero based). 1001: * @deprecated Use Calendar instead of Date, and use get(Calendar.MONTH) 1002: * instead. 1003: * @see #setMonth(int) 1004: * @see Calendar 1005: */ 1006: public int getMonth() 1007: { 1008: Calendar cal = Calendar.getInstance(); 1009: cal.setTimeInMillis(time); 1010: return cal.get(Calendar.MONTH); 1011: } 1012: 1013: /** 1014: * Sets the month to the given value. The other 1015: * fields are only altered as necessary to match 1016: * the same date and time in the new month. In most 1017: * cases, the other fields won't change at all. However, 1018: * in the case of a shorter month or a leap second, values 1019: * may be adjusted. For example, if the day of the month 1020: * is currently 31, and the month value is changed from 1021: * January (0) to September (8), the date will become 1022: * October the 1st, as September only has 30 days. Similarly, 1023: * a seconds value of 60 or 61 (a leap second) may result 1024: * in the seconds value being reset to 0 and the minutes 1025: * value being incremented by 1, if the new time does 1026: * not include a leap second. 1027: * 1028: * @param month the month, with a zero-based index 1029: * from January. 1030: * @deprecated Use Calendar instead of Date, and use 1031: * set(Calendar.MONTH, month) instead. 1032: * @see #getMonth() 1033: * @see Calendar 1034: */ 1035: public void setMonth(int month) 1036: { 1037: Calendar cal = Calendar.getInstance(); 1038: cal.setTimeInMillis(time); 1039: cal.set(Calendar.MONTH, month); 1040: time = cal.getTimeInMillis(); 1041: } 1042: 1043: /** 1044: * Returns the day of the month of this <code>Date</code> 1045: * object, as a value between 0 and 31. 1046: * 1047: * @return the day of month represented by this date object. 1048: * @deprecated Use Calendar instead of Date, and use get(Calendar.DATE) 1049: * instead. 1050: * @see Calendar 1051: * @see #setDate(int) 1052: */ 1053: public int getDate() 1054: { 1055: Calendar cal = Calendar.getInstance(); 1056: cal.setTimeInMillis(time); 1057: return cal.get(Calendar.DATE); 1058: } 1059: 1060: /** 1061: * Sets the date to the given value. The other 1062: * fields are only altered as necessary to match 1063: * the same date and time on the new day of the month. In most 1064: * cases, the other fields won't change at all. However, 1065: * in the case of a leap second or the day being out of 1066: * the range of the current month, values 1067: * may be adjusted. For example, if the day of the month 1068: * is currently 30 and the month is June, a new day of the 1069: * month value of 31 will cause the month to change to July, 1070: * as June only has 30 days . Similarly, 1071: * a seconds value of 60 or 61 (a leap second) may result 1072: * in the seconds value being reset to 0 and the minutes 1073: * value being incremented by 1, if the new time does 1074: * not include a leap second. 1075: * 1076: * @param date the date. 1077: * @deprecated Use Calendar instead of Date, and use 1078: * set(Calendar.DATE, date) instead. 1079: * @see Calendar 1080: * @see #getDate() 1081: */ 1082: public void setDate(int date) 1083: { 1084: Calendar cal = Calendar.getInstance(); 1085: cal.setTimeInMillis(time); 1086: cal.set(Calendar.DATE, date); 1087: time = cal.getTimeInMillis(); 1088: } 1089: 1090: /** 1091: * Returns the day represented by this <code>Date</code> 1092: * object as an integer between 0 (Sunday) and 6 (Saturday). 1093: * 1094: * @return the day represented by this date object. 1095: * @deprecated Use Calendar instead of Date, and use get(Calendar.DAY_OF_WEEK) 1096: * instead. 1097: * @see Calendar 1098: */ 1099: public int getDay() 1100: { 1101: Calendar cal = Calendar.getInstance(); 1102: cal.setTimeInMillis(time); 1103: // For Calendar, Sunday is 1. For Date, Sunday is 0. 1104: return cal.get(Calendar.DAY_OF_WEEK) - 1; 1105: } 1106: 1107: /** 1108: * Returns the hours represented by this <code>Date</code> 1109: * object as an integer between 0 and 23. 1110: * 1111: * @return the hours represented by this date object. 1112: * @deprecated Use Calendar instead of Date, and use get(Calendar.HOUR_OF_DAY) 1113: * instead. 1114: * @see Calendar 1115: * @see #setHours(int) 1116: */ 1117: public int getHours() 1118: { 1119: Calendar cal = Calendar.getInstance(); 1120: cal.setTimeInMillis(time); 1121: return cal.get(Calendar.HOUR_OF_DAY); 1122: } 1123: 1124: /** 1125: * Sets the hours to the given value. The other 1126: * fields are only altered as necessary to match 1127: * the same date and time in the new hour. In most 1128: * cases, the other fields won't change at all. However, 1129: * in the case of a leap second, values 1130: * may be adjusted. For example, 1131: * a seconds value of 60 or 61 (a leap second) may result 1132: * in the seconds value being reset to 0 and the minutes 1133: * value being incremented by 1 if the new hour does 1134: * not contain a leap second. 1135: * 1136: * @param hours the hours. 1137: * @deprecated Use Calendar instead of Date, and use 1138: * set(Calendar.HOUR_OF_DAY, hours) instead. 1139: * @see Calendar 1140: * @see #getHours() 1141: */ 1142: public void setHours(int hours) 1143: { 1144: Calendar cal = Calendar.getInstance(); 1145: cal.setTimeInMillis(time); 1146: cal.set(Calendar.HOUR_OF_DAY, hours); 1147: time = cal.getTimeInMillis(); 1148: } 1149: 1150: /** 1151: * Returns the number of minutes represented by the <code>Date</code> 1152: * object, as an integer between 0 and 59. 1153: * 1154: * @return the minutes represented by this date object. 1155: * @deprecated Use Calendar instead of Date, and use get(Calendar.MINUTE) 1156: * instead. 1157: * @see Calendar 1158: * @see #setMinutes(int) 1159: */ 1160: public int getMinutes() 1161: { 1162: Calendar cal = Calendar.getInstance(); 1163: cal.setTimeInMillis(time); 1164: return cal.get(Calendar.MINUTE); 1165: } 1166: 1167: /** 1168: * Sets the minutes to the given value. The other 1169: * fields are only altered as necessary to match 1170: * the same date and time in the new minute. In most 1171: * cases, the other fields won't change at all. However, 1172: * in the case of a leap second, values 1173: * may be adjusted. For example, 1174: * a seconds value of 60 or 61 (a leap second) may result 1175: * in the seconds value being reset to 0 and the minutes 1176: * value being incremented by 1 if the new minute does 1177: * not contain a leap second. 1178: * 1179: * @param minutes the minutes. 1180: * @deprecated Use Calendar instead of Date, and use 1181: * set(Calendar.MINUTE, minutes) instead. 1182: * @see Calendar 1183: * @see #getMinutes() 1184: */ 1185: public void setMinutes(int minutes) 1186: { 1187: Calendar cal = Calendar.getInstance(); 1188: cal.setTimeInMillis(time); 1189: cal.set(Calendar.MINUTE, minutes); 1190: time = cal.getTimeInMillis(); 1191: } 1192: 1193: /** 1194: * Returns the number of seconds represented by the <code>Date</code> 1195: * object, as an integer between 0 and 61 (60 and 61 being leap seconds). 1196: * 1197: * @return the seconds represented by this date object. 1198: * @deprecated Use Calendar instead of Date, and use get(Calendar.SECOND) 1199: * instead. 1200: * @see Calendar 1201: * @see #setSeconds(int) 1202: */ 1203: public int getSeconds() 1204: { 1205: Calendar cal = Calendar.getInstance(); 1206: cal.setTimeInMillis(time); 1207: return cal.get(Calendar.SECOND); 1208: } 1209: 1210: /** 1211: * Sets the seconds to the given value. The other 1212: * fields are only altered as necessary to match 1213: * the same date and time in the new minute. In most 1214: * cases, the other fields won't change at all. However, 1215: * in the case of a leap second, values 1216: * may be adjusted. For example, setting the 1217: * seconds value to 60 or 61 (a leap second) may result 1218: * in the seconds value being reset to 0 and the minutes 1219: * value being incremented by 1, if the current time does 1220: * not contain a leap second. 1221: * 1222: * @param seconds the seconds. 1223: * @deprecated Use Calendar instead of Date, and use 1224: * set(Calendar.SECOND, seconds) instead. 1225: * @see Calendar 1226: * @see #getSeconds() 1227: */ 1228: public void setSeconds(int seconds) 1229: { 1230: Calendar cal = Calendar.getInstance(); 1231: cal.setTimeInMillis(time); 1232: cal.set(Calendar.SECOND, seconds); 1233: time = cal.getTimeInMillis(); 1234: } 1235: 1236: /** 1237: * Deserializes a <code>Date</code> object from an 1238: * input stream, setting the time (in milliseconds 1239: * since the epoch) to the long value read from the 1240: * stream. 1241: * 1242: * @param input the input stream. 1243: * @throws IOException if an I/O error occurs in the stream. 1244: * @throws ClassNotFoundException if the class of the 1245: * serialized object could not be found. 1246: */ 1247: private void readObject(ObjectInputStream input) 1248: throws IOException, ClassNotFoundException 1249: { 1250: input.defaultReadObject(); 1251: time = input.readLong(); 1252: } 1253: 1254: /** 1255: * Serializes a <code>Date</code> object to an output stream, 1256: * storing the time (in milliseconds since the epoch) as a long 1257: * value in the stream. 1258: * 1259: * @serialdata A long value representing the offset from the epoch 1260: * in milliseconds. This is the same value that is returned by the 1261: * method getTime(). 1262: * @param output the output stream. 1263: * @throws IOException if an I/O error occurs in the stream. 1264: */ 1265: private void writeObject(ObjectOutputStream output) 1266: throws IOException 1267: { 1268: output.defaultWriteObject(); 1269: output.writeLong(time); 1270: } 1271: 1272: }