DateFormat.java 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956
  1. /* DateFormat.java -- Class for formatting/parsing date/times
  2. Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005
  3. Free Software Foundation, Inc.
  4. This file is part of GNU Classpath.
  5. GNU Classpath is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9. GNU Classpath is distributed in the hope that it will be useful, but
  10. WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GNU Classpath; see the file COPYING. If not, write to the
  15. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16. 02110-1301 USA.
  17. Linking this library statically or dynamically with other modules is
  18. making a combined work based on this library. Thus, the terms and
  19. conditions of the GNU General Public License cover the whole
  20. combination.
  21. As a special exception, the copyright holders of this library give you
  22. permission to link this library with independent modules to produce an
  23. executable, regardless of the license terms of these independent
  24. modules, and to copy and distribute the resulting executable under
  25. terms of your choice, provided that you also meet, for each linked
  26. independent module, the terms and conditions of the license of that
  27. module. An independent module is a module which is not derived from
  28. or based on this library. If you modify this library, you may extend
  29. this exception to your version of the library, but you are not
  30. obligated to do so. If you do not wish to do so, delete this
  31. exception statement from your version. */
  32. package java.text;
  33. import gnu.java.locale.LocaleHelper;
  34. import java.text.spi.DateFormatProvider;
  35. import java.io.InvalidObjectException;
  36. import java.util.Calendar;
  37. import java.util.Date;
  38. import java.util.Locale;
  39. import java.util.MissingResourceException;
  40. import java.util.ResourceBundle;
  41. import java.util.ServiceLoader;
  42. import java.util.TimeZone;
  43. /**
  44. * @author Per Bothner (bothner@cygnus.com)
  45. * @date October 25, 1998.
  46. */
  47. /* Written using "Java Class Libraries", 2nd edition, plus online
  48. * API docs for JDK 1.2 beta from http://www.javasoft.com.
  49. * Status: Mostly complete; search for FIXME to see omissions.
  50. */
  51. public abstract class DateFormat extends Format implements Cloneable
  52. {
  53. private static final long serialVersionUID = 7218322306649953788L;
  54. // Names fixed by serialization spec.
  55. protected Calendar calendar;
  56. protected NumberFormat numberFormat;
  57. // (Values determined using a test program.)
  58. public static final int FULL = 0;
  59. public static final int LONG = 1;
  60. public static final int MEDIUM = 2;
  61. public static final int SHORT = 3;
  62. public static final int DEFAULT = MEDIUM;
  63. /* These constants need to have these exact values. They
  64. * correspond to index positions within the localPatternChars
  65. * string for a given locale. Each locale may specify its
  66. * own character for a particular field, but the position
  67. * of these characters must correspond to an appropriate field
  68. * number (as listed below), in order for their meaning to
  69. * be determined. For example, the US locale uses
  70. * the string "GyMdkHmsSEDFwWahKzYeugAZ", where 'G' is the character
  71. * for era, 'y' for year, and so on down to 'Z' for time zone.
  72. */
  73. /**
  74. * Represents the position of the era
  75. * pattern character in the array of
  76. * localized pattern characters.
  77. * For example, 'AD' is an era used
  78. * in the Gregorian calendar system.
  79. * In the U.S. locale, this is 'G'.
  80. */
  81. public static final int ERA_FIELD = 0;
  82. /**
  83. * Represents the position of the year
  84. * pattern character in the array of
  85. * localized pattern characters.
  86. * In the U.S. locale, this is 'y'.
  87. */
  88. public static final int YEAR_FIELD = 1;
  89. /**
  90. * Represents the position of the month
  91. * pattern character in the array of
  92. * localized pattern characters.
  93. * In the U.S. locale, this is 'M'.
  94. */
  95. public static final int MONTH_FIELD = 2;
  96. /**
  97. * Represents the position of the date
  98. * or day of the month pattern character
  99. * in the array of localized pattern
  100. * characters. In the U.S. locale,
  101. * this is 'd'.
  102. */
  103. public static final int DATE_FIELD = 3;
  104. /**
  105. * Represents the position of the 24
  106. * hour pattern character in the array of
  107. * localized pattern characters.
  108. * In the U.S. locale, this is 'k'.
  109. * This field numbers hours from 1 to 24.
  110. */
  111. public static final int HOUR_OF_DAY1_FIELD = 4;
  112. /**
  113. * Represents the position of the 24
  114. * hour pattern character in the array of
  115. * localized pattern characters.
  116. * In the U.S. locale, this is 'H'.
  117. * This field numbers hours from 0 to 23.
  118. */
  119. public static final int HOUR_OF_DAY0_FIELD = 5;
  120. /**
  121. * Represents the position of the minute
  122. * pattern character in the array of
  123. * localized pattern characters.
  124. * In the U.S. locale, this is 'm'.
  125. */
  126. public static final int MINUTE_FIELD = 6;
  127. /**
  128. * Represents the position of the second
  129. * pattern character in the array of
  130. * localized pattern characters.
  131. * In the U.S. locale, this is 's'.
  132. */
  133. public static final int SECOND_FIELD = 7;
  134. /**
  135. * Represents the position of the millisecond
  136. * pattern character in the array of
  137. * localized pattern characters.
  138. * In the U.S. locale, this is 'S'.
  139. */
  140. public static final int MILLISECOND_FIELD = 8;
  141. /**
  142. * Represents the position of the day of the
  143. * week pattern character in the array of
  144. * localized pattern characters.
  145. * In the U.S. locale, this is 'E'.
  146. */
  147. public static final int DAY_OF_WEEK_FIELD = 9;
  148. /**
  149. * Represents the position of the day of the
  150. * year pattern character in the array of
  151. * localized pattern characters.
  152. * In the U.S. locale, this is 'D'.
  153. */
  154. public static final int DAY_OF_YEAR_FIELD = 10;
  155. /**
  156. * Represents the position of the day of the
  157. * week in the month pattern character in the
  158. * array of localized pattern characters.
  159. * In the U.S. locale, this is 'F'.
  160. */
  161. public static final int DAY_OF_WEEK_IN_MONTH_FIELD = 11;
  162. /**
  163. * Represents the position of the week of the
  164. * year pattern character in the array of
  165. * localized pattern characters.
  166. * In the U.S. locale, this is 'w'.
  167. */
  168. public static final int WEEK_OF_YEAR_FIELD = 12;
  169. /**
  170. * Represents the position of the week of the
  171. * month pattern character in the array of
  172. * localized pattern characters.
  173. * In the U.S. locale, this is 'W'.
  174. */
  175. public static final int WEEK_OF_MONTH_FIELD = 13;
  176. /**
  177. * Represents the position of the am/pm
  178. * pattern character in the array of
  179. * localized pattern characters.
  180. * In the U.S. locale, this is 'a'.
  181. */
  182. public static final int AM_PM_FIELD = 14;
  183. /**
  184. * Represents the position of the 12
  185. * hour pattern character in the array of
  186. * localized pattern characters.
  187. * In the U.S. locale, this is 'h'.
  188. * This field numbers hours from 1 to 12.
  189. */
  190. public static final int HOUR1_FIELD = 15;
  191. /**
  192. * Represents the position of the 12
  193. * hour pattern character in the array of
  194. * localized pattern characters.
  195. * In the U.S. locale, this is 'K'.
  196. * This field numbers hours from 0 to 11.
  197. */
  198. public static final int HOUR0_FIELD = 16;
  199. /**
  200. * Represents the position of the generic
  201. * timezone pattern character in the array of
  202. * localized pattern characters.
  203. * In the U.S. locale, this is 'z'.
  204. */
  205. public static final int TIMEZONE_FIELD = 17;
  206. public static class Field extends Format.Field
  207. {
  208. static final long serialVersionUID = 7441350119349544720L;
  209. private int calendarField;
  210. public static final DateFormat.Field ERA
  211. = new Field("era", Calendar.ERA);
  212. public static final DateFormat.Field YEAR
  213. = new Field("year", Calendar.YEAR);
  214. public static final DateFormat.Field MONTH
  215. = new Field("month", Calendar.MONTH);
  216. public static final DateFormat.Field DAY_OF_MONTH
  217. = new Field("day of month", Calendar.DAY_OF_MONTH);
  218. public static final DateFormat.Field HOUR_OF_DAY1
  219. = new Field("hour of day 1", Calendar.HOUR_OF_DAY);
  220. public static final DateFormat.Field HOUR_OF_DAY0
  221. = new Field("hour of day 0", Calendar.HOUR_OF_DAY);
  222. public static final DateFormat.Field MINUTE
  223. = new Field("minute", Calendar.MINUTE);
  224. public static final DateFormat.Field SECOND
  225. = new Field("second", Calendar.SECOND);
  226. public static final DateFormat.Field MILLISECOND
  227. = new Field("millisecond", Calendar.MILLISECOND);
  228. public static final DateFormat.Field DAY_OF_WEEK
  229. = new Field("day of week", Calendar.DAY_OF_WEEK);
  230. public static final DateFormat.Field DAY_OF_YEAR
  231. = new Field("day of year", Calendar.DAY_OF_YEAR);
  232. public static final DateFormat.Field DAY_OF_WEEK_IN_MONTH
  233. = new Field("day of week in month", Calendar.DAY_OF_WEEK_IN_MONTH);
  234. public static final DateFormat.Field WEEK_OF_YEAR
  235. = new Field("week of year", Calendar.WEEK_OF_YEAR);
  236. public static final DateFormat.Field WEEK_OF_MONTH
  237. = new Field("week of month", Calendar.WEEK_OF_MONTH);
  238. public static final DateFormat.Field AM_PM
  239. = new Field("am/pm", Calendar.AM_PM);
  240. public static final DateFormat.Field HOUR1
  241. = new Field("hour1", Calendar.HOUR);
  242. public static final DateFormat.Field HOUR0
  243. = new Field("hour0", Calendar.HOUR);
  244. public static final DateFormat.Field TIME_ZONE
  245. = new Field("timezone", Calendar.ZONE_OFFSET);
  246. static final DateFormat.Field[] allFields =
  247. {
  248. ERA, YEAR, MONTH, DAY_OF_MONTH, HOUR_OF_DAY1,
  249. HOUR_OF_DAY0, MINUTE, SECOND, MILLISECOND,
  250. DAY_OF_WEEK, DAY_OF_YEAR, DAY_OF_WEEK_IN_MONTH,
  251. WEEK_OF_YEAR, WEEK_OF_MONTH, AM_PM, HOUR1, HOUR0,
  252. TIME_ZONE
  253. };
  254. // For deserialization
  255. private Field()
  256. {
  257. super("");
  258. }
  259. protected Field(String name, int calendarField)
  260. {
  261. super(name);
  262. this.calendarField = calendarField;
  263. }
  264. public int getCalendarField()
  265. {
  266. return calendarField;
  267. }
  268. public static Field ofCalendarField(int calendarField)
  269. {
  270. if (calendarField >= allFields.length || calendarField < 0)
  271. throw new IllegalArgumentException("no such calendar field ("
  272. + calendarField + ")");
  273. return allFields[calendarField];
  274. }
  275. protected Object readResolve() throws InvalidObjectException
  276. {
  277. String s = getName();
  278. for (int i=0;i<allFields.length;i++)
  279. if (s.equals(allFields[i].getName()))
  280. return allFields[i];
  281. throw new InvalidObjectException("no such DateFormat field called " + s);
  282. }
  283. }
  284. /**
  285. * This method initializes a new instance of <code>DateFormat</code>.
  286. */
  287. protected DateFormat ()
  288. {
  289. }
  290. /**
  291. * This method tests this object for equality against the specified object.
  292. * The two objects will be considered equal if an only if the specified
  293. * object:
  294. * <P>
  295. * <ul>
  296. * <li>Is not <code>null</code>.</li>
  297. * <li>Is an instance of <code>DateFormat</code>.</li>
  298. * <li>Has equal numberFormat field as this object.</li>
  299. * <li>Has equal (Calendar) TimeZone rules as this object.</li>
  300. * <li>Has equal (Calendar) isLenient results.</li>
  301. * <li>Has equal Calendar first day of week and minimal days in week
  302. * values.</li>
  303. * </ul>
  304. * Note that not all properties of the Calendar are relevant for a
  305. * DateFormat. For formatting only the fact whether or not the
  306. * TimeZone has the same rules and whether the calendar is lenient
  307. * and has the same week rules is compared for this implementation
  308. * of equals. Other properties of the Calendar (such as the time)
  309. * are not taken into account.
  310. *
  311. * @param obj The object to test for equality against.
  312. *
  313. * @return <code>true</code> if the specified object is equal to this object,
  314. * <code>false</code> otherwise.
  315. */
  316. public boolean equals (Object obj)
  317. {
  318. if (!(obj instanceof DateFormat))
  319. return false;
  320. DateFormat d = (DateFormat) obj;
  321. TimeZone tz = getTimeZone();
  322. TimeZone tzd = d.getTimeZone();
  323. if (tz.hasSameRules(tzd))
  324. if (isLenient() == d.isLenient())
  325. {
  326. Calendar c = getCalendar();
  327. Calendar cd = d.getCalendar();
  328. if ((c == null && cd == null)
  329. ||
  330. (c.getFirstDayOfWeek() == cd.getFirstDayOfWeek()
  331. &&
  332. c.getMinimalDaysInFirstWeek()
  333. == cd.getMinimalDaysInFirstWeek()))
  334. return ((numberFormat == null && d.numberFormat == null)
  335. || numberFormat.equals(d.numberFormat));
  336. }
  337. return false;
  338. }
  339. /**
  340. * This method returns a copy of this object.
  341. *
  342. * @return A copy of this object.
  343. */
  344. public Object clone ()
  345. {
  346. // We know the superclass just call's Object's generic cloner.
  347. return super.clone ();
  348. }
  349. /**
  350. * This method formats the specified <code>Object</code> into a date string
  351. * and appends it to the specified <code>StringBuffer</code>.
  352. * The specified object must be an instance of <code>Number</code> or
  353. * <code>Date</code> or an <code>IllegalArgumentException</code> will be
  354. * thrown.
  355. *
  356. * @param obj The <code>Object</code> to format.
  357. * @param buf The <code>StringBuffer</code> to append the resultant
  358. * <code>String</code> to.
  359. * @param pos Is updated to the start and end index of the
  360. * specified field.
  361. *
  362. * @return The <code>StringBuffer</code> supplied on input, with the
  363. * formatted date/time appended.
  364. */
  365. public final StringBuffer format (Object obj,
  366. StringBuffer buf, FieldPosition pos)
  367. {
  368. if (obj instanceof Number)
  369. obj = new Date(((Number) obj).longValue());
  370. else if (! (obj instanceof Date))
  371. throw new IllegalArgumentException
  372. ("Cannot format given Object as a Date");
  373. return format ((Date) obj, buf, pos);
  374. }
  375. /**
  376. * Formats the date argument according to the pattern specified.
  377. *
  378. * @param date The formatted date.
  379. */
  380. public final String format (Date date)
  381. {
  382. StringBuffer sb = new StringBuffer ();
  383. format (date, sb, new FieldPosition (MONTH_FIELD));
  384. return sb.toString();
  385. }
  386. /**
  387. * This method formats a <code>Date</code> into a string and appends it
  388. * to the specified <code>StringBuffer</code>.
  389. *
  390. * @param date The <code>Date</code> value to format.
  391. * @param buf The <code>StringBuffer</code> to append the resultant
  392. * <code>String</code> to.
  393. * @param pos Is updated to the start and end index of the
  394. * specified field.
  395. *
  396. * @return The <code>StringBuffer</code> supplied on input, with the
  397. * formatted date/time appended.
  398. */
  399. public abstract StringBuffer format (Date date,
  400. StringBuffer buf, FieldPosition pos);
  401. /**
  402. * This method returns a list of available locales supported by this
  403. * class.
  404. */
  405. public static Locale[] getAvailableLocales()
  406. {
  407. return Locale.getAvailableLocales();
  408. }
  409. /**
  410. * This method returns the <code>Calendar</code> object being used by
  411. * this object to parse/format datetimes.
  412. *
  413. * @return The <code>Calendar</code> being used by this object.
  414. *
  415. * @see java.util.Calendar
  416. */
  417. public Calendar getCalendar ()
  418. {
  419. return calendar;
  420. }
  421. private static DateFormat computeInstance (int style, Locale loc,
  422. boolean use_date, boolean use_time)
  423. {
  424. return computeInstance (style, style, loc, use_date, use_time);
  425. }
  426. private static DateFormat computeInstance (int dateStyle, int timeStyle,
  427. Locale loc, boolean use_date,
  428. boolean use_time)
  429. throws MissingResourceException
  430. {
  431. if (loc.equals(Locale.ROOT))
  432. return computeDefault(dateStyle,timeStyle,use_date,use_time);
  433. ResourceBundle res =
  434. ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
  435. loc, ClassLoader.getSystemClassLoader());
  436. String pattern = null;
  437. if (use_date)
  438. {
  439. String name, def;
  440. switch (dateStyle)
  441. {
  442. case FULL:
  443. name = "fullDateFormat";
  444. def = "EEEE MMMM d, yyyy G";
  445. break;
  446. case LONG:
  447. name = "longDateFormat";
  448. def = "MMMM d, yyyy";
  449. break;
  450. case MEDIUM:
  451. name = "mediumDateFormat";
  452. def = "d-MMM-yy";
  453. break;
  454. case SHORT:
  455. name = "shortDateFormat";
  456. def = "M/d/yy";
  457. break;
  458. default:
  459. throw new IllegalArgumentException ();
  460. }
  461. try
  462. {
  463. pattern = res == null ? def : res.getString(name);
  464. }
  465. catch (MissingResourceException x)
  466. {
  467. pattern = def;
  468. }
  469. }
  470. if (use_time)
  471. {
  472. if (pattern == null)
  473. pattern = "";
  474. else
  475. pattern += " ";
  476. String name, def;
  477. switch (timeStyle)
  478. {
  479. case FULL:
  480. name = "fullTimeFormat";
  481. def = "h:mm:ss;S 'o''clock' a z";
  482. break;
  483. case LONG:
  484. name = "longTimeFormat";
  485. def = "h:mm:ss a z";
  486. break;
  487. case MEDIUM:
  488. name = "mediumTimeFormat";
  489. def = "h:mm:ss a";
  490. break;
  491. case SHORT:
  492. name = "shortTimeFormat";
  493. def = "h:mm a";
  494. break;
  495. default:
  496. throw new IllegalArgumentException ();
  497. }
  498. String s;
  499. try
  500. {
  501. s = res == null ? def : res.getString(name);
  502. }
  503. catch (MissingResourceException x)
  504. {
  505. s = def;
  506. }
  507. pattern += s;
  508. }
  509. return new SimpleDateFormat (pattern, loc);
  510. }
  511. private static DateFormat computeDefault (int dateStyle, int timeStyle,
  512. boolean use_date, boolean use_time)
  513. {
  514. String pattern = null;
  515. if (use_date)
  516. {
  517. switch (dateStyle)
  518. {
  519. case FULL:
  520. pattern = "EEEE MMMM d, yyyy G";
  521. break;
  522. case LONG:
  523. pattern = "MMMM d, yyyy";
  524. break;
  525. case MEDIUM:
  526. pattern = "d-MMM-yy";
  527. break;
  528. case SHORT:
  529. pattern = "M/d/yy";
  530. default:
  531. throw new IllegalArgumentException ();
  532. }
  533. }
  534. if (use_time)
  535. {
  536. if (pattern == null)
  537. pattern = "";
  538. else
  539. pattern += " ";
  540. switch (timeStyle)
  541. {
  542. case FULL:
  543. pattern += "h:mm:ss;S 'o''clock' a z";
  544. break;
  545. case LONG:
  546. pattern += "h:mm:ss a z";
  547. break;
  548. case MEDIUM:
  549. pattern += "h:mm:ss a";
  550. break;
  551. case SHORT:
  552. pattern += "h:mm a";
  553. break;
  554. default:
  555. throw new IllegalArgumentException ();
  556. }
  557. }
  558. return new SimpleDateFormat (pattern, Locale.ROOT);
  559. }
  560. /**
  561. * This method returns an instance of <code>DateFormat</code> that will
  562. * format using the default formatting style for dates.
  563. *
  564. * @return A new <code>DateFormat</code> instance.
  565. */
  566. public static final DateFormat getDateInstance ()
  567. {
  568. return getDateInstance (DEFAULT, Locale.getDefault());
  569. }
  570. /**
  571. * This method returns an instance of <code>DateFormat</code> that will
  572. * format using the specified formatting style for dates.
  573. *
  574. * @param style The type of formatting to perform.
  575. *
  576. * @return A new <code>DateFormat</code> instance.
  577. */
  578. public static final DateFormat getDateInstance (int style)
  579. {
  580. return getDateInstance (style, Locale.getDefault());
  581. }
  582. /**
  583. * This method returns an instance of <code>DateFormat</code> that will
  584. * format using the specified formatting style for dates. The specified
  585. * localed will be used in place of the default.
  586. *
  587. * @param style The type of formatting to perform.
  588. * @param loc The desired locale.
  589. *
  590. * @return A new <code>DateFormat</code> instance.
  591. */
  592. public static final DateFormat getDateInstance (int style, Locale loc)
  593. {
  594. try
  595. {
  596. return computeInstance (style, loc, true, false);
  597. }
  598. catch (MissingResourceException e)
  599. {
  600. for (DateFormatProvider p :
  601. ServiceLoader.load(DateFormatProvider.class))
  602. {
  603. for (Locale l : p.getAvailableLocales())
  604. {
  605. if (l.equals(loc))
  606. {
  607. DateFormat df = p.getDateInstance(style, loc);
  608. if (df != null)
  609. return df;
  610. break;
  611. }
  612. }
  613. }
  614. return getDateInstance(style,
  615. LocaleHelper.getFallbackLocale(loc));
  616. }
  617. }
  618. /**
  619. * This method returns a new instance of <code>DateFormat</code> that
  620. * formats both dates and times using the <code>SHORT</code> style.
  621. *
  622. * @return A new <code>DateFormat</code>instance.
  623. */
  624. public static final DateFormat getDateTimeInstance ()
  625. {
  626. return getDateTimeInstance (DEFAULT, DEFAULT, Locale.getDefault());
  627. }
  628. /**
  629. * This method returns a new instance of <code>DateFormat</code> that
  630. * formats both dates and times using the <code>DEFAULT</code> style.
  631. *
  632. * @return A new <code>DateFormat</code>instance.
  633. */
  634. public static final DateFormat getDateTimeInstance (int dateStyle,
  635. int timeStyle)
  636. {
  637. return getDateTimeInstance (dateStyle, timeStyle, Locale.getDefault());
  638. }
  639. /**
  640. * This method returns a new instance of <code>DateFormat</code> that
  641. * formats both dates and times using the specified styles.
  642. *
  643. * @param dateStyle The desired style for date formatting.
  644. * @param timeStyle The desired style for time formatting
  645. *
  646. * @return A new <code>DateFormat</code>instance.
  647. */
  648. public static final DateFormat getDateTimeInstance (int dateStyle,
  649. int timeStyle,
  650. Locale loc)
  651. {
  652. try
  653. {
  654. return computeInstance (dateStyle, timeStyle, loc, true, true);
  655. }
  656. catch (MissingResourceException e)
  657. {
  658. for (DateFormatProvider p :
  659. ServiceLoader.load(DateFormatProvider.class))
  660. {
  661. for (Locale l : p.getAvailableLocales())
  662. {
  663. if (l.equals(loc))
  664. {
  665. DateFormat df = p.getDateTimeInstance(dateStyle,
  666. timeStyle, loc);
  667. if (df != null)
  668. return df;
  669. break;
  670. }
  671. }
  672. }
  673. return getDateTimeInstance(dateStyle, timeStyle,
  674. LocaleHelper.getFallbackLocale(loc));
  675. }
  676. }
  677. /**
  678. * This method returns a new instance of <code>DateFormat</code> that
  679. * formats both dates and times using the <code>SHORT</code> style.
  680. *
  681. * @return A new <code>DateFormat</code>instance.
  682. */
  683. public static final DateFormat getInstance ()
  684. {
  685. // JCL book says SHORT.
  686. return getDateTimeInstance (SHORT, SHORT, Locale.getDefault());
  687. }
  688. /**
  689. * This method returns the <code>NumberFormat</code> object being used
  690. * by this object to parse/format time values.
  691. *
  692. * @return The <code>NumberFormat</code> in use by this object.
  693. */
  694. public NumberFormat getNumberFormat ()
  695. {
  696. return numberFormat;
  697. }
  698. /**
  699. * This method returns an instance of <code>DateFormat</code> that will
  700. * format using the default formatting style for times.
  701. *
  702. * @return A new <code>DateFormat</code> instance.
  703. */
  704. public static final DateFormat getTimeInstance ()
  705. {
  706. return getTimeInstance (DEFAULT, Locale.getDefault());
  707. }
  708. /**
  709. * This method returns an instance of <code>DateFormat</code> that will
  710. * format using the specified formatting style for times.
  711. *
  712. * @param style The type of formatting to perform.
  713. *
  714. * @return A new <code>DateFormat</code> instance.
  715. */
  716. public static final DateFormat getTimeInstance (int style)
  717. {
  718. return getTimeInstance (style, Locale.getDefault());
  719. }
  720. /**
  721. * This method returns an instance of <code>DateFormat</code> that will
  722. * format using the specified formatting style for times. The specified
  723. * localed will be used in place of the default.
  724. *
  725. * @param style The type of formatting to perform.
  726. * @param loc The desired locale.
  727. *
  728. * @return A new <code>DateFormat</code> instance.
  729. */
  730. public static final DateFormat getTimeInstance (int style, Locale loc)
  731. {
  732. try
  733. {
  734. return computeInstance (style, loc, false, true);
  735. }
  736. catch (MissingResourceException e)
  737. {
  738. for (DateFormatProvider p :
  739. ServiceLoader.load(DateFormatProvider.class))
  740. {
  741. for (Locale l : p.getAvailableLocales())
  742. {
  743. if (l.equals(loc))
  744. {
  745. DateFormat df = p.getTimeInstance(style, loc);
  746. if (df != null)
  747. return df;
  748. break;
  749. }
  750. }
  751. }
  752. return getTimeInstance(style,
  753. LocaleHelper.getFallbackLocale(loc));
  754. }
  755. }
  756. /**
  757. * This method returns the <code>TimeZone</code> object being used by
  758. * this instance.
  759. *
  760. * @return The time zone in use.
  761. */
  762. public TimeZone getTimeZone ()
  763. {
  764. return calendar.getTimeZone();
  765. }
  766. /**
  767. * This method returns a hash value for this object.
  768. *
  769. * @return A hash value for this object.
  770. */
  771. public int hashCode ()
  772. {
  773. if (numberFormat != null)
  774. return numberFormat.hashCode();
  775. else
  776. return 0;
  777. }
  778. /**
  779. * This method indicates whether or not the parsing of date and time
  780. * values should be done in a lenient value.
  781. *
  782. * @return <code>true</code> if date/time parsing is lenient,
  783. * <code>false</code> otherwise.
  784. */
  785. public boolean isLenient ()
  786. {
  787. return calendar.isLenient();
  788. }
  789. /**
  790. * This method parses the specified date/time string.
  791. *
  792. * @param source The string to parse.
  793. * @return The resultant date.
  794. *
  795. * @exception ParseException If the specified string cannot be parsed.
  796. */
  797. public Date parse (String source) throws ParseException
  798. {
  799. ParsePosition pos = new ParsePosition(0);
  800. Date result = parse (source, pos);
  801. if (result == null)
  802. {
  803. int index = pos.getErrorIndex();
  804. if (index < 0)
  805. index = pos.getIndex();
  806. throw new ParseException("invalid Date syntax in \""
  807. + source + '\"', index);
  808. }
  809. return result;
  810. }
  811. /**
  812. * This method parses the specified <code>String</code> into a
  813. * <code>Date</code>. The <code>pos</code> argument contains the
  814. * starting parse position on method entry and the ending parse
  815. * position on method exit.
  816. *
  817. * @param source The string to parse.
  818. * @param pos The starting parse position in entry, the ending parse
  819. * position on exit.
  820. *
  821. * @return The parsed date, or <code>null</code> if the string cannot
  822. * be parsed.
  823. */
  824. public abstract Date parse (String source, ParsePosition pos);
  825. /**
  826. * This method is identical to <code>parse(String, ParsePosition)</code>,
  827. * but returns its result as an <code>Object</code> instead of a
  828. * <code>Date</code>.
  829. *
  830. * @param source The string to parse.
  831. * @param pos The starting parse position in entry, the ending parse
  832. * position on exit.
  833. *
  834. * @return The parsed date, or <code>null</code> if the string cannot
  835. * be parsed.
  836. */
  837. public Object parseObject (String source, ParsePosition pos)
  838. {
  839. return parse(source, pos);
  840. }
  841. /**
  842. * This method specified the <code>Calendar</code> that should be used
  843. * by this object to parse/format datetimes.
  844. *
  845. * @param calendar The new <code>Calendar</code> for this object.
  846. *
  847. * @see java.util.Calendar
  848. */
  849. public void setCalendar (Calendar calendar)
  850. {
  851. this.calendar = calendar;
  852. }
  853. /**
  854. * This method specifies whether or not this object should be lenient in
  855. * the syntax it accepts while parsing date/time values.
  856. *
  857. * @param lenient <code>true</code> if parsing should be lenient,
  858. * <code>false</code> otherwise.
  859. */
  860. public void setLenient (boolean lenient)
  861. {
  862. calendar.setLenient(lenient);
  863. }
  864. /**
  865. * This method specifies the <code>NumberFormat</code> object that should
  866. * be used by this object to parse/format times.
  867. *
  868. * @param numberFormat The <code>NumberFormat</code> in use by this object.
  869. */
  870. public void setNumberFormat (NumberFormat numberFormat)
  871. {
  872. this.numberFormat = numberFormat;
  873. }
  874. /**
  875. * This method sets the time zone that should be used by this object.
  876. *
  877. * @param timeZone The new time zone.
  878. */
  879. public void setTimeZone (TimeZone timeZone)
  880. {
  881. calendar.setTimeZone(timeZone);
  882. }
  883. }