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