Date.java revision 9e78cee3f3edf84254174717f475605d712aad1c
1/* 2 * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package java.util; 27 28import java.text.DateFormat; 29import java.io.IOException; 30import java.io.ObjectOutputStream; 31import java.io.ObjectInputStream; 32import java.lang.ref.SoftReference; 33import sun.util.calendar.BaseCalendar; 34import sun.util.calendar.CalendarDate; 35import sun.util.calendar.CalendarSystem; 36import sun.util.calendar.CalendarUtils; 37import sun.util.calendar.Era; 38import sun.util.calendar.Gregorian; 39 40/** 41 * The class <code>Date</code> represents a specific instant 42 * in time, with millisecond precision. 43 * <p> 44 * Prior to JDK 1.1, the class <code>Date</code> had two additional 45 * functions. It allowed the interpretation of dates as year, month, day, hour, 46 * minute, and second values. It also allowed the formatting and parsing 47 * of date strings. Unfortunately, the API for these functions was not 48 * amenable to internationalization. As of JDK 1.1, the 49 * <code>Calendar</code> class should be used to convert between dates and time 50 * fields and the <code>DateFormat</code> class should be used to format and 51 * parse date strings. 52 * The corresponding methods in <code>Date</code> are deprecated. 53 * <p> 54 * Although the <code>Date</code> class is intended to reflect 55 * coordinated universal time (UTC), it may not do so exactly, 56 * depending on the host environment of the Java Virtual Machine. 57 * Nearly all modern operating systems assume that 1 day = 58 * 24 × 60 × 60 = 86400 seconds 59 * in all cases. In UTC, however, about once every year or two there 60 * is an extra second, called a "leap second." The leap 61 * second is always added as the last second of the day, and always 62 * on December 31 or June 30. For example, the last minute of the 63 * year 1995 was 61 seconds long, thanks to an added leap second. 64 * Most computer clocks are not accurate enough to be able to reflect 65 * the leap-second distinction. 66 * <p> 67 * Some computer standards are defined in terms of Greenwich mean 68 * time (GMT), which is equivalent to universal time (UT). GMT is 69 * the "civil" name for the standard; UT is the 70 * "scientific" name for the same standard. The 71 * distinction between UTC and UT is that UTC is based on an atomic 72 * clock and UT is based on astronomical observations, which for all 73 * practical purposes is an invisibly fine hair to split. Because the 74 * earth's rotation is not uniform (it slows down and speeds up 75 * in complicated ways), UT does not always flow uniformly. Leap 76 * seconds are introduced as needed into UTC so as to keep UTC within 77 * 0.9 seconds of UT1, which is a version of UT with certain 78 * corrections applied. There are other time and date systems as 79 * well; for example, the time scale used by the satellite-based 80 * global positioning system (GPS) is synchronized to UTC but is 81 * <i>not</i> adjusted for leap seconds. An interesting source of 82 * further information is the U.S. Naval Observatory, particularly 83 * the Directorate of Time at: 84 * <blockquote><pre> 85 * <a href=http://tycho.usno.navy.mil>http://tycho.usno.navy.mil</a> 86 * </pre></blockquote> 87 * <p> 88 * and their definitions of "Systems of Time" at: 89 * <blockquote><pre> 90 * <a href=http://tycho.usno.navy.mil/systime.html>http://tycho.usno.navy.mil/systime.html</a> 91 * </pre></blockquote> 92 * <p> 93 * In all methods of class <code>Date</code> that accept or return 94 * year, month, date, hours, minutes, and seconds values, the 95 * following representations are used: 96 * <ul> 97 * <li>A year <i>y</i> is represented by the integer 98 * <i>y</i> <code>- 1900</code>. 99 * <li>A month is represented by an integer from 0 to 11; 0 is January, 100 * 1 is February, and so forth; thus 11 is December. 101 * <li>A date (day of month) is represented by an integer from 1 to 31 102 * in the usual manner. 103 * <li>An hour is represented by an integer from 0 to 23. Thus, the hour 104 * from midnight to 1 a.m. is hour 0, and the hour from noon to 1 105 * p.m. is hour 12. 106 * <li>A minute is represented by an integer from 0 to 59 in the usual manner. 107 * <li>A second is represented by an integer from 0 to 61; the values 60 and 108 * 61 occur only for leap seconds and even then only in Java 109 * implementations that actually track leap seconds correctly. Because 110 * of the manner in which leap seconds are currently introduced, it is 111 * extremely unlikely that two leap seconds will occur in the same 112 * minute, but this specification follows the date and time conventions 113 * for ISO C. 114 * </ul> 115 * <p> 116 * In all cases, arguments given to methods for these purposes need 117 * not fall within the indicated ranges; for example, a date may be 118 * specified as January 32 and is interpreted as meaning February 1. 119 * 120 * @author James Gosling 121 * @author Arthur van Hoff 122 * @author Alan Liu 123 * @see java.text.DateFormat 124 * @see java.util.Calendar 125 * @see java.util.TimeZone 126 * @since JDK1.0 127 */ 128public class Date 129 implements java.io.Serializable, Cloneable, Comparable<Date> 130{ 131 private static final BaseCalendar gcal = 132 CalendarSystem.getGregorianCalendar(); 133 private static BaseCalendar jcal; 134 135 private transient long fastTime; 136 137 /* 138 * If cdate is null, then fastTime indicates the time in millis. 139 * If cdate.isNormalized() is true, then fastTime and cdate are in 140 * synch. Otherwise, fastTime is ignored, and cdate indicates the 141 * time. 142 */ 143 private transient BaseCalendar.Date cdate; 144 145 // Initialized just before the value is used. See parse(). 146 private static int defaultCenturyStart; 147 148 /* use serialVersionUID from modified java.util.Date for 149 * interoperability with JDK1.1. The Date was modified to write 150 * and read only the UTC time. 151 */ 152 private static final long serialVersionUID = 7523967970034938905L; 153 154 /** 155 * Allocates a <code>Date</code> object and initializes it so that 156 * it represents the time at which it was allocated, measured to the 157 * nearest millisecond. 158 * 159 * @see java.lang.System#currentTimeMillis() 160 */ 161 public Date() { 162 this(System.currentTimeMillis()); 163 } 164 165 /** 166 * Allocates a <code>Date</code> object and initializes it to 167 * represent the specified number of milliseconds since the 168 * standard base time known as "the epoch", namely January 1, 169 * 1970, 00:00:00 GMT. 170 * 171 * @param date the milliseconds since January 1, 1970, 00:00:00 GMT. 172 * @see java.lang.System#currentTimeMillis() 173 */ 174 public Date(long date) { 175 fastTime = date; 176 } 177 178 /** 179 * Allocates a <code>Date</code> object and initializes it so that 180 * it represents midnight, local time, at the beginning of the day 181 * specified by the <code>year</code>, <code>month</code>, and 182 * <code>date</code> arguments. 183 * 184 * @param year the year minus 1900. 185 * @param month the month between 0-11. 186 * @param date the day of the month between 1-31. 187 * @see java.util.Calendar 188 * @deprecated As of JDK version 1.1, 189 * replaced by <code>Calendar.set(year + 1900, month, date)</code> 190 * or <code>GregorianCalendar(year + 1900, month, date)</code>. 191 */ 192 @Deprecated 193 public Date(int year, int month, int date) { 194 this(year, month, date, 0, 0, 0); 195 } 196 197 /** 198 * Allocates a <code>Date</code> object and initializes it so that 199 * it represents the instant at the start of the minute specified by 200 * the <code>year</code>, <code>month</code>, <code>date</code>, 201 * <code>hrs</code>, and <code>min</code> arguments, in the local 202 * time zone. 203 * 204 * @param year the year minus 1900. 205 * @param month the month between 0-11. 206 * @param date the day of the month between 1-31. 207 * @param hrs the hours between 0-23. 208 * @param min the minutes between 0-59. 209 * @see java.util.Calendar 210 * @deprecated As of JDK version 1.1, 211 * replaced by <code>Calendar.set(year + 1900, month, date, 212 * hrs, min)</code> or <code>GregorianCalendar(year + 1900, 213 * month, date, hrs, min)</code>. 214 */ 215 @Deprecated 216 public Date(int year, int month, int date, int hrs, int min) { 217 this(year, month, date, hrs, min, 0); 218 } 219 220 /** 221 * Allocates a <code>Date</code> object and initializes it so that 222 * it represents the instant at the start of the second specified 223 * by the <code>year</code>, <code>month</code>, <code>date</code>, 224 * <code>hrs</code>, <code>min</code>, and <code>sec</code> arguments, 225 * in the local time zone. 226 * 227 * @param year the year minus 1900. 228 * @param month the month between 0-11. 229 * @param date the day of the month between 1-31. 230 * @param hrs the hours between 0-23. 231 * @param min the minutes between 0-59. 232 * @param sec the seconds between 0-59. 233 * @see java.util.Calendar 234 * @deprecated As of JDK version 1.1, 235 * replaced by <code>Calendar.set(year + 1900, month, date, 236 * hrs, min, sec)</code> or <code>GregorianCalendar(year + 1900, 237 * month, date, hrs, min, sec)</code>. 238 */ 239 @Deprecated 240 public Date(int year, int month, int date, int hrs, int min, int sec) { 241 int y = year + 1900; 242 // month is 0-based. So we have to normalize month to support Long.MAX_VALUE. 243 if (month >= 12) { 244 y += month / 12; 245 month %= 12; 246 } else if (month < 0) { 247 y += CalendarUtils.floorDivide(month, 12); 248 month = CalendarUtils.mod(month, 12); 249 } 250 BaseCalendar cal = getCalendarSystem(y); 251 cdate = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.getDefaultRef()); 252 cdate.setNormalizedDate(y, month + 1, date).setTimeOfDay(hrs, min, sec, 0); 253 getTimeImpl(); 254 cdate = null; 255 } 256 257 /** 258 * Allocates a <code>Date</code> object and initializes it so that 259 * it represents the date and time indicated by the string 260 * <code>s</code>, which is interpreted as if by the 261 * {@link Date#parse} method. 262 * 263 * @param s a string representation of the date. 264 * @see java.text.DateFormat 265 * @see java.util.Date#parse(java.lang.String) 266 * @deprecated As of JDK version 1.1, 267 * replaced by <code>DateFormat.parse(String s)</code>. 268 */ 269 @Deprecated 270 public Date(String s) { 271 this(parse(s)); 272 } 273 274 /** 275 * Return a copy of this object. 276 */ 277 public Object clone() { 278 Date d = null; 279 try { 280 d = (Date)super.clone(); 281 if (cdate != null) { 282 d.cdate = (BaseCalendar.Date) cdate.clone(); 283 } 284 } catch (CloneNotSupportedException e) {} // Won't happen 285 return d; 286 } 287 288 /** 289 * Determines the date and time based on the arguments. The 290 * arguments are interpreted as a year, month, day of the month, 291 * hour of the day, minute within the hour, and second within the 292 * minute, exactly as for the <tt>Date</tt> constructor with six 293 * arguments, except that the arguments are interpreted relative 294 * to UTC rather than to the local time zone. The time indicated is 295 * returned represented as the distance, measured in milliseconds, 296 * of that time from the epoch (00:00:00 GMT on January 1, 1970). 297 * 298 * @param year the year minus 1900. 299 * @param month the month between 0-11. 300 * @param date the day of the month between 1-31. 301 * @param hrs the hours between 0-23. 302 * @param min the minutes between 0-59. 303 * @param sec the seconds between 0-59. 304 * @return the number of milliseconds since January 1, 1970, 00:00:00 GMT for 305 * the date and time specified by the arguments. 306 * @see java.util.Calendar 307 * @deprecated As of JDK version 1.1, 308 * replaced by <code>Calendar.set(year + 1900, month, date, 309 * hrs, min, sec)</code> or <code>GregorianCalendar(year + 1900, 310 * month, date, hrs, min, sec)</code>, using a UTC 311 * <code>TimeZone</code>, followed by <code>Calendar.getTime().getTime()</code>. 312 */ 313 @Deprecated 314 public static long UTC(int year, int month, int date, 315 int hrs, int min, int sec) { 316 int y = year + 1900; 317 // month is 0-based. So we have to normalize month to support Long.MAX_VALUE. 318 if (month >= 12) { 319 y += month / 12; 320 month %= 12; 321 } else if (month < 0) { 322 y += CalendarUtils.floorDivide(month, 12); 323 month = CalendarUtils.mod(month, 12); 324 } 325 int m = month + 1; 326 BaseCalendar cal = getCalendarSystem(y); 327 BaseCalendar.Date udate = (BaseCalendar.Date) cal.newCalendarDate(null); 328 udate.setNormalizedDate(y, m, date).setTimeOfDay(hrs, min, sec, 0); 329 330 // Use a Date instance to perform normalization. Its fastTime 331 // is the UTC value after the normalization. 332 Date d = new Date(0); 333 d.normalize(udate); 334 return d.fastTime; 335 } 336 337 /** 338 * Attempts to interpret the string <tt>s</tt> as a representation 339 * of a date and time. If the attempt is successful, the time 340 * indicated is returned represented as the distance, measured in 341 * milliseconds, of that time from the epoch (00:00:00 GMT on 342 * January 1, 1970). If the attempt fails, an 343 * <tt>IllegalArgumentException</tt> is thrown. 344 * <p> 345 * It accepts many syntaxes; in particular, it recognizes the IETF 346 * standard date syntax: "Sat, 12 Aug 1995 13:30:00 GMT". It also 347 * understands the continental U.S. time-zone abbreviations, but for 348 * general use, a time-zone offset should be used: "Sat, 12 Aug 1995 349 * 13:30:00 GMT+0430" (4 hours, 30 minutes west of the Greenwich 350 * meridian). If no time zone is specified, the local time zone is 351 * assumed. GMT and UTC are considered equivalent. 352 * <p> 353 * The string <tt>s</tt> is processed from left to right, looking for 354 * data of interest. Any material in <tt>s</tt> that is within the 355 * ASCII parenthesis characters <tt>(</tt> and <tt>)</tt> is ignored. 356 * Parentheses may be nested. Otherwise, the only characters permitted 357 * within <tt>s</tt> are these ASCII characters: 358 * <blockquote><pre> 359 * abcdefghijklmnopqrstuvwxyz 360 * ABCDEFGHIJKLMNOPQRSTUVWXYZ 361 * 0123456789,+-:/</pre></blockquote> 362 * and whitespace characters.<p> 363 * A consecutive sequence of decimal digits is treated as a decimal 364 * number:<ul> 365 * <li>If a number is preceded by <tt>+</tt> or <tt>-</tt> and a year 366 * has already been recognized, then the number is a time-zone 367 * offset. If the number is less than 24, it is an offset measured 368 * in hours. Otherwise, it is regarded as an offset in minutes, 369 * expressed in 24-hour time format without punctuation. A 370 * preceding <tt>-</tt> means a westward offset. Time zone offsets 371 * are always relative to UTC (Greenwich). Thus, for example, 372 * <tt>-5</tt> occurring in the string would mean "five hours west 373 * of Greenwich" and <tt>+0430</tt> would mean "four hours and 374 * thirty minutes east of Greenwich." It is permitted for the 375 * string to specify <tt>GMT</tt>, <tt>UT</tt>, or <tt>UTC</tt> 376 * redundantly-for example, <tt>GMT-5</tt> or <tt>utc+0430</tt>. 377 * <li>The number is regarded as a year number if one of the 378 * following conditions is true: 379 * <ul> 380 * <li>The number is equal to or greater than 70 and followed by a 381 * space, comma, slash, or end of string 382 * <li>The number is less than 70, and both a month and a day of 383 * the month have already been recognized</li> 384 * </ul> 385 * If the recognized year number is less than 100, it is 386 * interpreted as an abbreviated year relative to a century of 387 * which dates are within 80 years before and 19 years after 388 * the time when the Date class is initialized. 389 * After adjusting the year number, 1900 is subtracted from 390 * it. For example, if the current year is 1999 then years in 391 * the range 19 to 99 are assumed to mean 1919 to 1999, while 392 * years from 0 to 18 are assumed to mean 2000 to 2018. Note 393 * that this is slightly different from the interpretation of 394 * years less than 100 that is used in {@link java.text.SimpleDateFormat}. 395 * <li>If the number is followed by a colon, it is regarded as an hour, 396 * unless an hour has already been recognized, in which case it is 397 * regarded as a minute. 398 * <li>If the number is followed by a slash, it is regarded as a month 399 * (it is decreased by 1 to produce a number in the range <tt>0</tt> 400 * to <tt>11</tt>), unless a month has already been recognized, in 401 * which case it is regarded as a day of the month. 402 * <li>If the number is followed by whitespace, a comma, a hyphen, or 403 * end of string, then if an hour has been recognized but not a 404 * minute, it is regarded as a minute; otherwise, if a minute has 405 * been recognized but not a second, it is regarded as a second; 406 * otherwise, it is regarded as a day of the month. </ul><p> 407 * A consecutive sequence of letters is regarded as a word and treated 408 * as follows:<ul> 409 * <li>A word that matches <tt>AM</tt>, ignoring case, is ignored (but 410 * the parse fails if an hour has not been recognized or is less 411 * than <tt>1</tt> or greater than <tt>12</tt>). 412 * <li>A word that matches <tt>PM</tt>, ignoring case, adds <tt>12</tt> 413 * to the hour (but the parse fails if an hour has not been 414 * recognized or is less than <tt>1</tt> or greater than <tt>12</tt>). 415 * <li>Any word that matches any prefix of <tt>SUNDAY, MONDAY, TUESDAY, 416 * WEDNESDAY, THURSDAY, FRIDAY</tt>, or <tt>SATURDAY</tt>, ignoring 417 * case, is ignored. For example, <tt>sat, Friday, TUE</tt>, and 418 * <tt>Thurs</tt> are ignored. 419 * <li>Otherwise, any word that matches any prefix of <tt>JANUARY, 420 * FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, 421 * OCTOBER, NOVEMBER</tt>, or <tt>DECEMBER</tt>, ignoring case, and 422 * considering them in the order given here, is recognized as 423 * specifying a month and is converted to a number (<tt>0</tt> to 424 * <tt>11</tt>). For example, <tt>aug, Sept, april</tt>, and 425 * <tt>NOV</tt> are recognized as months. So is <tt>Ma</tt>, which 426 * is recognized as <tt>MARCH</tt>, not <tt>MAY</tt>. 427 * <li>Any word that matches <tt>GMT, UT</tt>, or <tt>UTC</tt>, ignoring 428 * case, is treated as referring to UTC. 429 * <li>Any word that matches <tt>EST, CST, MST</tt>, or <tt>PST</tt>, 430 * ignoring case, is recognized as referring to the time zone in 431 * North America that is five, six, seven, or eight hours west of 432 * Greenwich, respectively. Any word that matches <tt>EDT, CDT, 433 * MDT</tt>, or <tt>PDT</tt>, ignoring case, is recognized as 434 * referring to the same time zone, respectively, during daylight 435 * saving time.</ul><p> 436 * Once the entire string s has been scanned, it is converted to a time 437 * result in one of two ways. If a time zone or time-zone offset has been 438 * recognized, then the year, month, day of month, hour, minute, and 439 * second are interpreted in UTC and then the time-zone offset is 440 * applied. Otherwise, the year, month, day of month, hour, minute, and 441 * second are interpreted in the local time zone. 442 * 443 * @param s a string to be parsed as a date. 444 * @return the number of milliseconds since January 1, 1970, 00:00:00 GMT 445 * represented by the string argument. 446 * @see java.text.DateFormat 447 * @deprecated As of JDK version 1.1, 448 * replaced by <code>DateFormat.parse(String s)</code>. 449 */ 450 @Deprecated 451 public static long parse(String s) { 452 int year = Integer.MIN_VALUE; 453 int mon = -1; 454 int mday = -1; 455 int hour = -1; 456 int min = -1; 457 int sec = -1; 458 int millis = -1; 459 int c = -1; 460 int i = 0; 461 int n = -1; 462 int wst = -1; 463 int tzoffset = -1; 464 int prevc = 0; 465 syntax: 466 { 467 if (s == null) 468 break syntax; 469 int limit = s.length(); 470 while (i < limit) { 471 c = s.charAt(i); 472 i++; 473 if (c <= ' ' || c == ',') 474 continue; 475 if (c == '(') { // skip comments 476 int depth = 1; 477 while (i < limit) { 478 c = s.charAt(i); 479 i++; 480 if (c == '(') depth++; 481 else if (c == ')') 482 if (--depth <= 0) 483 break; 484 } 485 continue; 486 } 487 if ('0' <= c && c <= '9') { 488 n = c - '0'; 489 while (i < limit && '0' <= (c = s.charAt(i)) && c <= '9') { 490 n = n * 10 + c - '0'; 491 i++; 492 } 493 if (prevc == '+' || prevc == '-' && year != Integer.MIN_VALUE) { 494 // timezone offset 495 if (n < 24) 496 n = n * 60; // EG. "GMT-3" 497 else 498 n = n % 100 + n / 100 * 60; // eg "GMT-0430" 499 if (prevc == '+') // plus means east of GMT 500 n = -n; 501 if (tzoffset != 0 && tzoffset != -1) 502 break syntax; 503 tzoffset = n; 504 } else if (n >= 70) 505 if (year != Integer.MIN_VALUE) 506 break syntax; 507 else if (c <= ' ' || c == ',' || c == '/' || i >= limit) 508 // year = n < 1900 ? n : n - 1900; 509 year = n; 510 else 511 break syntax; 512 else if (c == ':') 513 if (hour < 0) 514 hour = (byte) n; 515 else if (min < 0) 516 min = (byte) n; 517 else 518 break syntax; 519 else if (c == '/') 520 if (mon < 0) 521 mon = (byte) (n - 1); 522 else if (mday < 0) 523 mday = (byte) n; 524 else 525 break syntax; 526 else if (i < limit && c != ',' && c > ' ' && c != '-') 527 break syntax; 528 else if (hour >= 0 && min < 0) 529 min = (byte) n; 530 else if (min >= 0 && sec < 0) 531 sec = (byte) n; 532 else if (mday < 0) 533 mday = (byte) n; 534 // Handle two-digit years < 70 (70-99 handled above). 535 else if (year == Integer.MIN_VALUE && mon >= 0 && mday >= 0) 536 year = n; 537 else 538 break syntax; 539 prevc = 0; 540 } else if (c == '/' || c == ':' || c == '+' || c == '-') 541 prevc = c; 542 else { 543 int st = i - 1; 544 while (i < limit) { 545 c = s.charAt(i); 546 if (!('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z')) 547 break; 548 i++; 549 } 550 if (i <= st + 1) 551 break syntax; 552 int k; 553 for (k = wtb.length; --k >= 0;) 554 if (wtb[k].regionMatches(true, 0, s, st, i - st)) { 555 int action = ttb[k]; 556 if (action != 0) { 557 if (action == 1) { // pm 558 if (hour > 12 || hour < 1) 559 break syntax; 560 else if (hour < 12) 561 hour += 12; 562 } else if (action == 14) { // am 563 if (hour > 12 || hour < 1) 564 break syntax; 565 else if (hour == 12) 566 hour = 0; 567 } else if (action <= 13) { // month! 568 if (mon < 0) 569 mon = (byte) (action - 2); 570 else 571 break syntax; 572 } else { 573 tzoffset = action - 10000; 574 } 575 } 576 break; 577 } 578 if (k < 0) 579 break syntax; 580 prevc = 0; 581 } 582 } 583 if (year == Integer.MIN_VALUE || mon < 0 || mday < 0) 584 break syntax; 585 // Parse 2-digit years within the correct default century. 586 if (year < 100) { 587 synchronized (Date.class) { 588 if (defaultCenturyStart == 0) { 589 defaultCenturyStart = gcal.getCalendarDate().getYear() - 80; 590 } 591 } 592 year += (defaultCenturyStart / 100) * 100; 593 if (year < defaultCenturyStart) year += 100; 594 } 595 if (sec < 0) 596 sec = 0; 597 if (min < 0) 598 min = 0; 599 if (hour < 0) 600 hour = 0; 601 BaseCalendar cal = getCalendarSystem(year); 602 if (tzoffset == -1) { // no time zone specified, have to use local 603 BaseCalendar.Date ldate = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.getDefaultRef()); 604 ldate.setDate(year, mon + 1, mday); 605 ldate.setTimeOfDay(hour, min, sec, 0); 606 return cal.getTime(ldate); 607 } 608 BaseCalendar.Date udate = (BaseCalendar.Date) cal.newCalendarDate(null); // no time zone 609 udate.setDate(year, mon + 1, mday); 610 udate.setTimeOfDay(hour, min, sec, 0); 611 return cal.getTime(udate) + tzoffset * (60 * 1000); 612 } 613 // syntax error 614 throw new IllegalArgumentException(); 615 } 616 private final static String wtb[] = { 617 "am", "pm", 618 "monday", "tuesday", "wednesday", "thursday", "friday", 619 "saturday", "sunday", 620 "january", "february", "march", "april", "may", "june", 621 "july", "august", "september", "october", "november", "december", 622 "gmt", "ut", "utc", "est", "edt", "cst", "cdt", 623 "mst", "mdt", "pst", "pdt" 624 }; 625 private final static int ttb[] = { 626 14, 1, 0, 0, 0, 0, 0, 0, 0, 627 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 628 10000 + 0, 10000 + 0, 10000 + 0, // GMT/UT/UTC 629 10000 + 5 * 60, 10000 + 4 * 60, // EST/EDT 630 10000 + 6 * 60, 10000 + 5 * 60, // CST/CDT 631 10000 + 7 * 60, 10000 + 6 * 60, // MST/MDT 632 10000 + 8 * 60, 10000 + 7 * 60 // PST/PDT 633 }; 634 635 /** 636 * Returns a value that is the result of subtracting 1900 from the 637 * year that contains or begins with the instant in time represented 638 * by this <code>Date</code> object, as interpreted in the local 639 * time zone. 640 * 641 * @return the year represented by this date, minus 1900. 642 * @see java.util.Calendar 643 * @deprecated As of JDK version 1.1, 644 * replaced by <code>Calendar.get(Calendar.YEAR) - 1900</code>. 645 */ 646 @Deprecated 647 public int getYear() { 648 return normalize().getYear() - 1900; 649 } 650 651 /** 652 * Sets the year of this <tt>Date</tt> object to be the specified 653 * value plus 1900. This <code>Date</code> object is modified so 654 * that it represents a point in time within the specified year, 655 * with the month, date, hour, minute, and second the same as 656 * before, as interpreted in the local time zone. (Of course, if 657 * the date was February 29, for example, and the year is set to a 658 * non-leap year, then the new date will be treated as if it were 659 * on March 1.) 660 * 661 * @param year the year value. 662 * @see java.util.Calendar 663 * @deprecated As of JDK version 1.1, 664 * replaced by <code>Calendar.set(Calendar.YEAR, year + 1900)</code>. 665 */ 666 @Deprecated 667 public void setYear(int year) { 668 getCalendarDate().setNormalizedYear(year + 1900); 669 } 670 671 /** 672 * Returns a number representing the month that contains or begins 673 * with the instant in time represented by this <tt>Date</tt> object. 674 * The value returned is between <code>0</code> and <code>11</code>, 675 * with the value <code>0</code> representing January. 676 * 677 * @return the month represented by this date. 678 * @see java.util.Calendar 679 * @deprecated As of JDK version 1.1, 680 * replaced by <code>Calendar.get(Calendar.MONTH)</code>. 681 */ 682 @Deprecated 683 public int getMonth() { 684 return normalize().getMonth() - 1; // adjust 1-based to 0-based 685 } 686 687 /** 688 * Sets the month of this date to the specified value. This 689 * <tt>Date</tt> object is modified so that it represents a point 690 * in time within the specified month, with the year, date, hour, 691 * minute, and second the same as before, as interpreted in the 692 * local time zone. If the date was October 31, for example, and 693 * the month is set to June, then the new date will be treated as 694 * if it were on July 1, because June has only 30 days. 695 * 696 * @param month the month value between 0-11. 697 * @see java.util.Calendar 698 * @deprecated As of JDK version 1.1, 699 * replaced by <code>Calendar.set(Calendar.MONTH, int month)</code>. 700 */ 701 @Deprecated 702 public void setMonth(int month) { 703 int y = 0; 704 if (month >= 12) { 705 y = month / 12; 706 month %= 12; 707 } else if (month < 0) { 708 y = CalendarUtils.floorDivide(month, 12); 709 month = CalendarUtils.mod(month, 12); 710 } 711 BaseCalendar.Date d = getCalendarDate(); 712 if (y != 0) { 713 d.setNormalizedYear(d.getNormalizedYear() + y); 714 } 715 d.setMonth(month + 1); // adjust 0-based to 1-based month numbering 716 } 717 718 /** 719 * Returns the day of the month represented by this <tt>Date</tt> object. 720 * The value returned is between <code>1</code> and <code>31</code> 721 * representing the day of the month that contains or begins with the 722 * instant in time represented by this <tt>Date</tt> object, as 723 * interpreted in the local time zone. 724 * 725 * @return the day of the month represented by this date. 726 * @see java.util.Calendar 727 * @deprecated As of JDK version 1.1, 728 * replaced by <code>Calendar.get(Calendar.DAY_OF_MONTH)</code>. 729 */ 730 @Deprecated 731 // Android removed stray @deprecated tag. 732 public int getDate() { 733 return normalize().getDayOfMonth(); 734 } 735 736 /** 737 * Sets the day of the month of this <tt>Date</tt> object to the 738 * specified value. This <tt>Date</tt> object is modified so that 739 * it represents a point in time within the specified day of the 740 * month, with the year, month, hour, minute, and second the same 741 * as before, as interpreted in the local time zone. If the date 742 * was April 30, for example, and the date is set to 31, then it 743 * will be treated as if it were on May 1, because April has only 744 * 30 days. 745 * 746 * @param date the day of the month value between 1-31. 747 * @see java.util.Calendar 748 * @deprecated As of JDK version 1.1, 749 * replaced by <code>Calendar.set(Calendar.DAY_OF_MONTH, int date)</code>. 750 */ 751 @Deprecated 752 public void setDate(int date) { 753 getCalendarDate().setDayOfMonth(date); 754 } 755 756 /** 757 * Returns the day of the week represented by this date. The 758 * returned value (<tt>0</tt> = Sunday, <tt>1</tt> = Monday, 759 * <tt>2</tt> = Tuesday, <tt>3</tt> = Wednesday, <tt>4</tt> = 760 * Thursday, <tt>5</tt> = Friday, <tt>6</tt> = Saturday) 761 * represents the day of the week that contains or begins with 762 * the instant in time represented by this <tt>Date</tt> object, 763 * as interpreted in the local time zone. 764 * 765 * @return the day of the week represented by this date. 766 * @see java.util.Calendar 767 * @deprecated As of JDK version 1.1, 768 * replaced by <code>Calendar.get(Calendar.DAY_OF_WEEK)</code>. 769 */ 770 @Deprecated 771 public int getDay() { 772 return normalize().getDayOfWeek() - gcal.SUNDAY; 773 } 774 775 /** 776 * Returns the hour represented by this <tt>Date</tt> object. The 777 * returned value is a number (<tt>0</tt> through <tt>23</tt>) 778 * representing the hour within the day that contains or begins 779 * with the instant in time represented by this <tt>Date</tt> 780 * object, as interpreted in the local time zone. 781 * 782 * @return the hour represented by this date. 783 * @see java.util.Calendar 784 * @deprecated As of JDK version 1.1, 785 * replaced by <code>Calendar.get(Calendar.HOUR_OF_DAY)</code>. 786 */ 787 @Deprecated 788 public int getHours() { 789 return normalize().getHours(); 790 } 791 792 /** 793 * Sets the hour of this <tt>Date</tt> object to the specified value. 794 * This <tt>Date</tt> object is modified so that it represents a point 795 * in time within the specified hour of the day, with the year, month, 796 * date, minute, and second the same as before, as interpreted in the 797 * local time zone. 798 * 799 * @param hours the hour value. 800 * @see java.util.Calendar 801 * @deprecated As of JDK version 1.1, 802 * replaced by <code>Calendar.set(Calendar.HOUR_OF_DAY, int hours)</code>. 803 */ 804 @Deprecated 805 public void setHours(int hours) { 806 getCalendarDate().setHours(hours); 807 } 808 809 /** 810 * Returns the number of minutes past the hour represented by this date, 811 * as interpreted in the local time zone. 812 * The value returned is between <code>0</code> and <code>59</code>. 813 * 814 * @return the number of minutes past the hour represented by this date. 815 * @see java.util.Calendar 816 * @deprecated As of JDK version 1.1, 817 * replaced by <code>Calendar.get(Calendar.MINUTE)</code>. 818 */ 819 @Deprecated 820 public int getMinutes() { 821 return normalize().getMinutes(); 822 } 823 824 /** 825 * Sets the minutes of this <tt>Date</tt> object to the specified value. 826 * This <tt>Date</tt> object is modified so that it represents a point 827 * in time within the specified minute of the hour, with the year, month, 828 * date, hour, and second the same as before, as interpreted in the 829 * local time zone. 830 * 831 * @param minutes the value of the minutes. 832 * @see java.util.Calendar 833 * @deprecated As of JDK version 1.1, 834 * replaced by <code>Calendar.set(Calendar.MINUTE, int minutes)</code>. 835 */ 836 @Deprecated 837 public void setMinutes(int minutes) { 838 getCalendarDate().setMinutes(minutes); 839 } 840 841 /** 842 * Returns the number of seconds past the minute represented by this date. 843 * The value returned is between <code>0</code> and <code>61</code>. The 844 * values <code>60</code> and <code>61</code> can only occur on those 845 * Java Virtual Machines that take leap seconds into account. 846 * 847 * @return the number of seconds past the minute represented by this date. 848 * @see java.util.Calendar 849 * @deprecated As of JDK version 1.1, 850 * replaced by <code>Calendar.get(Calendar.SECOND)</code>. 851 */ 852 @Deprecated 853 public int getSeconds() { 854 return normalize().getSeconds(); 855 } 856 857 /** 858 * Sets the seconds of this <tt>Date</tt> to the specified value. 859 * This <tt>Date</tt> object is modified so that it represents a 860 * point in time within the specified second of the minute, with 861 * the year, month, date, hour, and minute the same as before, as 862 * interpreted in the local time zone. 863 * 864 * @param seconds the seconds value. 865 * @see java.util.Calendar 866 * @deprecated As of JDK version 1.1, 867 * replaced by <code>Calendar.set(Calendar.SECOND, int seconds)</code>. 868 */ 869 @Deprecated 870 public void setSeconds(int seconds) { 871 getCalendarDate().setSeconds(seconds); 872 } 873 874 /** 875 * Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT 876 * represented by this <tt>Date</tt> object. 877 * 878 * @return the number of milliseconds since January 1, 1970, 00:00:00 GMT 879 * represented by this date. 880 */ 881 public long getTime() { 882 return getTimeImpl(); 883 } 884 885 private final long getTimeImpl() { 886 if (cdate != null && !cdate.isNormalized()) { 887 normalize(); 888 } 889 return fastTime; 890 } 891 892 /** 893 * Sets this <code>Date</code> object to represent a point in time that is 894 * <code>time</code> milliseconds after January 1, 1970 00:00:00 GMT. 895 * 896 * @param time the number of milliseconds. 897 */ 898 public void setTime(long time) { 899 fastTime = time; 900 cdate = null; 901 } 902 903 /** 904 * Tests if this date is before the specified date. 905 * 906 * @param when a date. 907 * @return <code>true</code> if and only if the instant of time 908 * represented by this <tt>Date</tt> object is strictly 909 * earlier than the instant represented by <tt>when</tt>; 910 * <code>false</code> otherwise. 911 * @exception NullPointerException if <code>when</code> is null. 912 */ 913 public boolean before(Date when) { 914 return getMillisOf(this) < getMillisOf(when); 915 } 916 917 /** 918 * Tests if this date is after the specified date. 919 * 920 * @param when a date. 921 * @return <code>true</code> if and only if the instant represented 922 * by this <tt>Date</tt> object is strictly later than the 923 * instant represented by <tt>when</tt>; 924 * <code>false</code> otherwise. 925 * @exception NullPointerException if <code>when</code> is null. 926 */ 927 public boolean after(Date when) { 928 return getMillisOf(this) > getMillisOf(when); 929 } 930 931 /** 932 * Compares two dates for equality. 933 * The result is <code>true</code> if and only if the argument is 934 * not <code>null</code> and is a <code>Date</code> object that 935 * represents the same point in time, to the millisecond, as this object. 936 * <p> 937 * Thus, two <code>Date</code> objects are equal if and only if the 938 * <code>getTime</code> method returns the same <code>long</code> 939 * value for both. 940 * 941 * @param obj the object to compare with. 942 * @return <code>true</code> if the objects are the same; 943 * <code>false</code> otherwise. 944 * @see java.util.Date#getTime() 945 */ 946 public boolean equals(Object obj) { 947 return obj instanceof Date && getTime() == ((Date) obj).getTime(); 948 } 949 950 /** 951 * Returns the millisecond value of this <code>Date</code> object 952 * without affecting its internal state. 953 */ 954 static final long getMillisOf(Date date) { 955 if (date.cdate == null || date.cdate.isNormalized()) { 956 return date.fastTime; 957 } 958 BaseCalendar.Date d = (BaseCalendar.Date) date.cdate.clone(); 959 return gcal.getTime(d); 960 } 961 962 /** 963 * Compares two Dates for ordering. 964 * 965 * @param anotherDate the <code>Date</code> to be compared. 966 * @return the value <code>0</code> if the argument Date is equal to 967 * this Date; a value less than <code>0</code> if this Date 968 * is before the Date argument; and a value greater than 969 * <code>0</code> if this Date is after the Date argument. 970 * @since 1.2 971 * @exception NullPointerException if <code>anotherDate</code> is null. 972 */ 973 public int compareTo(Date anotherDate) { 974 long thisTime = getMillisOf(this); 975 long anotherTime = getMillisOf(anotherDate); 976 return (thisTime<anotherTime ? -1 : (thisTime==anotherTime ? 0 : 1)); 977 } 978 979 /** 980 * Returns a hash code value for this object. The result is the 981 * exclusive OR of the two halves of the primitive <tt>long</tt> 982 * value returned by the {@link Date#getTime} 983 * method. That is, the hash code is the value of the expression: 984 * <blockquote><pre> 985 * (int)(this.getTime()^(this.getTime() >>> 32))</pre></blockquote> 986 * 987 * @return a hash code value for this object. 988 */ 989 public int hashCode() { 990 long ht = this.getTime(); 991 return (int) ht ^ (int) (ht >> 32); 992 } 993 994 /** 995 * Converts this <code>Date</code> object to a <code>String</code> 996 * of the form: 997 * <blockquote><pre> 998 * dow mon dd hh:mm:ss zzz yyyy</pre></blockquote> 999 * where:<ul> 1000 * <li><tt>dow</tt> is the day of the week (<tt>Sun, Mon, Tue, Wed, 1001 * Thu, Fri, Sat</tt>). 1002 * <li><tt>mon</tt> is the month (<tt>Jan, Feb, Mar, Apr, May, Jun, 1003 * Jul, Aug, Sep, Oct, Nov, Dec</tt>). 1004 * <li><tt>dd</tt> is the day of the month (<tt>01</tt> through 1005 * <tt>31</tt>), as two decimal digits. 1006 * <li><tt>hh</tt> is the hour of the day (<tt>00</tt> through 1007 * <tt>23</tt>), as two decimal digits. 1008 * <li><tt>mm</tt> is the minute within the hour (<tt>00</tt> through 1009 * <tt>59</tt>), as two decimal digits. 1010 * <li><tt>ss</tt> is the second within the minute (<tt>00</tt> through 1011 * <tt>61</tt>, as two decimal digits. 1012 * <li><tt>zzz</tt> is the time zone (and may reflect daylight saving 1013 * time). Standard time zone abbreviations include those 1014 * recognized by the method <tt>parse</tt>. If time zone 1015 * information is not available, then <tt>zzz</tt> is empty - 1016 * that is, it consists of no characters at all. 1017 * <li><tt>yyyy</tt> is the year, as four decimal digits. 1018 * </ul> 1019 * 1020 * @return a string representation of this date. 1021 * @see java.util.Date#toLocaleString() 1022 * @see java.util.Date#toGMTString() 1023 */ 1024 public String toString() { 1025 // "EEE MMM dd HH:mm:ss zzz yyyy"; 1026 BaseCalendar.Date date = normalize(); 1027 StringBuilder sb = new StringBuilder(28); 1028 int index = date.getDayOfWeek(); 1029 if (index == gcal.SUNDAY) { 1030 index = 8; 1031 } 1032 convertToAbbr(sb, wtb[index]).append(' '); // EEE 1033 convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' '); // MMM 1034 CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd 1035 1036 CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':'); // HH 1037 CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm 1038 CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss 1039 TimeZone zi = date.getZone(); 1040 if (zi != null) { 1041 sb.append(zi.getDisplayName(date.isDaylightTime(), zi.SHORT, Locale.US)); // zzz 1042 } else { 1043 sb.append("GMT"); 1044 } 1045 sb.append(' ').append(date.getYear()); // yyyy 1046 return sb.toString(); 1047 } 1048 1049 /** 1050 * Converts the given name to its 3-letter abbreviation (e.g., 1051 * "monday" -> "Mon") and stored the abbreviation in the given 1052 * <code>StringBuilder</code>. 1053 */ 1054 private static final StringBuilder convertToAbbr(StringBuilder sb, String name) { 1055 sb.append(Character.toUpperCase(name.charAt(0))); 1056 sb.append(name.charAt(1)).append(name.charAt(2)); 1057 return sb; 1058 } 1059 1060 /** 1061 * Creates a string representation of this <tt>Date</tt> object in an 1062 * implementation-dependent form. The intent is that the form should 1063 * be familiar to the user of the Java application, wherever it may 1064 * happen to be running. The intent is comparable to that of the 1065 * "<code>%c</code>" format supported by the <code>strftime()</code> 1066 * function of ISO C. 1067 * 1068 * @return a string representation of this date, using the locale 1069 * conventions. 1070 * @see java.text.DateFormat 1071 * @see java.util.Date#toString() 1072 * @see java.util.Date#toGMTString() 1073 * @deprecated As of JDK version 1.1, 1074 * replaced by <code>DateFormat.format(Date date)</code>. 1075 */ 1076 @Deprecated 1077 public String toLocaleString() { 1078 DateFormat formatter = DateFormat.getDateTimeInstance(); 1079 return formatter.format(this); 1080 } 1081 1082 /** 1083 * Creates a string representation of this <tt>Date</tt> object of 1084 * the form: 1085 * <blockquote<pre> 1086 * d mon yyyy hh:mm:ss GMT</pre></blockquote> 1087 * where:<ul> 1088 * <li><i>d</i> is the day of the month (<tt>1</tt> through <tt>31</tt>), 1089 * as one or two decimal digits. 1090 * <li><i>mon</i> is the month (<tt>Jan, Feb, Mar, Apr, May, Jun, Jul, 1091 * Aug, Sep, Oct, Nov, Dec</tt>). 1092 * <li><i>yyyy</i> is the year, as four decimal digits. 1093 * <li><i>hh</i> is the hour of the day (<tt>00</tt> through <tt>23</tt>), 1094 * as two decimal digits. 1095 * <li><i>mm</i> is the minute within the hour (<tt>00</tt> through 1096 * <tt>59</tt>), as two decimal digits. 1097 * <li><i>ss</i> is the second within the minute (<tt>00</tt> through 1098 * <tt>61</tt>), as two decimal digits. 1099 * <li><i>GMT</i> is exactly the ASCII letters "<tt>GMT</tt>" to indicate 1100 * Greenwich Mean Time. 1101 * </ul><p> 1102 * The result does not depend on the local time zone. 1103 * 1104 * @return a string representation of this date, using the Internet GMT 1105 * conventions. 1106 * @see java.text.DateFormat 1107 * @see java.util.Date#toString() 1108 * @see java.util.Date#toLocaleString() 1109 * @deprecated As of JDK version 1.1, 1110 * replaced by <code>DateFormat.format(Date date)</code>, using a 1111 * GMT <code>TimeZone</code>. 1112 */ 1113 @Deprecated 1114 public String toGMTString() { 1115 // d MMM yyyy HH:mm:ss 'GMT' 1116 long t = getTime(); 1117 BaseCalendar cal = getCalendarSystem(t); 1118 BaseCalendar.Date date = 1119 (BaseCalendar.Date) cal.getCalendarDate(getTime(), (TimeZone)null); 1120 StringBuilder sb = new StringBuilder(32); 1121 CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 1).append(' '); // d 1122 convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' '); // MMM 1123 sb.append(date.getYear()).append(' '); // yyyy 1124 CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':'); // HH 1125 CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm 1126 CalendarUtils.sprintf0d(sb, date.getSeconds(), 2); // ss 1127 sb.append(" GMT"); // ' GMT' 1128 return sb.toString(); 1129 } 1130 1131 /** 1132 * Returns the offset, measured in minutes, for the local time zone 1133 * relative to UTC that is appropriate for the time represented by 1134 * this <code>Date</code> object. 1135 * <p> 1136 * For example, in Massachusetts, five time zones west of Greenwich: 1137 * <blockquote><pre> 1138 * new Date(96, 1, 14).getTimezoneOffset() returns 300</pre></blockquote> 1139 * because on February 14, 1996, standard time (Eastern Standard Time) 1140 * is in use, which is offset five hours from UTC; but: 1141 * <blockquote><pre> 1142 * new Date(96, 5, 1).getTimezoneOffset() returns 240</pre></blockquote> 1143 * because on June 1, 1996, daylight saving time (Eastern Daylight Time) 1144 * is in use, which is offset only four hours from UTC.<p> 1145 * This method produces the same result as if it computed: 1146 * <blockquote><pre> 1147 * (this.getTime() - UTC(this.getYear(), 1148 * this.getMonth(), 1149 * this.getDate(), 1150 * this.getHours(), 1151 * this.getMinutes(), 1152 * this.getSeconds())) / (60 * 1000) 1153 * </pre></blockquote> 1154 * 1155 * @return the time-zone offset, in minutes, for the current time zone. 1156 * @see java.util.Calendar#ZONE_OFFSET 1157 * @see java.util.Calendar#DST_OFFSET 1158 * @see java.util.TimeZone#getDefault 1159 * @deprecated As of JDK version 1.1, 1160 * replaced by <code>-(Calendar.get(Calendar.ZONE_OFFSET) + 1161 * Calendar.get(Calendar.DST_OFFSET)) / (60 * 1000)</code>. 1162 */ 1163 @Deprecated 1164 public int getTimezoneOffset() { 1165 int zoneOffset; 1166 if (cdate == null) { 1167 GregorianCalendar cal = new GregorianCalendar(fastTime); 1168 zoneOffset = -(cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / 60000; 1169 } else { 1170 normalize(); 1171 zoneOffset = cdate.getZoneOffset(); 1172 } 1173 return -zoneOffset/60000; // convert to minutes 1174 } 1175 1176 private final BaseCalendar.Date getCalendarDate() { 1177 if (cdate == null) { 1178 BaseCalendar cal = getCalendarSystem(fastTime); 1179 cdate = (BaseCalendar.Date) cal.getCalendarDate(fastTime, 1180 TimeZone.getDefaultRef()); 1181 } 1182 return cdate; 1183 } 1184 1185 private final BaseCalendar.Date normalize() { 1186 if (cdate == null) { 1187 BaseCalendar cal = getCalendarSystem(fastTime); 1188 cdate = (BaseCalendar.Date) cal.getCalendarDate(fastTime, 1189 TimeZone.getDefaultRef()); 1190 return cdate; 1191 } 1192 1193 // Normalize cdate with the TimeZone in cdate first. This is 1194 // required for the compatible behavior. 1195 if (!cdate.isNormalized()) { 1196 cdate = normalize(cdate); 1197 } 1198 1199 // If the default TimeZone has changed, then recalculate the 1200 // fields with the new TimeZone. 1201 TimeZone tz = TimeZone.getDefaultRef(); 1202 if (tz != cdate.getZone()) { 1203 cdate.setZone(tz); 1204 CalendarSystem cal = getCalendarSystem(cdate); 1205 cal.getCalendarDate(fastTime, cdate); 1206 } 1207 return cdate; 1208 } 1209 1210 // fastTime and the returned data are in sync upon return. 1211 private final BaseCalendar.Date normalize(BaseCalendar.Date date) { 1212 int y = date.getNormalizedYear(); 1213 int m = date.getMonth(); 1214 int d = date.getDayOfMonth(); 1215 int hh = date.getHours(); 1216 int mm = date.getMinutes(); 1217 int ss = date.getSeconds(); 1218 int ms = date.getMillis(); 1219 TimeZone tz = date.getZone(); 1220 1221 // If the specified year can't be handled using a long value 1222 // in milliseconds, GregorianCalendar is used for full 1223 // compatibility with underflow and overflow. This is required 1224 // by some JCK tests. The limits are based max year values - 1225 // years that can be represented by max values of d, hh, mm, 1226 // ss and ms. Also, let GregorianCalendar handle the default 1227 // cutover year so that we don't need to worry about the 1228 // transition here. 1229 if (y == 1582 || y > 280000000 || y < -280000000) { 1230 if (tz == null) { 1231 tz = TimeZone.getTimeZone("GMT"); 1232 } 1233 GregorianCalendar gc = new GregorianCalendar(tz); 1234 gc.clear(); 1235 gc.set(gc.MILLISECOND, ms); 1236 gc.set(y, m-1, d, hh, mm, ss); 1237 fastTime = gc.getTimeInMillis(); 1238 BaseCalendar cal = getCalendarSystem(fastTime); 1239 date = (BaseCalendar.Date) cal.getCalendarDate(fastTime, tz); 1240 return date; 1241 } 1242 1243 BaseCalendar cal = getCalendarSystem(y); 1244 if (cal != getCalendarSystem(date)) { 1245 date = (BaseCalendar.Date) cal.newCalendarDate(tz); 1246 date.setNormalizedDate(y, m, d).setTimeOfDay(hh, mm, ss, ms); 1247 } 1248 // Perform the GregorianCalendar-style normalization. 1249 fastTime = cal.getTime(date); 1250 1251 // In case the normalized date requires the other calendar 1252 // system, we need to recalculate it using the other one. 1253 BaseCalendar ncal = getCalendarSystem(fastTime); 1254 if (ncal != cal) { 1255 date = (BaseCalendar.Date) ncal.newCalendarDate(tz); 1256 date.setNormalizedDate(y, m, d).setTimeOfDay(hh, mm, ss, ms); 1257 fastTime = ncal.getTime(date); 1258 } 1259 return date; 1260 } 1261 1262 /** 1263 * Returns the Gregorian or Julian calendar system to use with the 1264 * given date. Use Gregorian from October 15, 1582. 1265 * 1266 * @param year normalized calendar year (not -1900) 1267 * @return the CalendarSystem to use for the specified date 1268 */ 1269 private static final BaseCalendar getCalendarSystem(int year) { 1270 if (year >= 1582) { 1271 return gcal; 1272 } 1273 return getJulianCalendar(); 1274 } 1275 1276 private static final BaseCalendar getCalendarSystem(long utc) { 1277 // Quickly check if the time stamp given by `utc' is the Epoch 1278 // or later. If it's before 1970, we convert the cutover to 1279 // local time to compare. 1280 if (utc >= 0 1281 || utc >= GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER 1282 - TimeZone.getDefaultRef().getOffset(utc)) { 1283 return gcal; 1284 } 1285 return getJulianCalendar(); 1286 } 1287 1288 private static final BaseCalendar getCalendarSystem(BaseCalendar.Date cdate) { 1289 if (jcal == null) { 1290 return gcal; 1291 } 1292 if (cdate.getEra() != null) { 1293 return jcal; 1294 } 1295 return gcal; 1296 } 1297 1298 synchronized private static final BaseCalendar getJulianCalendar() { 1299 if (jcal == null) { 1300 jcal = (BaseCalendar) CalendarSystem.forName("julian"); 1301 } 1302 return jcal; 1303 } 1304 1305 /** 1306 * Save the state of this object to a stream (i.e., serialize it). 1307 * 1308 * @serialData The value returned by <code>getTime()</code> 1309 * is emitted (long). This represents the offset from 1310 * January 1, 1970, 00:00:00 GMT in milliseconds. 1311 */ 1312 private void writeObject(ObjectOutputStream s) 1313 throws IOException 1314 { 1315 s.writeLong(getTimeImpl()); 1316 } 1317 1318 /** 1319 * Reconstitute this object from a stream (i.e., deserialize it). 1320 */ 1321 private void readObject(ObjectInputStream s) 1322 throws IOException, ClassNotFoundException 1323 { 1324 fastTime = s.readLong(); 1325 } 1326} 1327