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