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