GNU Classpath (0.20) | |
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: while (tok != null && tok.length() > 0) 776: { 777: int punctOffset = tok.length(); 778: int num = 0; 779: int punct; 780: for (int i = 0; ; i++) 781: { 782: if (i >= punctOffset) 783: { 784: punct = -1; 785: break; 786: } 787: else 788: { 789: punct = tok.charAt(i); 790: if (punct >= '0' && punct <= '9') 791: { 792: if (num > 999999999) // in case of overflow 793: throw new IllegalArgumentException(tok); 794: num = 10 * num + (punct - '0'); 795: } 796: else 797: { 798: punctOffset = i; 799: break; 800: } 801: } 802: 803: } 804: 805: if (punct == ':') 806: { 807: if (hour < 0) 808: hour = num; 809: else 810: minute = num; 811: } 812: else if ((num >= 70 813: && (punct == ' ' || punct == ',' 814: || punct == '/' || punct < 0)) 815: || (num < 70 && day >= 0 && month >= 0 && year < 0)) 816: { 817: if (num >= 100) 818: year = num; 819: else 820: { 821: int curYear = 1900 + new Date().getYear(); 822: int firstYear = curYear - 80; 823: year = firstYear / 100 * 100 + num; 824: if (year < firstYear) 825: year += 100; 826: } 827: } 828: else if (punct == '/') 829: { 830: if (month < 0) 831: month = num - 1; 832: else 833: day = num; 834: } 835: else if (hour >= 0 && minute < 0) 836: minute = num; 837: else if (minute >= 0 && second < 0) 838: second = num; 839: else if (day < 0) 840: day = num; 841: else 842: throw new IllegalArgumentException(tok); 843: 844: // Advance string if there's more to process in this token. 845: if (punct < 0 || punctOffset + 1 >= tok.length()) 846: tok = null; 847: else 848: tok = tok.substring(punctOffset + 1); 849: } 850: } 851: else if (firstch >= 'A' && firstch <= 'Z') 852: { 853: if (tok.equals("AM")) 854: { 855: if (hour < 1 || hour > 12) 856: throw new IllegalArgumentException(tok); 857: if (hour == 12) 858: hour = 0; 859: } 860: else if (tok.equals("PM")) 861: { 862: if (hour < 1 || hour > 12) 863: throw new IllegalArgumentException(tok); 864: if (hour < 12) 865: hour += 12; 866: } 867: else if (parseDayOfWeek(tok)) 868: ; // Ignore it; throw the token away. 869: else if (tok.equals("UT") || tok.equals("UTC") || tok.equals("GMT")) 870: localTimezone = false; 871: else if (tok.startsWith("UT") || tok.startsWith("GMT")) 872: { 873: int signOffset = 3; 874: if (tok.charAt(1) == 'T' && tok.charAt(2) != 'C') 875: signOffset = 2; 876: 877: char sign = tok.charAt(signOffset); 878: if (sign != '+' && sign != '-') 879: throw new IllegalArgumentException(tok); 880: 881: timezone = parseTz(tok.substring(signOffset), sign); 882: localTimezone = false; 883: } 884: else if ((tmpMonth = parseMonth(tok)) >= 0) 885: month = tmpMonth; 886: else if (tok.length() == 3 && tok.charAt(2) == 'T') 887: { 888: // Convert timezone offset from hours to minutes. 889: char ch = tok.charAt(0); 890: if (ch == 'E') 891: timezone = -5 * 60; 892: else if (ch == 'C') 893: timezone = -6 * 60; 894: else if (ch == 'M') 895: timezone = -7 * 60; 896: else if (ch == 'P') 897: timezone = -8 * 60; 898: else 899: throw new IllegalArgumentException(tok); 900: 901: // Shift 60 minutes for Daylight Savings Time. 902: if (tok.charAt(1) == 'D') 903: timezone += 60; 904: else if (tok.charAt(1) != 'S') 905: throw new IllegalArgumentException(tok); 906: 907: localTimezone = false; 908: } 909: else 910: throw new IllegalArgumentException(tok); 911: } 912: else 913: throw new IllegalArgumentException(tok); 914: } 915: 916: // Unspecified hours, minutes, or seconds should default to 0. 917: if (hour < 0) 918: hour = 0; 919: if (minute < 0) 920: minute = 0; 921: if (second < 0) 922: second = 0; 923: 924: // Throw exception if any other fields have not been recognized and set. 925: if (year < 0 || month < 0 || day < 0) 926: throw new IllegalArgumentException("Missing field"); 927: 928: // Return the time in either local time or relative to GMT as parsed. 929: // If no time-zone was specified, get the local one (in minutes) and 930: // convert to milliseconds before adding to the UTC. 931: GregorianCalendar cal 932: = new GregorianCalendar(year, month, day, hour, minute, second); 933: if (!localTimezone) 934: { 935: cal.set(Calendar.ZONE_OFFSET, timezone * 60 * 1000); 936: cal.set(Calendar.DST_OFFSET, 0); 937: } 938: return cal.getTimeInMillis(); 939: } 940: 941: /** 942: * Returns the difference between the year represented by this 943: * <code>Date</code> object and 1900. 944: * 945: * @return the year minus 1900 represented by this date object. 946: * @deprecated Use Calendar instead of Date, and use get(Calendar.YEAR) 947: * instead. Note the 1900 difference in the year. 948: * @see Calendar 949: * @see #setYear(int) 950: */ 951: public int getYear() 952: { 953: Calendar cal = Calendar.getInstance(); 954: cal.setTimeInMillis(time); 955: return cal.get(Calendar.YEAR) - 1900; 956: } 957: 958: /** 959: * Sets the year to the specified year, plus 1900. The other 960: * fields are only altered as required to match the same date 961: * and time in the new year. Usually, this will mean that 962: * the fields are not changed at all, but in the case of 963: * a leap day or leap second, the fields will change in 964: * relation to the existence of such an event in the new year. 965: * For example, if the date specifies February the 29th, 2000, 966: * then this will become March the 1st if the year is changed 967: * to 2001, as 2001 is not a leap year. Similarly, a seconds 968: * value of 60 or 61 may result in the seconds becoming 0 and 969: * the minute increasing by 1, if the new time does not include 970: * a leap second. 971: * 972: * @param year the year minus 1900. 973: * @deprecated Use Calendar instead of Date, and use 974: * set(Calendar.YEAR, year) instead. Note about the 1900 975: * difference in year. 976: * @see #getYear() 977: * @see Calendar 978: */ 979: public void setYear(int year) 980: { 981: Calendar cal = Calendar.getInstance(); 982: cal.setTimeInMillis(time); 983: cal.set(Calendar.YEAR, 1900 + year); 984: time = cal.getTimeInMillis(); 985: } 986: 987: /** 988: * Returns the month represented by this <code>Date</code> object, 989: * as a value between 0 (January) and 11 (December). 990: * 991: * @return the month represented by this date object (zero based). 992: * @deprecated Use Calendar instead of Date, and use get(Calendar.MONTH) 993: * instead. 994: * @see #setMonth(int) 995: * @see Calendar 996: */ 997: public int getMonth() 998: { 999: Calendar cal = Calendar.getInstance(); 1000: cal.setTimeInMillis(time); 1001: return cal.get(Calendar.MONTH); 1002: } 1003: 1004: /** 1005: * Sets the month to the given value. The other 1006: * fields are only altered as necessary to match 1007: * the same date and time in the new month. In most 1008: * cases, the other fields won't change at all. However, 1009: * in the case of a shorter month or a leap second, values 1010: * may be adjusted. For example, if the day of the month 1011: * is currently 31, and the month value is changed from 1012: * January (0) to September (8), the date will become 1013: * October the 1st, as September only has 30 days. Similarly, 1014: * a seconds value of 60 or 61 (a leap second) may result 1015: * in the seconds value being reset to 0 and the minutes 1016: * value being incremented by 1, if the new time does 1017: * not include a leap second. 1018: * 1019: * @param month the month, with a zero-based index 1020: * from January. 1021: * @deprecated Use Calendar instead of Date, and use 1022: * set(Calendar.MONTH, month) instead. 1023: * @see #getMonth() 1024: * @see Calendar 1025: */ 1026: public void setMonth(int month) 1027: { 1028: Calendar cal = Calendar.getInstance(); 1029: cal.setTimeInMillis(time); 1030: cal.set(Calendar.MONTH, month); 1031: time = cal.getTimeInMillis(); 1032: } 1033: 1034: /** 1035: * Returns the day of the month of this <code>Date</code> 1036: * object, as a value between 0 and 31. 1037: * 1038: * @return the day of month represented by this date object. 1039: * @deprecated Use Calendar instead of Date, and use get(Calendar.DATE) 1040: * instead. 1041: * @see Calendar 1042: * @see #setDate(int) 1043: */ 1044: public int getDate() 1045: { 1046: Calendar cal = Calendar.getInstance(); 1047: cal.setTimeInMillis(time); 1048: return cal.get(Calendar.DATE); 1049: } 1050: 1051: /** 1052: * Sets the date to the given value. The other 1053: * fields are only altered as necessary to match 1054: * the same date and time on the new day of the month. In most 1055: * cases, the other fields won't change at all. However, 1056: * in the case of a leap second or the day being out of 1057: * the range of the current month, values 1058: * may be adjusted. For example, if the day of the month 1059: * is currently 30 and the month is June, a new day of the 1060: * month value of 31 will cause the month to change to July, 1061: * as June only has 30 days . Similarly, 1062: * a seconds value of 60 or 61 (a leap second) may result 1063: * in the seconds value being reset to 0 and the minutes 1064: * value being incremented by 1, if the new time does 1065: * not include a leap second. 1066: * 1067: * @param date the date. 1068: * @deprecated Use Calendar instead of Date, and use 1069: * set(Calendar.DATE, date) instead. 1070: * @see Calendar 1071: * @see #getDate() 1072: */ 1073: public void setDate(int date) 1074: { 1075: Calendar cal = Calendar.getInstance(); 1076: cal.setTimeInMillis(time); 1077: cal.set(Calendar.DATE, date); 1078: time = cal.getTimeInMillis(); 1079: } 1080: 1081: /** 1082: * Returns the day represented by this <code>Date</code> 1083: * object as an integer between 0 (Sunday) and 6 (Saturday). 1084: * 1085: * @return the day represented by this date object. 1086: * @deprecated Use Calendar instead of Date, and use get(Calendar.DAY_OF_WEEK) 1087: * instead. 1088: * @see Calendar 1089: */ 1090: public int getDay() 1091: { 1092: Calendar cal = Calendar.getInstance(); 1093: cal.setTimeInMillis(time); 1094: // For Calendar, Sunday is 1. For Date, Sunday is 0. 1095: return cal.get(Calendar.DAY_OF_WEEK) - 1; 1096: } 1097: 1098: /** 1099: * Returns the hours represented by this <code>Date</code> 1100: * object as an integer between 0 and 23. 1101: * 1102: * @return the hours represented by this date object. 1103: * @deprecated Use Calendar instead of Date, and use get(Calendar.HOUR_OF_DAY) 1104: * instead. 1105: * @see Calendar 1106: * @see #setHours(int) 1107: */ 1108: public int getHours() 1109: { 1110: Calendar cal = Calendar.getInstance(); 1111: cal.setTimeInMillis(time); 1112: return cal.get(Calendar.HOUR_OF_DAY); 1113: } 1114: 1115: /** 1116: * Sets the hours to the given value. The other 1117: * fields are only altered as necessary to match 1118: * the same date and time in the new hour. In most 1119: * cases, the other fields won't change at all. However, 1120: * in the case of a leap second, values 1121: * may be adjusted. For example, 1122: * a seconds value of 60 or 61 (a leap second) may result 1123: * in the seconds value being reset to 0 and the minutes 1124: * value being incremented by 1 if the new hour does 1125: * not contain a leap second. 1126: * 1127: * @param hours the hours. 1128: * @deprecated Use Calendar instead of Date, and use 1129: * set(Calendar.HOUR_OF_DAY, hours) instead. 1130: * @see Calendar 1131: * @see #getHours() 1132: */ 1133: public void setHours(int hours) 1134: { 1135: Calendar cal = Calendar.getInstance(); 1136: cal.setTimeInMillis(time); 1137: cal.set(Calendar.HOUR_OF_DAY, hours); 1138: time = cal.getTimeInMillis(); 1139: } 1140: 1141: /** 1142: * Returns the number of minutes represented by the <code>Date</code> 1143: * object, as an integer between 0 and 59. 1144: * 1145: * @return the minutes represented by this date object. 1146: * @deprecated Use Calendar instead of Date, and use get(Calendar.MINUTE) 1147: * instead. 1148: * @see Calendar 1149: * @see #setMinutes(int) 1150: */ 1151: public int getMinutes() 1152: { 1153: Calendar cal = Calendar.getInstance(); 1154: cal.setTimeInMillis(time); 1155: return cal.get(Calendar.MINUTE); 1156: } 1157: 1158: /** 1159: * Sets the minutes to the given value. The other 1160: * fields are only altered as necessary to match 1161: * the same date and time in the new minute. In most 1162: * cases, the other fields won't change at all. However, 1163: * in the case of a leap second, values 1164: * may be adjusted. For example, 1165: * a seconds value of 60 or 61 (a leap second) may result 1166: * in the seconds value being reset to 0 and the minutes 1167: * value being incremented by 1 if the new minute does 1168: * not contain a leap second. 1169: * 1170: * @param minutes the minutes. 1171: * @deprecated Use Calendar instead of Date, and use 1172: * set(Calendar.MINUTE, minutes) instead. 1173: * @see Calendar 1174: * @see #getMinutes() 1175: */ 1176: public void setMinutes(int minutes) 1177: { 1178: Calendar cal = Calendar.getInstance(); 1179: cal.setTimeInMillis(time); 1180: cal.set(Calendar.MINUTE, minutes); 1181: time = cal.getTimeInMillis(); 1182: } 1183: 1184: /** 1185: * Returns the number of seconds represented by the <code>Date</code> 1186: * object, as an integer between 0 and 61 (60 and 61 being leap seconds). 1187: * 1188: * @return the seconds represented by this date object. 1189: * @deprecated Use Calendar instead of Date, and use get(Calendar.SECOND) 1190: * instead. 1191: * @see Calendar 1192: * @see #setSeconds(int) 1193: */ 1194: public int getSeconds() 1195: { 1196: Calendar cal = Calendar.getInstance(); 1197: cal.setTimeInMillis(time); 1198: return cal.get(Calendar.SECOND); 1199: } 1200: 1201: /** 1202: * Sets the seconds to the given value. The other 1203: * fields are only altered as necessary to match 1204: * the same date and time in the new minute. In most 1205: * cases, the other fields won't change at all. However, 1206: * in the case of a leap second, values 1207: * may be adjusted. For example, setting the 1208: * seconds value to 60 or 61 (a leap second) may result 1209: * in the seconds value being reset to 0 and the minutes 1210: * value being incremented by 1, if the current time does 1211: * not contain a leap second. 1212: * 1213: * @param seconds the seconds. 1214: * @deprecated Use Calendar instead of Date, and use 1215: * set(Calendar.SECOND, seconds) instead. 1216: * @see Calendar 1217: * @see #getSeconds() 1218: */ 1219: public void setSeconds(int seconds) 1220: { 1221: Calendar cal = Calendar.getInstance(); 1222: cal.setTimeInMillis(time); 1223: cal.set(Calendar.SECOND, seconds); 1224: time = cal.getTimeInMillis(); 1225: } 1226: 1227: /** 1228: * Deserializes a <code>Date</code> object from an 1229: * input stream, setting the time (in milliseconds 1230: * since the epoch) to the long value read from the 1231: * stream. 1232: * 1233: * @param input the input stream. 1234: * @throws IOException if an I/O error occurs in the stream. 1235: * @throws ClassNotFoundException if the class of the 1236: * serialized object could not be found. 1237: */ 1238: private void readObject(ObjectInputStream input) 1239: throws IOException, ClassNotFoundException 1240: { 1241: input.defaultReadObject(); 1242: time = input.readLong(); 1243: } 1244: 1245: /** 1246: * Serializes a <code>Date</code> object to an output stream, 1247: * storing the time (in milliseconds since the epoch) as a long 1248: * value in the stream. 1249: * 1250: * @serialdata A long value representing the offset from the epoch 1251: * in milliseconds. This is the same value that is returned by the 1252: * method getTime(). 1253: * @param output the output stream. 1254: * @throws IOException if an I/O error occurs in the stream. 1255: */ 1256: private void writeObject(ObjectOutputStream output) 1257: throws IOException 1258: { 1259: output.defaultWriteObject(); 1260: output.writeLong(time); 1261: } 1262: 1263: }
GNU Classpath (0.20) |