Date.java 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257
  1. /* java.util.Date
  2. Copyright (C) 1998, 1999, 2000, 2001, 2005 Free Software Foundation, Inc.
  3. This file is part of GNU Classpath.
  4. GNU Classpath is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. GNU Classpath is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Classpath; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. 02110-1301 USA.
  16. Linking this library statically or dynamically with other modules is
  17. making a combined work based on this library. Thus, the terms and
  18. conditions of the GNU General Public License cover the whole
  19. combination.
  20. As a special exception, the copyright holders of this library give you
  21. permission to link this library with independent modules to produce an
  22. executable, regardless of the license terms of these independent
  23. modules, and to copy and distribute the resulting executable under
  24. terms of your choice, provided that you also meet, for each linked
  25. independent module, the terms and conditions of the license of that
  26. module. An independent module is a module which is not derived from
  27. or based on this library. If you modify this library, you may extend
  28. this exception to your version of the library, but you are not
  29. obligated to do so. If you do not wish to do so, delete this
  30. exception statement from your version. */
  31. package java.util;
  32. import gnu.java.lang.CPStringBuilder;
  33. import java.io.IOException;
  34. import java.io.ObjectInputStream;
  35. import java.io.ObjectOutputStream;
  36. import java.io.Serializable;
  37. import java.text.DateFormat;
  38. import java.text.SimpleDateFormat;
  39. /**
  40. * <p>
  41. * This class represents a specific time in milliseconds since the epoch.
  42. * The epoch is 1970, January 1 00:00:00.0000 UTC.
  43. * </p>
  44. * <p>
  45. * <code>Date</code> is intended to reflect universal time coordinate (UTC),
  46. * but this depends on the underlying host environment. Most operating systems
  47. * don't handle the leap second, which occurs about once every year or
  48. * so. The leap second is added to the last minute of the day on either
  49. * the 30th of June or the 31st of December, creating a minute 61 seconds
  50. * in length.
  51. * </p>
  52. * <p>
  53. * The representations of the date fields are as follows:
  54. * <ul>
  55. * <li>
  56. * Years are specified as the difference between the year
  57. * and 1900. Thus, the final year used is equal to
  58. * 1900 + y, where y is the input value.
  59. * </li>
  60. * <li>
  61. * Months are represented using zero-based indexing,
  62. * making 0 January and 11 December.
  63. * </li>
  64. * <li>
  65. * Dates are represented with the usual values of
  66. * 1 through to 31.
  67. * </li>
  68. * <li>
  69. * Hours are represented in the twenty-four hour clock,
  70. * with integer values from 0 to 23. 12am is 0, and
  71. * 12pm is 12.
  72. * </li>
  73. * <li>
  74. * Minutes are again as usual, with values from 0 to 59.
  75. * </li>
  76. * <li>
  77. * Seconds are represented with the values 0 through to 61,
  78. * with 60 and 61 being leap seconds (as per the ISO C standard).
  79. * </li>
  80. * </ul>
  81. * </p>
  82. * <p>
  83. * Prior to JDK 1.1, this class was the sole class handling date and time
  84. * related functionality. However, this particular solution was not
  85. * amenable to internationalization. The new <code>Calendar</code>
  86. * class should now be used to handle dates and times, with <code>Date</code>
  87. * being used only for values in milliseconds since the epoch. The
  88. * <code>Calendar</code> class, and its concrete implementations, handle
  89. * the interpretation of these values into minutes, hours, days, months
  90. * and years. The formatting and parsing of dates is left to the
  91. * <code>DateFormat</code> class, which is able to handle the different
  92. * types of date format which occur in different locales.
  93. * </p>
  94. *
  95. * @see Calendar
  96. * @see GregorianCalendar
  97. * @see java.text.DateFormat
  98. * @author Jochen Hoenicke
  99. * @author Per Bothner (bothner@cygnus.com)
  100. * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
  101. */
  102. public class Date
  103. implements Cloneable, Comparable<Date>, Serializable
  104. {
  105. /**
  106. * This is the serialization UID for this class
  107. * for compatability with Sun's JDK.
  108. */
  109. private static final long serialVersionUID = 7523967970034938905L;
  110. /**
  111. * The time in milliseconds since the epoch.
  112. */
  113. private transient long time;
  114. /**
  115. * An array of week names used to map names to integer values.
  116. */
  117. private static final String[] weekNames = { "Sun", "Mon", "Tue", "Wed",
  118. "Thu", "Fri", "Sat" };
  119. /**
  120. * An array of month names used to map names to integer values.
  121. */
  122. private static final String[] monthNames = { "Jan", "Feb", "Mar", "Apr",
  123. "May", "Jun", "Jul", "Aug",
  124. "Sep", "Oct", "Nov", "Dec" };
  125. /**
  126. * Creates a new Date Object representing the current time.
  127. */
  128. public Date()
  129. {
  130. time = System.currentTimeMillis();
  131. }
  132. /**
  133. * Creates a new Date Object representing the given time.
  134. *
  135. * @param time the time in milliseconds since the epoch.
  136. */
  137. public Date(long time)
  138. {
  139. this.time = time;
  140. }
  141. /**
  142. * Creates a new Date Object representing the given time.
  143. *
  144. * @deprecated use <code>new GregorianCalendar(year+1900, month,
  145. * day)</code> instead.
  146. * @param year the difference between the required year and 1900.
  147. * @param month the month as a value between 0 and 11.
  148. * @param day the day as a value between 0 and 31.
  149. */
  150. public Date(int year, int month, int day)
  151. {
  152. this(year, month, day, 0, 0, 0);
  153. }
  154. /**
  155. * Creates a new Date Object representing the given time.
  156. *
  157. * @deprecated use <code>new GregorianCalendar(year+1900, month,
  158. * day, hour, min)</code> instead.
  159. * @param year the difference between the required year and 1900.
  160. * @param month the month as a value between 0 and 11.
  161. * @param day the day as a value between 0 and 31.
  162. * @param hour the hour as a value between 0 and 23, in 24-hour
  163. * clock notation.
  164. * @param min the minute as a value between 0 and 59.
  165. */
  166. public Date(int year, int month, int day, int hour, int min)
  167. {
  168. this(year, month, day, hour, min, 0);
  169. }
  170. /**
  171. * Creates a new Date Object representing the given time.
  172. *
  173. * @deprecated use <code>new GregorianCalendar(year+1900, month,
  174. * day, hour, min, sec)</code> instead.
  175. * @param year the difference between the required year and 1900.
  176. * @param month the month as a value between 0 and 11.
  177. * @param day the day as a value between 0 and 31.
  178. * @param hour the hour as a value between 0 and 23, in 24-hour
  179. * clock notation.
  180. * @param min the minute as a value between 0 and 59.
  181. * @param sec the second as a value between 0 and 61 (with 60
  182. * and 61 being leap seconds).
  183. */
  184. public Date(int year, int month, int day, int hour, int min, int sec)
  185. {
  186. GregorianCalendar cal =
  187. new GregorianCalendar(year + 1900, month, day, hour, min, sec);
  188. time = cal.getTimeInMillis();
  189. }
  190. /**
  191. * Creates a new Date from the given string representation. This
  192. * does the same as <code>new Date(Date.parse(s))</code>
  193. * @see #parse
  194. * @deprecated use <code>java.text.DateFormat.parse(s)</code> instead.
  195. */
  196. public Date(String s)
  197. {
  198. time = parse(s);
  199. }
  200. /**
  201. * Returns a copy of this <code>Date</code> object.
  202. *
  203. * @return a copy, or null if the object couldn't be
  204. * cloned.
  205. * @see Object#clone()
  206. */
  207. public Object clone()
  208. {
  209. try
  210. {
  211. return super.clone();
  212. }
  213. catch (CloneNotSupportedException ex)
  214. {
  215. return null;
  216. }
  217. }
  218. /**
  219. * Returns the number of milliseconds since the epoch
  220. * specified by the given arguments. The arguments are
  221. * interpreted relative to UTC rather than the local
  222. * time zone.
  223. *
  224. * @deprecated Use <code>Calendar</code> with a UTC
  225. * <code>TimeZone</code> instead.
  226. * @param year the difference between the required year and 1900.
  227. * @param month the month as a value between 0 and 11.
  228. * @param date the day as a value between 0 and 31.
  229. * @param hrs the hour as a value between 0 and 23, in 24-hour
  230. * clock notation.
  231. * @param min the minute as a value between 0 and 59.
  232. * @param sec the second as a value between 0 and 61 (with 60
  233. * and 61 being leap seconds).
  234. * @return the time in milliseconds since the epoch.
  235. */
  236. public static long UTC(int year, int month, int date,
  237. int hrs, int min, int sec)
  238. {
  239. GregorianCalendar cal =
  240. new GregorianCalendar(year + 1900, month, date, hrs, min, sec);
  241. cal.set(Calendar.ZONE_OFFSET, 0);
  242. cal.set(Calendar.DST_OFFSET, 0);
  243. return cal.getTimeInMillis();
  244. }
  245. /**
  246. * Gets the time represented by this object.
  247. *
  248. * @return the time in milliseconds since the epoch.
  249. */
  250. public long getTime()
  251. {
  252. return time;
  253. }
  254. /**
  255. * Returns the number of minutes offset used with UTC to give the time
  256. * represented by this object in the current time zone. The date information
  257. * from this object is also used to determine whether or not daylight savings
  258. * time is in effect. For example, the offset for the UK would be 0 if the
  259. * month of the date object was January, and 1 if the month was August.
  260. *
  261. * @deprecated use
  262. * <code>Calendar.get(Calendar.ZONE_OFFSET)+Calendar.get(Calendar.DST_OFFSET)</code>
  263. * instead.
  264. * @return The time zone offset in minutes of the local time zone
  265. * relative to UTC. The time represented by this object is used to
  266. * determine if we should use daylight savings.
  267. */
  268. public int getTimezoneOffset()
  269. {
  270. Calendar cal = Calendar.getInstance();
  271. cal.setTimeInMillis(time);
  272. return - (cal.get(Calendar.ZONE_OFFSET)
  273. + cal.get(Calendar.DST_OFFSET)) / (60 * 1000);
  274. }
  275. /**
  276. * Sets the time which this object should represent.
  277. *
  278. * @param time the time in milliseconds since the epoch.
  279. */
  280. public void setTime(long time)
  281. {
  282. this.time = time;
  283. }
  284. /**
  285. * Tests if this date is after the specified date.
  286. *
  287. * @param when the other date
  288. * @return true, if the date represented by this object is
  289. * strictly later than the time represented by when.
  290. */
  291. public boolean after(Date when)
  292. {
  293. return time > when.time;
  294. }
  295. /**
  296. * Tests if this date is before the specified date.
  297. *
  298. * @param when the other date
  299. * @return true, if the date represented by when is strictly later
  300. * than the time represented by this object.
  301. */
  302. public boolean before(Date when)
  303. {
  304. return time < when.time;
  305. }
  306. /**
  307. * Compares two dates for equality.
  308. *
  309. * @param obj the object to compare.
  310. * @return true, if obj is a Date object and the time represented
  311. * by obj is exactly the same as the time represented by this
  312. * object.
  313. */
  314. public boolean equals(Object obj)
  315. {
  316. return (obj instanceof Date && time == ((Date) obj).time);
  317. }
  318. /**
  319. * Compares two dates.
  320. *
  321. * @param when the other date.
  322. * @return 0, if the date represented
  323. * by obj is exactly the same as the time represented by this
  324. * object, a negative if this Date is before the other Date, and
  325. * a positive value otherwise.
  326. */
  327. public int compareTo(Date when)
  328. {
  329. return (time < when.time) ? -1 : (time == when.time) ? 0 : 1;
  330. }
  331. /**
  332. * Computes the hash code of this <code>Date</code> as the
  333. * XOR of the most significant and the least significant
  334. * 32 bits of the 64 bit milliseconds value.
  335. *
  336. * @return the hash code.
  337. */
  338. public int hashCode()
  339. {
  340. return (int) time ^ (int) (time >>> 32);
  341. }
  342. /**
  343. * <p>
  344. * Returns a string representation of this date using
  345. * the following date format:
  346. * </p>
  347. * <p>
  348. * <code>day mon dd hh:mm:ss zz yyyy</code>
  349. * </p>
  350. * <p>where the fields used here are:
  351. * <ul>
  352. * <li>
  353. * <code>day</code> -- the day of the week
  354. * (Sunday through to Saturday).
  355. * </li>
  356. * <li>
  357. * <code>mon</code> -- the month (Jan to Dec).
  358. * </li>
  359. * <li>
  360. * <code>dd</code> -- the day of the month
  361. * as two decimal digits (01 to 31).
  362. * </li>
  363. * <li>
  364. * <code>hh</code> -- the hour of the day
  365. * as two decimal digits in 24-hour clock notation
  366. * (01 to 23).
  367. * </li>
  368. * <li>
  369. * <code>mm</code> -- the minute of the day
  370. * as two decimal digits (01 to 59).
  371. * </li>
  372. * <li>
  373. * <code>ss</code> -- the second of the day
  374. * as two decimal digits (01 to 61).
  375. * </li>
  376. * <li>
  377. * <code>zz</code> -- the time zone information if available.
  378. * The possible time zones used include the abbreviations
  379. * recognised by <code>parse()</code> (e.g. GMT, CET, etc.)
  380. * and may reflect the fact that daylight savings time is in
  381. * effect. The empty string is used if there is no time zone
  382. * information.
  383. * </li>
  384. * <li>
  385. * <code>yyyy</code> -- the year as four decimal digits.
  386. * </li>
  387. * </ul>
  388. * <p>
  389. * The <code>DateFormat</code> class should now be
  390. * preferred over using this method.
  391. * </p>
  392. *
  393. * @return A string of the form 'day mon dd hh:mm:ss zz yyyy'
  394. * @see #parse(String)
  395. * @see DateFormat
  396. */
  397. public String toString()
  398. {
  399. Calendar cal = Calendar.getInstance();
  400. cal.setTimeInMillis(time);
  401. String day = "0" + cal.get(Calendar.DATE);
  402. String hour = "0" + cal.get(Calendar.HOUR_OF_DAY);
  403. String min = "0" + cal.get(Calendar.MINUTE);
  404. String sec = "0" + cal.get(Calendar.SECOND);
  405. String year = "000" + cal.get(Calendar.YEAR);
  406. return weekNames[cal.get(Calendar.DAY_OF_WEEK) - 1] + " "
  407. + monthNames[cal.get(Calendar.MONTH)] + " "
  408. + day.substring(day.length() - 2) + " "
  409. + hour.substring(hour.length() - 2) + ":"
  410. + min.substring(min.length() - 2) + ":"
  411. + sec.substring(sec.length() - 2) + " "
  412. +
  413. cal.getTimeZone().getDisplayName(cal.getTimeZone().inDaylightTime(this),
  414. TimeZone.SHORT) + " " +
  415. year.substring(year.length() - 4);
  416. }
  417. /**
  418. * Returns a locale-dependent string representation of this
  419. * <code>Date</code> object.
  420. *
  421. * @deprecated Use DateFormat.format(Date)
  422. * @return A locale-dependent string representation.
  423. * @see #parse(String)
  424. * @see DateFormat
  425. */
  426. public String toLocaleString()
  427. {
  428. return java.text.DateFormat.getInstance().format(this);
  429. }
  430. /**
  431. * <p>
  432. * Returns a string representation of this <code>Date</code>
  433. * object using GMT rather than the local timezone.
  434. * The following date format is used:
  435. * </p>
  436. * <p>
  437. * <code>d mon yyyy hh:mm:ss GMT</code>
  438. * </p>
  439. * <p>where the fields used here are:
  440. * <ul>
  441. * <li>
  442. * <code>d</code> -- the day of the month
  443. * as one or two decimal digits (1 to 31).
  444. * </li>
  445. * <li>
  446. * <code>mon</code> -- the month (Jan to Dec).
  447. * </li>
  448. * <li>
  449. * <code>yyyy</code> -- the year as four decimal digits.
  450. * </li>
  451. * <li>
  452. * <code>hh</code> -- the hour of the day
  453. * as two decimal digits in 24-hour clock notation
  454. * (01 to 23).
  455. * </li>
  456. * <li>
  457. * <code>mm</code> -- the minute of the day
  458. * as two decimal digits (01 to 59).
  459. * </li>
  460. * <li>
  461. * <code>ss</code> -- the second of the day
  462. * as two decimal digits (01 to 61).
  463. * </li>
  464. * <li>
  465. * <code>GMT</code> -- the literal string "GMT"
  466. * indicating Greenwich Mean Time as opposed to
  467. * the local timezone.
  468. * </li>
  469. * </ul>
  470. *
  471. * @deprecated Use DateFormat.format(Date) with a GMT TimeZone.
  472. * @return A string of the form 'd mon yyyy hh:mm:ss GMT' using
  473. * GMT as opposed to the local timezone.
  474. * @see #parse(String)
  475. * @see DateFormat
  476. */
  477. public String toGMTString()
  478. {
  479. java.text.DateFormat format = java.text.DateFormat.getInstance();
  480. format.setTimeZone(TimeZone.getTimeZone("GMT"));
  481. return format.format(this);
  482. }
  483. /**
  484. * Parses the time zone string.
  485. *
  486. * @param tok The token containing the time zone.
  487. * @param sign The sign (+ or -) used by the time zone.
  488. * @return An integer representing the number of minutes offset
  489. * from GMT for the time zone.
  490. */
  491. private static int parseTz(String tok, char sign)
  492. throws IllegalArgumentException
  493. {
  494. int num;
  495. try
  496. {
  497. // parseInt doesn't handle '+' so strip off sign.
  498. num = Integer.parseInt(tok.substring(1));
  499. }
  500. catch (NumberFormatException ex)
  501. {
  502. throw new IllegalArgumentException(tok);
  503. }
  504. // Convert hours to minutes.
  505. if (num < 24)
  506. num *= 60;
  507. else
  508. num = (num / 100) * 60 + num % 100;
  509. return sign == '-' ? -num : num;
  510. }
  511. /**
  512. * Parses the month string.
  513. *
  514. * @param tok the token containing the month.
  515. * @return An integer between 0 and 11, representing
  516. * a month from January (0) to December (11),
  517. * or -1 if parsing failed.
  518. */
  519. private static int parseMonth(String tok)
  520. {
  521. // Initialize strings for month names.
  522. // We could possibly use the fields of DateFormatSymbols but that is
  523. // localized and thus might not match the English words specified.
  524. String months[] = { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY",
  525. "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER",
  526. "NOVEMBER", "DECEMBER" };
  527. int i;
  528. for (i = 0; i < 12; i++)
  529. if (months[i].startsWith(tok))
  530. return i;
  531. // Return -1 if not found.
  532. return -1;
  533. }
  534. /**
  535. * Parses the day of the week string.
  536. *
  537. * @param tok the token containing the day of the week.
  538. * @return true if the token was parsed successfully.
  539. */
  540. private static boolean parseDayOfWeek(String tok)
  541. {
  542. // Initialize strings for days of the week names.
  543. // We could possibly use the fields of DateFormatSymbols but that is
  544. // localized and thus might not match the English words specified.
  545. String daysOfWeek[] = { "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
  546. "THURSDAY", "FRIDAY", "SATURDAY" };
  547. int i;
  548. for (i = 0; i < 7; i++)
  549. if (daysOfWeek[i].startsWith(tok))
  550. return true;
  551. return false;
  552. }
  553. /**
  554. * <p>
  555. * Parses a String and returns the time, in milliseconds since the
  556. * epoch, it represents. Most syntaxes are handled, including
  557. * the IETF date standard "day, dd mon yyyy hh:mm:ss zz" (see
  558. * <code>toString()</code> for definitions of these fields).
  559. * Standard U.S. time zone abbreviations are recognised, in
  560. * addition to time zone offsets in positive or negative minutes.
  561. * If a time zone is specified, the specified time is assumed to
  562. * be in UTC and the appropriate conversion is applied, following
  563. * parsing, to convert this to the local time zone. If no zone
  564. * is specified, the time is assumed to already be in the local
  565. * time zone.
  566. * </p>
  567. * <p>
  568. * The method parses the string progressively from left to right.
  569. * At the end of the parsing process, either a time is returned
  570. * or an <code>IllegalArgumentException</code> is thrown to signify
  571. * failure. The ASCII characters A-Z, a-z, 0-9, and ',', '+', '-',
  572. * ':' and '/' are the only characters permitted within the string,
  573. * besides whitespace and characters enclosed within parantheses
  574. * '(' and ')'.
  575. * </p>
  576. * <p>
  577. * A sequence of consecutive digits are recognised as a number,
  578. * and interpreted as follows:
  579. * <ul>
  580. * <li>
  581. * A number preceded by a sign (+ or -) is taken to be a time zone
  582. * offset. The time zone offset can be specified in either hours
  583. * or minutes. The former is assumed if the number is less than 24.
  584. * Otherwise, the offset is assumed to be in minutes. A - indicates
  585. * a time zone west of GMT, while a + represents a time zone to the
  586. * east of GMT. The time zones are always assumed to be relative
  587. * to GMT, and a (redundant) specification of this can be included
  588. * with the time zone. For example, '-9', 'utc-9' and 'GMT-9' all
  589. * represent a time zone nine hours west of GMT. Similarly,
  590. * '+4', 'ut+4' and 'UTC+4' all give 4 hours east of GMT.
  591. * </li>
  592. * <li>
  593. * A number equal to or greater than 70 is regarded as a year specification.
  594. * Values lower than 70 are only assumed to indicate a year if both the
  595. * day of the month and the month itself have already been recognised.
  596. * Year values less than 100 are interpreted as being relative to the current
  597. * century when the <code>Date</code> class is initialised.. Given a century,
  598. * x, the year is assumed to be within the range x - 80 to x + 19. The value
  599. * itself is then used as a match against the two last digits of one of these
  600. * years. For example, take x to be 2004. A two-digit year is assumed to fall
  601. * within the range x - 80 (1924) and x + 19 (2023). Thus, any intepreted value
  602. * between 0 and 23 is assumed to be 2000 to 2023 and values between 24 and 99
  603. * are taken as being 1924 to 1999. This only applies for the case of 2004.
  604. * With a different year, the values will be interpreted differently. 2005
  605. * will used 0 to 24 as 2000 to 2024 and 25 to 99 as 1925 to 1999, for example.
  606. * This behaviour differs from that of <code>SimpleDateFormat</code> and is
  607. * time-dependent (a two-digit year will be interpreted differently depending
  608. * on the time the code is run).
  609. * </li>
  610. * <li>
  611. * Numbers followed by a colon are interpreted by first an hour, and then
  612. * as a minute, once an hour has been found.
  613. * </li>
  614. * <li>
  615. * <li>
  616. * Numbers followed by a slash are regarded first as a month, and then as
  617. * a day of the month once the month has been found. This follows the
  618. * U.S. date format of mm/dd, rather than the European dd/mm. Months
  619. * are converted to the recognised value - 1 before storage, in order
  620. * to put the number within the range 0 to 11.
  621. * </li>
  622. * <li>
  623. * Numbers followed by commas, whitespace, hyphens or the end of the string
  624. * are interpreted in the following order: hour, minute, second, day of month.
  625. * The first type not already recognised in the current string being parsed is
  626. * assumed.
  627. * </li>
  628. * </ul>
  629. * </p>
  630. * <p>
  631. * A sequence of consecutive alphabetic characters is recognised as a word,
  632. * and interpreted as follows, in a case-insentive fashion:
  633. * <ul>
  634. * <li>
  635. * The characters 'AM' or 'PM' restrict the hour value to a value between 0
  636. * and 12. In the latter case, 12 is added to the hour value before storage.
  637. * </li>
  638. * <li>
  639. * Any words which match any prefix of one of the days of the week ('Monday',
  640. * 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' and 'Sunday'),
  641. * are simply ignored.
  642. * </li>
  643. * <li>
  644. * Any words which match any prefix of one of the months of the year ('January',
  645. * 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September',
  646. * 'October', 'November', 'December') are recognised and interpreted as the
  647. * appropriate value between 0 and 11. The first match made against a
  648. * month is the one used, in the order specified here. For example, 'Ma' is
  649. * intepreted as 'March' (2) and not as 'May' (4). Similarly, 'Ju' is 'June',
  650. * and not 'July'.
  651. * </li>
  652. * <li>
  653. * The words 'GMT', 'UT' and 'UTC' are interpreted as specifying UTC as the
  654. * time zone in use for this date.
  655. * </li>
  656. * <li>
  657. * The word pairs 'EST'/'EDT', 'CST'/'CDT', 'MST'/'MDT' and 'PST'/'PDT' are
  658. * interpreted as the appropriate U.S. time zone abbreviation. Each pair
  659. * is the standard and daylight savings time zone specification, respectively,
  660. * for each zone within the U.S, these being Eastern Standard/Daylight Time
  661. * (-5), Central Standard/Daylight Time (-6), Mountain Standard/Daylight Time
  662. * (-7) and Pacific Standard/Daylight Time (-8).
  663. * </li>
  664. * </ul>
  665. *
  666. * @param string The String to parse.
  667. * @return The time in milliseconds since the epoch.
  668. * @throws IllegalArgumentException if the string fails to parse.
  669. * @deprecated Use DateFormat.parse(String)
  670. * @see #toString()
  671. * @see SimpleDateFormat
  672. */
  673. public static long parse(String string)
  674. {
  675. // Initialize date/time fields before parsing begins.
  676. int year = -1;
  677. int month = -1;
  678. int day = -1;
  679. int hour = -1;
  680. int minute = -1;
  681. int second = -1;
  682. int timezone = 0;
  683. boolean localTimezone = true;
  684. // Trim out any nested stuff in parentheses now to make parsing easier.
  685. CPStringBuilder buf = new CPStringBuilder();
  686. int parenNesting = 0;
  687. int len = string.length();
  688. for (int i = 0; i < len; i++)
  689. {
  690. char ch = string.charAt(i);
  691. if (ch >= 'a' && ch <= 'z')
  692. ch -= 'a' - 'A';
  693. if (ch == '(')
  694. parenNesting++;
  695. else if (parenNesting == 0)
  696. buf.append(ch);
  697. else if (ch == ')')
  698. parenNesting--;
  699. }
  700. int tmpMonth;
  701. // Make all chars upper case to simplify comparisons later.
  702. // Also ignore commas; treat them as delimiters.
  703. StringTokenizer strtok = new StringTokenizer(buf.toString(), " \t\n\r,");
  704. while (strtok.hasMoreTokens())
  705. {
  706. String tok = strtok.nextToken();
  707. char firstch = tok.charAt(0);
  708. if ((firstch == '+' || firstch == '-') && year >= 0)
  709. {
  710. timezone = parseTz(tok, firstch);
  711. localTimezone = false;
  712. }
  713. else if (firstch >= '0' && firstch <= '9')
  714. {
  715. int lastPunct = -1;
  716. while (tok != null && tok.length() > 0)
  717. {
  718. int punctOffset = tok.length();
  719. int num = 0;
  720. int punct;
  721. for (int i = 0; ; i++)
  722. {
  723. if (i >= punctOffset)
  724. {
  725. punct = -1;
  726. break;
  727. }
  728. else
  729. {
  730. punct = tok.charAt(i);
  731. if (punct >= '0' && punct <= '9')
  732. {
  733. if (num > 999999999) // in case of overflow
  734. throw new IllegalArgumentException(tok);
  735. num = 10 * num + (punct - '0');
  736. }
  737. else
  738. {
  739. punctOffset = i;
  740. break;
  741. }
  742. }
  743. }
  744. if (punct == ':')
  745. {
  746. if (hour < 0)
  747. hour = num;
  748. else
  749. minute = num;
  750. }
  751. else if (lastPunct == ':' && hour >= 0 && (minute < 0 || second < 0))
  752. {
  753. if (minute < 0)
  754. minute = num;
  755. else
  756. second = num;
  757. }
  758. else if ((num >= 70
  759. && (punct == ' ' || punct == ','
  760. || punct == '/' || punct < 0))
  761. || (num < 70 && day >= 0 && month >= 0 && year < 0))
  762. {
  763. if (num >= 100)
  764. year = num;
  765. else
  766. {
  767. int curYear = 1900 + new Date().getYear();
  768. int firstYear = curYear - 80;
  769. year = firstYear / 100 * 100 + num;
  770. if (year < firstYear)
  771. year += 100;
  772. }
  773. }
  774. else if (punct == '/')
  775. {
  776. if (month < 0)
  777. month = num - 1;
  778. else
  779. day = num;
  780. }
  781. else if (hour >= 0 && minute < 0)
  782. minute = num;
  783. else if (minute >= 0 && second < 0)
  784. second = num;
  785. else if (day < 0)
  786. day = num;
  787. else
  788. throw new IllegalArgumentException(tok);
  789. // Advance string if there's more to process in this token.
  790. if (punct < 0 || punctOffset + 1 >= tok.length())
  791. tok = null;
  792. else
  793. tok = tok.substring(punctOffset + 1);
  794. lastPunct = punct;
  795. }
  796. }
  797. else if (firstch >= 'A' && firstch <= 'Z')
  798. {
  799. if (tok.equals("AM"))
  800. {
  801. if (hour < 1 || hour > 12)
  802. throw new IllegalArgumentException(tok);
  803. if (hour == 12)
  804. hour = 0;
  805. }
  806. else if (tok.equals("PM"))
  807. {
  808. if (hour < 1 || hour > 12)
  809. throw new IllegalArgumentException(tok);
  810. if (hour < 12)
  811. hour += 12;
  812. }
  813. else if (parseDayOfWeek(tok))
  814. { /* Ignore it; throw the token away. */ }
  815. else if (tok.equals("UT") || tok.equals("UTC") || tok.equals("GMT"))
  816. localTimezone = false;
  817. else if (tok.startsWith("UT") || tok.startsWith("GMT"))
  818. {
  819. int signOffset = 3;
  820. if (tok.charAt(1) == 'T' && tok.charAt(2) != 'C')
  821. signOffset = 2;
  822. char sign = tok.charAt(signOffset);
  823. if (sign != '+' && sign != '-')
  824. throw new IllegalArgumentException(tok);
  825. timezone = parseTz(tok.substring(signOffset), sign);
  826. localTimezone = false;
  827. }
  828. else if ((tmpMonth = parseMonth(tok)) >= 0)
  829. month = tmpMonth;
  830. else if (tok.length() == 3 && tok.charAt(2) == 'T')
  831. {
  832. // Convert timezone offset from hours to minutes.
  833. char ch = tok.charAt(0);
  834. if (ch == 'E')
  835. timezone = -5 * 60;
  836. else if (ch == 'C')
  837. timezone = -6 * 60;
  838. else if (ch == 'M')
  839. timezone = -7 * 60;
  840. else if (ch == 'P')
  841. timezone = -8 * 60;
  842. else
  843. throw new IllegalArgumentException(tok);
  844. // Shift 60 minutes for Daylight Savings Time.
  845. if (tok.charAt(1) == 'D')
  846. timezone += 60;
  847. else if (tok.charAt(1) != 'S')
  848. throw new IllegalArgumentException(tok);
  849. localTimezone = false;
  850. }
  851. else
  852. throw new IllegalArgumentException(tok);
  853. }
  854. else
  855. throw new IllegalArgumentException(tok);
  856. }
  857. // Unspecified hours, minutes, or seconds should default to 0.
  858. if (hour < 0)
  859. hour = 0;
  860. if (minute < 0)
  861. minute = 0;
  862. if (second < 0)
  863. second = 0;
  864. // Throw exception if any other fields have not been recognized and set.
  865. if (year < 0 || month < 0 || day < 0)
  866. throw new IllegalArgumentException("Missing field");
  867. // Return the time in either local time or relative to GMT as parsed.
  868. // If no time-zone was specified, get the local one (in minutes) and
  869. // convert to milliseconds before adding to the UTC.
  870. GregorianCalendar cal
  871. = new GregorianCalendar(year, month, day, hour, minute, second);
  872. if (!localTimezone)
  873. {
  874. cal.set(Calendar.ZONE_OFFSET, timezone * 60 * 1000);
  875. cal.set(Calendar.DST_OFFSET, 0);
  876. }
  877. return cal.getTimeInMillis();
  878. }
  879. /**
  880. * Returns the difference between the year represented by this
  881. * <code>Date</code> object and 1900.
  882. *
  883. * @return the year minus 1900 represented by this date object.
  884. * @deprecated Use Calendar instead of Date, and use get(Calendar.YEAR)
  885. * instead. Note the 1900 difference in the year.
  886. * @see Calendar
  887. * @see #setYear(int)
  888. */
  889. public int getYear()
  890. {
  891. Calendar cal = Calendar.getInstance();
  892. cal.setTimeInMillis(time);
  893. return cal.get(Calendar.YEAR) - 1900;
  894. }
  895. /**
  896. * Sets the year to the specified year, plus 1900. The other
  897. * fields are only altered as required to match the same date
  898. * and time in the new year. Usually, this will mean that
  899. * the fields are not changed at all, but in the case of
  900. * a leap day or leap second, the fields will change in
  901. * relation to the existence of such an event in the new year.
  902. * For example, if the date specifies February the 29th, 2000,
  903. * then this will become March the 1st if the year is changed
  904. * to 2001, as 2001 is not a leap year. Similarly, a seconds
  905. * value of 60 or 61 may result in the seconds becoming 0 and
  906. * the minute increasing by 1, if the new time does not include
  907. * a leap second.
  908. *
  909. * @param year the year minus 1900.
  910. * @deprecated Use Calendar instead of Date, and use
  911. * set(Calendar.YEAR, year) instead. Note about the 1900
  912. * difference in year.
  913. * @see #getYear()
  914. * @see Calendar
  915. */
  916. public void setYear(int year)
  917. {
  918. Calendar cal = Calendar.getInstance();
  919. cal.setTimeInMillis(time);
  920. cal.set(Calendar.YEAR, 1900 + year);
  921. time = cal.getTimeInMillis();
  922. }
  923. /**
  924. * Returns the month represented by this <code>Date</code> object,
  925. * as a value between 0 (January) and 11 (December).
  926. *
  927. * @return the month represented by this date object (zero based).
  928. * @deprecated Use Calendar instead of Date, and use get(Calendar.MONTH)
  929. * instead.
  930. * @see #setMonth(int)
  931. * @see Calendar
  932. */
  933. public int getMonth()
  934. {
  935. Calendar cal = Calendar.getInstance();
  936. cal.setTimeInMillis(time);
  937. return cal.get(Calendar.MONTH);
  938. }
  939. /**
  940. * Sets the month to the given value. The other
  941. * fields are only altered as necessary to match
  942. * the same date and time in the new month. In most
  943. * cases, the other fields won't change at all. However,
  944. * in the case of a shorter month or a leap second, values
  945. * may be adjusted. For example, if the day of the month
  946. * is currently 31, and the month value is changed from
  947. * January (0) to September (8), the date will become
  948. * October the 1st, as September only has 30 days. Similarly,
  949. * a seconds value of 60 or 61 (a leap second) may result
  950. * in the seconds value being reset to 0 and the minutes
  951. * value being incremented by 1, if the new time does
  952. * not include a leap second.
  953. *
  954. * @param month the month, with a zero-based index
  955. * from January.
  956. * @deprecated Use Calendar instead of Date, and use
  957. * set(Calendar.MONTH, month) instead.
  958. * @see #getMonth()
  959. * @see Calendar
  960. */
  961. public void setMonth(int month)
  962. {
  963. Calendar cal = Calendar.getInstance();
  964. cal.setTimeInMillis(time);
  965. cal.set(Calendar.MONTH, month);
  966. time = cal.getTimeInMillis();
  967. }
  968. /**
  969. * Returns the day of the month of this <code>Date</code>
  970. * object, as a value between 0 and 31.
  971. *
  972. * @return the day of month represented by this date object.
  973. * @deprecated Use Calendar instead of Date, and use get(Calendar.DATE)
  974. * instead.
  975. * @see Calendar
  976. * @see #setDate(int)
  977. */
  978. public int getDate()
  979. {
  980. Calendar cal = Calendar.getInstance();
  981. cal.setTimeInMillis(time);
  982. return cal.get(Calendar.DATE);
  983. }
  984. /**
  985. * Sets the date to the given value. The other
  986. * fields are only altered as necessary to match
  987. * the same date and time on the new day of the month. In most
  988. * cases, the other fields won't change at all. However,
  989. * in the case of a leap second or the day being out of
  990. * the range of the current month, values
  991. * may be adjusted. For example, if the day of the month
  992. * is currently 30 and the month is June, a new day of the
  993. * month value of 31 will cause the month to change to July,
  994. * as June only has 30 days . Similarly,
  995. * a seconds value of 60 or 61 (a leap second) may result
  996. * in the seconds value being reset to 0 and the minutes
  997. * value being incremented by 1, if the new time does
  998. * not include a leap second.
  999. *
  1000. * @param date the date.
  1001. * @deprecated Use Calendar instead of Date, and use
  1002. * set(Calendar.DATE, date) instead.
  1003. * @see Calendar
  1004. * @see #getDate()
  1005. */
  1006. public void setDate(int date)
  1007. {
  1008. Calendar cal = Calendar.getInstance();
  1009. cal.setTimeInMillis(time);
  1010. cal.set(Calendar.DATE, date);
  1011. time = cal.getTimeInMillis();
  1012. }
  1013. /**
  1014. * Returns the day represented by this <code>Date</code>
  1015. * object as an integer between 0 (Sunday) and 6 (Saturday).
  1016. *
  1017. * @return the day represented by this date object.
  1018. * @deprecated Use Calendar instead of Date, and use get(Calendar.DAY_OF_WEEK)
  1019. * instead.
  1020. * @see Calendar
  1021. */
  1022. public int getDay()
  1023. {
  1024. Calendar cal = Calendar.getInstance();
  1025. cal.setTimeInMillis(time);
  1026. // For Calendar, Sunday is 1. For Date, Sunday is 0.
  1027. return cal.get(Calendar.DAY_OF_WEEK) - 1;
  1028. }
  1029. /**
  1030. * Returns the hours represented by this <code>Date</code>
  1031. * object as an integer between 0 and 23.
  1032. *
  1033. * @return the hours represented by this date object.
  1034. * @deprecated Use Calendar instead of Date, and use get(Calendar.HOUR_OF_DAY)
  1035. * instead.
  1036. * @see Calendar
  1037. * @see #setHours(int)
  1038. */
  1039. public int getHours()
  1040. {
  1041. Calendar cal = Calendar.getInstance();
  1042. cal.setTimeInMillis(time);
  1043. return cal.get(Calendar.HOUR_OF_DAY);
  1044. }
  1045. /**
  1046. * Sets the hours to the given value. The other
  1047. * fields are only altered as necessary to match
  1048. * the same date and time in the new hour. In most
  1049. * cases, the other fields won't change at all. However,
  1050. * in the case of a leap second, values
  1051. * may be adjusted. For example,
  1052. * a seconds value of 60 or 61 (a leap second) may result
  1053. * in the seconds value being reset to 0 and the minutes
  1054. * value being incremented by 1 if the new hour does
  1055. * not contain a leap second.
  1056. *
  1057. * @param hours the hours.
  1058. * @deprecated Use Calendar instead of Date, and use
  1059. * set(Calendar.HOUR_OF_DAY, hours) instead.
  1060. * @see Calendar
  1061. * @see #getHours()
  1062. */
  1063. public void setHours(int hours)
  1064. {
  1065. Calendar cal = Calendar.getInstance();
  1066. cal.setTimeInMillis(time);
  1067. cal.set(Calendar.HOUR_OF_DAY, hours);
  1068. time = cal.getTimeInMillis();
  1069. }
  1070. /**
  1071. * Returns the number of minutes represented by the <code>Date</code>
  1072. * object, as an integer between 0 and 59.
  1073. *
  1074. * @return the minutes represented by this date object.
  1075. * @deprecated Use Calendar instead of Date, and use get(Calendar.MINUTE)
  1076. * instead.
  1077. * @see Calendar
  1078. * @see #setMinutes(int)
  1079. */
  1080. public int getMinutes()
  1081. {
  1082. Calendar cal = Calendar.getInstance();
  1083. cal.setTimeInMillis(time);
  1084. return cal.get(Calendar.MINUTE);
  1085. }
  1086. /**
  1087. * Sets the minutes to the given value. The other
  1088. * fields are only altered as necessary to match
  1089. * the same date and time in the new minute. In most
  1090. * cases, the other fields won't change at all. However,
  1091. * in the case of a leap second, values
  1092. * may be adjusted. For example,
  1093. * a seconds value of 60 or 61 (a leap second) may result
  1094. * in the seconds value being reset to 0 and the minutes
  1095. * value being incremented by 1 if the new minute does
  1096. * not contain a leap second.
  1097. *
  1098. * @param minutes the minutes.
  1099. * @deprecated Use Calendar instead of Date, and use
  1100. * set(Calendar.MINUTE, minutes) instead.
  1101. * @see Calendar
  1102. * @see #getMinutes()
  1103. */
  1104. public void setMinutes(int minutes)
  1105. {
  1106. Calendar cal = Calendar.getInstance();
  1107. cal.setTimeInMillis(time);
  1108. cal.set(Calendar.MINUTE, minutes);
  1109. time = cal.getTimeInMillis();
  1110. }
  1111. /**
  1112. * Returns the number of seconds represented by the <code>Date</code>
  1113. * object, as an integer between 0 and 61 (60 and 61 being leap seconds).
  1114. *
  1115. * @return the seconds represented by this date object.
  1116. * @deprecated Use Calendar instead of Date, and use get(Calendar.SECOND)
  1117. * instead.
  1118. * @see Calendar
  1119. * @see #setSeconds(int)
  1120. */
  1121. public int getSeconds()
  1122. {
  1123. Calendar cal = Calendar.getInstance();
  1124. cal.setTimeInMillis(time);
  1125. return cal.get(Calendar.SECOND);
  1126. }
  1127. /**
  1128. * Sets the seconds to the given value. The other
  1129. * fields are only altered as necessary to match
  1130. * the same date and time in the new minute. In most
  1131. * cases, the other fields won't change at all. However,
  1132. * in the case of a leap second, values
  1133. * may be adjusted. For example, setting the
  1134. * seconds value to 60 or 61 (a leap second) may result
  1135. * in the seconds value being reset to 0 and the minutes
  1136. * value being incremented by 1, if the current time does
  1137. * not contain a leap second.
  1138. *
  1139. * @param seconds the seconds.
  1140. * @deprecated Use Calendar instead of Date, and use
  1141. * set(Calendar.SECOND, seconds) instead.
  1142. * @see Calendar
  1143. * @see #getSeconds()
  1144. */
  1145. public void setSeconds(int seconds)
  1146. {
  1147. Calendar cal = Calendar.getInstance();
  1148. cal.setTimeInMillis(time);
  1149. cal.set(Calendar.SECOND, seconds);
  1150. time = cal.getTimeInMillis();
  1151. }
  1152. /**
  1153. * Deserializes a <code>Date</code> object from an
  1154. * input stream, setting the time (in milliseconds
  1155. * since the epoch) to the long value read from the
  1156. * stream.
  1157. *
  1158. * @param input the input stream.
  1159. * @throws IOException if an I/O error occurs in the stream.
  1160. * @throws ClassNotFoundException if the class of the
  1161. * serialized object could not be found.
  1162. */
  1163. private void readObject(ObjectInputStream input)
  1164. throws IOException, ClassNotFoundException
  1165. {
  1166. input.defaultReadObject();
  1167. time = input.readLong();
  1168. }
  1169. /**
  1170. * Serializes a <code>Date</code> object to an output stream,
  1171. * storing the time (in milliseconds since the epoch) as a long
  1172. * value in the stream.
  1173. *
  1174. * @serialdata A long value representing the offset from the epoch
  1175. * in milliseconds. This is the same value that is returned by the
  1176. * method getTime().
  1177. * @param output the output stream.
  1178. * @throws IOException if an I/O error occurs in the stream.
  1179. */
  1180. private void writeObject(ObjectOutputStream output)
  1181. throws IOException
  1182. {
  1183. output.defaultWriteObject();
  1184. output.writeLong(time);
  1185. }
  1186. }