Date.java revision 12745:f068a4ffddd2
1/* 2 * Copyright (c) 1994, 2013, 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.time.LocalDate; 30import java.io.IOException; 31import java.io.ObjectOutputStream; 32import java.io.ObjectInputStream; 33import java.lang.ref.SoftReference; 34import java.time.Instant; 35import sun.util.calendar.BaseCalendar; 36import sun.util.calendar.CalendarDate; 37import sun.util.calendar.CalendarSystem; 38import sun.util.calendar.CalendarUtils; 39import sun.util.calendar.Era; 40import sun.util.calendar.Gregorian; 41import sun.util.calendar.ZoneInfo; 42 43/** 44 * The class {@code Date} represents a specific instant 45 * in time, with millisecond precision. 46 * <p> 47 * Prior to JDK 1.1, the class {@code Date} had two additional 48 * functions. It allowed the interpretation of dates as year, month, day, hour, 49 * minute, and second values. It also allowed the formatting and parsing 50 * of date strings. Unfortunately, the API for these functions was not 51 * amenable to internationalization. As of JDK 1.1, the 52 * {@code Calendar} class should be used to convert between dates and time 53 * fields and the {@code DateFormat} class should be used to format and 54 * parse date strings. 55 * The corresponding methods in {@code Date} are deprecated. 56 * <p> 57 * Although the {@code Date} class is intended to reflect 58 * coordinated universal time (UTC), it may not do so exactly, 59 * depending on the host environment of the Java Virtual Machine. 60 * Nearly all modern operating systems assume that 1 day = 61 * 24 × 60 × 60 = 86400 seconds 62 * in all cases. In UTC, however, about once every year or two there 63 * is an extra second, called a "leap second." The leap 64 * second is always added as the last second of the day, and always 65 * on December 31 or June 30. For example, the last minute of the 66 * year 1995 was 61 seconds long, thanks to an added leap second. 67 * Most computer clocks are not accurate enough to be able to reflect 68 * the leap-second distinction. 69 * <p> 70 * Some computer standards are defined in terms of Greenwich mean 71 * time (GMT), which is equivalent to universal time (UT). GMT is 72 * the "civil" name for the standard; UT is the 73 * "scientific" name for the same standard. The 74 * distinction between UTC and UT is that UTC is based on an atomic 75 * clock and UT is based on astronomical observations, which for all 76 * practical purposes is an invisibly fine hair to split. Because the 77 * earth's rotation is not uniform (it slows down and speeds up 78 * in complicated ways), UT does not always flow uniformly. Leap 79 * seconds are introduced as needed into UTC so as to keep UTC within 80 * 0.9 seconds of UT1, which is a version of UT with certain 81 * corrections applied. There are other time and date systems as 82 * well; for example, the time scale used by the satellite-based 83 * global positioning system (GPS) is synchronized to UTC but is 84 * <i>not</i> adjusted for leap seconds. An interesting source of 85 * further information is the U.S. Naval Observatory, particularly 86 * the Directorate of Time at: 87 * <blockquote><pre> 88 * <a href=http://tycho.usno.navy.mil>http://tycho.usno.navy.mil</a> 89 * </pre></blockquote> 90 * <p> 91 * and their definitions of "Systems of Time" at: 92 * <blockquote><pre> 93 * <a href=http://tycho.usno.navy.mil/systime.html>http://tycho.usno.navy.mil/systime.html</a> 94 * </pre></blockquote> 95 * <p> 96 * In all methods of class {@code Date} that accept or return 97 * year, month, date, hours, minutes, and seconds values, the 98 * following representations are used: 99 * <ul> 100 * <li>A year <i>y</i> is represented by the integer 101 * <i>y</i> {@code - 1900}. 102 * <li>A month is represented by an integer from 0 to 11; 0 is January, 103 * 1 is February, and so forth; thus 11 is December. 104 * <li>A date (day of month) is represented by an integer from 1 to 31 105 * in the usual manner. 106 * <li>An hour is represented by an integer from 0 to 23. Thus, the hour 107 * from midnight to 1 a.m. is hour 0, and the hour from noon to 1 108 * p.m. is hour 12. 109 * <li>A minute is represented by an integer from 0 to 59 in the usual manner. 110 * <li>A second is represented by an integer from 0 to 61; the values 60 and 111 * 61 occur only for leap seconds and even then only in Java 112 * implementations that actually track leap seconds correctly. Because 113 * of the manner in which leap seconds are currently introduced, it is 114 * extremely unlikely that two leap seconds will occur in the same 115 * minute, but this specification follows the date and time conventions 116 * for ISO C. 117 * </ul> 118 * <p> 119 * In all cases, arguments given to methods for these purposes need 120 * not fall within the indicated ranges; for example, a date may be 121 * specified as January 32 and is interpreted as meaning February 1. 122 * 123 * @author James Gosling 124 * @author Arthur van Hoff 125 * @author Alan Liu 126 * @see java.text.DateFormat 127 * @see java.util.Calendar 128 * @see java.util.TimeZone 129 * @since 1.0 130 */ 131public class Date 132 implements java.io.Serializable, Cloneable, Comparable<Date> 133{ 134 private static final BaseCalendar gcal = 135 CalendarSystem.getGregorianCalendar(); 136 private static BaseCalendar jcal; 137 138 private transient long fastTime; 139 140 /* 141 * If cdate is null, then fastTime indicates the time in millis. 142 * If cdate.isNormalized() is true, then fastTime and cdate are in 143 * synch. Otherwise, fastTime is ignored, and cdate indicates the 144 * time. 145 */ 146 private transient BaseCalendar.Date cdate; 147 148 // Initialized just before the value is used. See parse(). 149 private static int defaultCenturyStart; 150 151 /* use serialVersionUID from modified java.util.Date for 152 * interoperability with JDK1.1. The Date was modified to write 153 * and read only the UTC time. 154 */ 155 private static final long serialVersionUID = 7523967970034938905L; 156 157 /** 158 * Allocates a {@code Date} object and initializes it so that 159 * it represents the time at which it was allocated, measured to the 160 * nearest millisecond. 161 * 162 * @see java.lang.System#currentTimeMillis() 163 */ 164 public Date() { 165 this(System.currentTimeMillis()); 166 } 167 168 /** 169 * Allocates a {@code Date} object and initializes it to 170 * represent the specified number of milliseconds since the 171 * standard base time known as "the epoch", namely January 1, 172 * 1970, 00:00:00 GMT. 173 * 174 * @param date the milliseconds since January 1, 1970, 00:00:00 GMT. 175 * @see java.lang.System#currentTimeMillis() 176 */ 177 public Date(long date) { 178 fastTime = date; 179 } 180 181 /** 182 * Allocates a {@code Date} object and initializes it so that 183 * it represents midnight, local time, at the beginning of the day 184 * specified by the {@code year}, {@code month}, and 185 * {@code date} arguments. 186 * 187 * @param year the year minus 1900. 188 * @param month the month between 0-11. 189 * @param date the day of the month between 1-31. 190 * @see java.util.Calendar 191 * @deprecated As of JDK version 1.1, 192 * replaced by {@code Calendar.set(year + 1900, month, date)} 193 * or {@code GregorianCalendar(year + 1900, month, date)}. 194 */ 195 @Deprecated 196 public Date(int year, int month, int date) { 197 this(year, month, date, 0, 0, 0); 198 } 199 200 /** 201 * Allocates a {@code Date} object and initializes it so that 202 * it represents the instant at the start of the minute specified by 203 * the {@code year}, {@code month}, {@code date}, 204 * {@code hrs}, and {@code min} arguments, in the local 205 * time zone. 206 * 207 * @param year the year minus 1900. 208 * @param month the month between 0-11. 209 * @param date the day of the month between 1-31. 210 * @param hrs the hours between 0-23. 211 * @param min the minutes between 0-59. 212 * @see java.util.Calendar 213 * @deprecated As of JDK version 1.1, 214 * replaced by {@code Calendar.set(year + 1900, month, date, hrs, min)} 215 * or {@code GregorianCalendar(year + 1900, month, date, hrs, min)}. 216 */ 217 @Deprecated 218 public Date(int year, int month, int date, int hrs, int min) { 219 this(year, month, date, hrs, min, 0); 220 } 221 222 /** 223 * Allocates a {@code Date} object and initializes it so that 224 * it represents the instant at the start of the second specified 225 * by the {@code year}, {@code month}, {@code date}, 226 * {@code hrs}, {@code min}, and {@code sec} arguments, 227 * in the local time zone. 228 * 229 * @param year the year minus 1900. 230 * @param month the month between 0-11. 231 * @param date the day of the month between 1-31. 232 * @param hrs the hours between 0-23. 233 * @param min the minutes between 0-59. 234 * @param sec the seconds between 0-59. 235 * @see java.util.Calendar 236 * @deprecated As of JDK version 1.1, 237 * replaced by {@code Calendar.set(year + 1900, month, date, hrs, min, sec)} 238 * or {@code GregorianCalendar(year + 1900, month, date, hrs, min, sec)}. 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} object and initializes it so that 260 * it represents the date and time indicated by the string 261 * {@code s}, 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)}. 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 {@code Date} 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, hrs, min, sec)} 310 * or {@code GregorianCalendar(year + 1900, month, date, hrs, min, sec)}, using a UTC 311 * {@code TimeZone}, followed by {@code Calendar.getTime().getTime()}. 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 {@code s} 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 * {@code IllegalArgumentException} 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 {@code s} is processed from left to right, looking for 354 * data of interest. Any material in {@code s} that is within the 355 * ASCII parenthesis characters {@code (} and {@code )} is ignored. 356 * Parentheses may be nested. Otherwise, the only characters permitted 357 * within {@code s} 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 {@code +} or {@code -} 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 {@code -} means a westward offset. Time zone offsets 371 * are always relative to UTC (Greenwich). Thus, for example, 372 * {@code -5} occurring in the string would mean "five hours west 373 * of Greenwich" and {@code +0430} would mean "four hours and 374 * thirty minutes east of Greenwich." It is permitted for the 375 * string to specify {@code GMT}, {@code UT}, or {@code UTC} 376 * redundantly-for example, {@code GMT-5} or {@code utc+0430}. 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 {@code 0} 400 * to {@code 11}), 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 {@code AM}, ignoring case, is ignored (but 410 * the parse fails if an hour has not been recognized or is less 411 * than {@code 1} or greater than {@code 12}). 412 * <li>A word that matches {@code PM}, ignoring case, adds {@code 12} 413 * to the hour (but the parse fails if an hour has not been 414 * recognized or is less than {@code 1} or greater than {@code 12}). 415 * <li>Any word that matches any prefix of {@code SUNDAY, MONDAY, TUESDAY, 416 * WEDNESDAY, THURSDAY, FRIDAY}, or {@code SATURDAY}, ignoring 417 * case, is ignored. For example, {@code sat, Friday, TUE}, and 418 * {@code Thurs} are ignored. 419 * <li>Otherwise, any word that matches any prefix of {@code JANUARY, 420 * FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, 421 * OCTOBER, NOVEMBER}, or {@code DECEMBER}, ignoring case, and 422 * considering them in the order given here, is recognized as 423 * specifying a month and is converted to a number ({@code 0} to 424 * {@code 11}). For example, {@code aug, Sept, april}, and 425 * {@code NOV} are recognized as months. So is {@code Ma}, which 426 * is recognized as {@code MARCH}, not {@code MAY}. 427 * <li>Any word that matches {@code GMT, UT}, or {@code UTC}, ignoring 428 * case, is treated as referring to UTC. 429 * <li>Any word that matches {@code EST, CST, MST}, or {@code PST}, 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 {@code EDT, CDT, 433 * MDT}, or {@code PDT}, 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)}. 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 static final 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 static final 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} 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}. 645 */ 646 @Deprecated 647 public int getYear() { 648 return normalize().getYear() - 1900; 649 } 650 651 /** 652 * Sets the year of this {@code Date} object to be the specified 653 * value plus 1900. This {@code Date} 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)}. 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 {@code Date} object. 674 * The value returned is between {@code 0} and {@code 11}, 675 * with the value {@code 0} 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)}. 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 * {@code Date} 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)}. 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 {@code Date} object. 720 * The value returned is between {@code 1} and {@code 31} 721 * representing the day of the month that contains or begins with the 722 * instant in time represented by this {@code Date} 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)}. 729 * @deprecated 730 */ 731 @Deprecated 732 public int getDate() { 733 return normalize().getDayOfMonth(); 734 } 735 736 /** 737 * Sets the day of the month of this {@code Date} object to the 738 * specified value. This {@code Date} 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)}. 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 ({@code 0} = Sunday, {@code 1} = Monday, 759 * {@code 2} = Tuesday, {@code 3} = Wednesday, {@code 4} = 760 * Thursday, {@code 5} = Friday, {@code 6} = Saturday) 761 * represents the day of the week that contains or begins with 762 * the instant in time represented by this {@code Date} 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)}. 769 */ 770 @Deprecated 771 public int getDay() { 772 return normalize().getDayOfWeek() - BaseCalendar.SUNDAY; 773 } 774 775 /** 776 * Returns the hour represented by this {@code Date} object. The 777 * returned value is a number ({@code 0} through {@code 23}) 778 * representing the hour within the day that contains or begins 779 * with the instant in time represented by this {@code Date} 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)}. 786 */ 787 @Deprecated 788 public int getHours() { 789 return normalize().getHours(); 790 } 791 792 /** 793 * Sets the hour of this {@code Date} object to the specified value. 794 * This {@code Date} 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)}. 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} and {@code 59}. 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)}. 818 */ 819 @Deprecated 820 public int getMinutes() { 821 return normalize().getMinutes(); 822 } 823 824 /** 825 * Sets the minutes of this {@code Date} object to the specified value. 826 * This {@code Date} 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)}. 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} and {@code 61}. The 844 * values {@code 60} and {@code 61} 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)}. 851 */ 852 @Deprecated 853 public int getSeconds() { 854 return normalize().getSeconds(); 855 } 856 857 /** 858 * Sets the seconds of this {@code Date} to the specified value. 859 * This {@code Date} 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)}. 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 {@code Date} 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} object to represent a point in time that is 894 * {@code time} 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} if and only if the instant of time 908 * represented by this {@code Date} object is strictly 909 * earlier than the instant represented by {@code when}; 910 * {@code false} otherwise. 911 * @exception NullPointerException if {@code when} 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} if and only if the instant represented 922 * by this {@code Date} object is strictly later than the 923 * instant represented by {@code when}; 924 * {@code false} otherwise. 925 * @exception NullPointerException if {@code when} 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} if and only if the argument is 934 * not {@code null} and is a {@code Date} object that 935 * represents the same point in time, to the millisecond, as this object. 936 * <p> 937 * Thus, two {@code Date} objects are equal if and only if the 938 * {@code getTime} method returns the same {@code long} 939 * value for both. 940 * 941 * @param obj the object to compare with. 942 * @return {@code true} if the objects are the same; 943 * {@code false} 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} 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} to be compared. 966 * @return the value {@code 0} if the argument Date is equal to 967 * this Date; a value less than {@code 0} if this Date 968 * is before the Date argument; and a value greater than 969 * {@code 0} if this Date is after the Date argument. 970 * @since 1.2 971 * @exception NullPointerException if {@code anotherDate} 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 {@code long} 982 * value returned by the {@link Date#getTime} 983 * method. That is, the hash code is the value of the expression: 984 * <blockquote><pre>{@code 985 * (int)(this.getTime()^(this.getTime() >>> 32)) 986 * }</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} object to a {@code String} 997 * of the form: 998 * <blockquote><pre> 999 * dow mon dd hh:mm:ss zzz yyyy</pre></blockquote> 1000 * where:<ul> 1001 * <li>{@code dow} is the day of the week ({@code Sun, Mon, Tue, Wed, 1002 * Thu, Fri, Sat}). 1003 * <li>{@code mon} is the month ({@code Jan, Feb, Mar, Apr, May, Jun, 1004 * Jul, Aug, Sep, Oct, Nov, Dec}). 1005 * <li>{@code dd} is the day of the month ({@code 01} through 1006 * {@code 31}), as two decimal digits. 1007 * <li>{@code hh} is the hour of the day ({@code 00} through 1008 * {@code 23}), as two decimal digits. 1009 * <li>{@code mm} is the minute within the hour ({@code 00} through 1010 * {@code 59}), as two decimal digits. 1011 * <li>{@code ss} is the second within the minute ({@code 00} through 1012 * {@code 61}, as two decimal digits. 1013 * <li>{@code zzz} is the time zone (and may reflect daylight saving 1014 * time). Standard time zone abbreviations include those 1015 * recognized by the method {@code parse}. If time zone 1016 * information is not available, then {@code zzz} is empty - 1017 * that is, it consists of no characters at all. 1018 * <li>{@code yyyy} 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 == BaseCalendar.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(), TimeZone.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}. 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 {@code Date} 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}" format supported by the {@code strftime()} 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)}. 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 {@code Date} 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 ({@code 1} through {@code 31}), 1090 * as one or two decimal digits. 1091 * <li><i>mon</i> is the month ({@code Jan, Feb, Mar, Apr, May, Jun, Jul, 1092 * Aug, Sep, Oct, Nov, Dec}). 1093 * <li><i>yyyy</i> is the year, as four decimal digits. 1094 * <li><i>hh</i> is the hour of the day ({@code 00} through {@code 23}), 1095 * as two decimal digits. 1096 * <li><i>mm</i> is the minute within the hour ({@code 00} through 1097 * {@code 59}), as two decimal digits. 1098 * <li><i>ss</i> is the second within the minute ({@code 00} through 1099 * {@code 61}), as two decimal digits. 1100 * <li><i>GMT</i> is exactly the ASCII letters "{@code GMT}" 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)}, using a 1112 * GMT {@code TimeZone}. 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} 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)}. 1163 */ 1164 @Deprecated 1165 public int getTimezoneOffset() { 1166 int zoneOffset; 1167 if (cdate == null) { 1168 TimeZone tz = TimeZone.getDefaultRef(); 1169 if (tz instanceof ZoneInfo) { 1170 zoneOffset = ((ZoneInfo)tz).getOffsets(fastTime, null); 1171 } else { 1172 zoneOffset = tz.getOffset(fastTime); 1173 } 1174 } else { 1175 normalize(); 1176 zoneOffset = cdate.getZoneOffset(); 1177 } 1178 return -zoneOffset/60000; // convert to minutes 1179 } 1180 1181 private final BaseCalendar.Date getCalendarDate() { 1182 if (cdate == null) { 1183 BaseCalendar cal = getCalendarSystem(fastTime); 1184 cdate = (BaseCalendar.Date) cal.getCalendarDate(fastTime, 1185 TimeZone.getDefaultRef()); 1186 } 1187 return cdate; 1188 } 1189 1190 private final BaseCalendar.Date normalize() { 1191 if (cdate == null) { 1192 BaseCalendar cal = getCalendarSystem(fastTime); 1193 cdate = (BaseCalendar.Date) cal.getCalendarDate(fastTime, 1194 TimeZone.getDefaultRef()); 1195 return cdate; 1196 } 1197 1198 // Normalize cdate with the TimeZone in cdate first. This is 1199 // required for the compatible behavior. 1200 if (!cdate.isNormalized()) { 1201 cdate = normalize(cdate); 1202 } 1203 1204 // If the default TimeZone has changed, then recalculate the 1205 // fields with the new TimeZone. 1206 TimeZone tz = TimeZone.getDefaultRef(); 1207 if (tz != cdate.getZone()) { 1208 cdate.setZone(tz); 1209 CalendarSystem cal = getCalendarSystem(cdate); 1210 cal.getCalendarDate(fastTime, cdate); 1211 } 1212 return cdate; 1213 } 1214 1215 // fastTime and the returned data are in sync upon return. 1216 private final BaseCalendar.Date normalize(BaseCalendar.Date date) { 1217 int y = date.getNormalizedYear(); 1218 int m = date.getMonth(); 1219 int d = date.getDayOfMonth(); 1220 int hh = date.getHours(); 1221 int mm = date.getMinutes(); 1222 int ss = date.getSeconds(); 1223 int ms = date.getMillis(); 1224 TimeZone tz = date.getZone(); 1225 1226 // If the specified year can't be handled using a long value 1227 // in milliseconds, GregorianCalendar is used for full 1228 // compatibility with underflow and overflow. This is required 1229 // by some JCK tests. The limits are based max year values - 1230 // years that can be represented by max values of d, hh, mm, 1231 // ss and ms. Also, let GregorianCalendar handle the default 1232 // cutover year so that we don't need to worry about the 1233 // transition here. 1234 if (y == 1582 || y > 280000000 || y < -280000000) { 1235 if (tz == null) { 1236 tz = TimeZone.getTimeZone("GMT"); 1237 } 1238 GregorianCalendar gc = new GregorianCalendar(tz); 1239 gc.clear(); 1240 gc.set(GregorianCalendar.MILLISECOND, ms); 1241 gc.set(y, m-1, d, hh, mm, ss); 1242 fastTime = gc.getTimeInMillis(); 1243 BaseCalendar cal = getCalendarSystem(fastTime); 1244 date = (BaseCalendar.Date) cal.getCalendarDate(fastTime, tz); 1245 return date; 1246 } 1247 1248 BaseCalendar cal = getCalendarSystem(y); 1249 if (cal != getCalendarSystem(date)) { 1250 date = (BaseCalendar.Date) cal.newCalendarDate(tz); 1251 date.setNormalizedDate(y, m, d).setTimeOfDay(hh, mm, ss, ms); 1252 } 1253 // Perform the GregorianCalendar-style normalization. 1254 fastTime = cal.getTime(date); 1255 1256 // In case the normalized date requires the other calendar 1257 // system, we need to recalculate it using the other one. 1258 BaseCalendar ncal = getCalendarSystem(fastTime); 1259 if (ncal != cal) { 1260 date = (BaseCalendar.Date) ncal.newCalendarDate(tz); 1261 date.setNormalizedDate(y, m, d).setTimeOfDay(hh, mm, ss, ms); 1262 fastTime = ncal.getTime(date); 1263 } 1264 return date; 1265 } 1266 1267 /** 1268 * Returns the Gregorian or Julian calendar system to use with the 1269 * given date. Use Gregorian from October 15, 1582. 1270 * 1271 * @param year normalized calendar year (not -1900) 1272 * @return the CalendarSystem to use for the specified date 1273 */ 1274 private static final BaseCalendar getCalendarSystem(int year) { 1275 if (year >= 1582) { 1276 return gcal; 1277 } 1278 return getJulianCalendar(); 1279 } 1280 1281 private static final BaseCalendar getCalendarSystem(long utc) { 1282 // Quickly check if the time stamp given by `utc' is the Epoch 1283 // or later. If it's before 1970, we convert the cutover to 1284 // local time to compare. 1285 if (utc >= 0 1286 || utc >= GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER 1287 - TimeZone.getDefaultRef().getOffset(utc)) { 1288 return gcal; 1289 } 1290 return getJulianCalendar(); 1291 } 1292 1293 private static final BaseCalendar getCalendarSystem(BaseCalendar.Date cdate) { 1294 if (jcal == null) { 1295 return gcal; 1296 } 1297 if (cdate.getEra() != null) { 1298 return jcal; 1299 } 1300 return gcal; 1301 } 1302 1303 private static final synchronized BaseCalendar getJulianCalendar() { 1304 if (jcal == null) { 1305 jcal = (BaseCalendar) CalendarSystem.forName("julian"); 1306 } 1307 return jcal; 1308 } 1309 1310 /** 1311 * Save the state of this object to a stream (i.e., serialize it). 1312 * 1313 * @serialData The value returned by {@code getTime()} 1314 * is emitted (long). This represents the offset from 1315 * January 1, 1970, 00:00:00 GMT in milliseconds. 1316 */ 1317 private void writeObject(ObjectOutputStream s) 1318 throws IOException 1319 { 1320 s.defaultWriteObject(); 1321 s.writeLong(getTimeImpl()); 1322 } 1323 1324 /** 1325 * Reconstitute this object from a stream (i.e., deserialize it). 1326 */ 1327 private void readObject(ObjectInputStream s) 1328 throws IOException, ClassNotFoundException 1329 { 1330 s.defaultReadObject(); 1331 fastTime = s.readLong(); 1332 } 1333 1334 /** 1335 * Obtains an instance of {@code Date} from an {@code Instant} object. 1336 * <p> 1337 * {@code Instant} uses a precision of nanoseconds, whereas {@code Date} 1338 * uses a precision of milliseconds. The conversion will truncate any 1339 * excess precision information as though the amount in nanoseconds was 1340 * subject to integer division by one million. 1341 * <p> 1342 * {@code Instant} can store points on the time-line further in the future 1343 * and further in the past than {@code Date}. In this scenario, this method 1344 * will throw an exception. 1345 * 1346 * @param instant the instant to convert 1347 * @return a {@code Date} representing the same point on the time-line as 1348 * the provided instant 1349 * @exception NullPointerException if {@code instant} is null. 1350 * @exception IllegalArgumentException if the instant is too large to 1351 * represent as a {@code Date} 1352 * @since 1.8 1353 */ 1354 public static Date from(Instant instant) { 1355 try { 1356 return new Date(instant.toEpochMilli()); 1357 } catch (ArithmeticException ex) { 1358 throw new IllegalArgumentException(ex); 1359 } 1360 } 1361 1362 /** 1363 * Converts this {@code Date} object to an {@code Instant}. 1364 * <p> 1365 * The conversion creates an {@code Instant} that represents the same 1366 * point on the time-line as this {@code Date}. 1367 * 1368 * @return an instant representing the same point on the time-line as 1369 * this {@code Date} object 1370 * @since 1.8 1371 */ 1372 public Instant toInstant() { 1373 return Instant.ofEpochMilli(getTime()); 1374 } 1375} 1376