1 /* DateFormat.java -- Class for formatting/parsing date/times
2 Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
41 import java
.io
.InvalidObjectException
;
42 import java
.util
.Calendar
;
43 import java
.util
.Date
;
44 import java
.util
.Locale
;
45 import java
.util
.MissingResourceException
;
46 import java
.util
.ResourceBundle
;
47 import java
.util
.TimeZone
;
50 * @author Per Bothner <bothner@cygnus.com>
51 * @date October 25, 1998.
53 /* Written using "Java Class Libraries", 2nd edition, plus online
54 * API docs for JDK 1.2 beta from http://www.javasoft.com.
55 * Status: Mostly complete; search for FIXME to see omissions.
58 public abstract class DateFormat
extends Format
implements Cloneable
60 protected Calendar calendar
;
61 protected NumberFormat numberFormat
;
63 // (Values determined using a test program.)
64 public static final int FULL
= 0;
65 public static final int LONG
= 1;
66 public static final int MEDIUM
= 2;
67 public static final int SHORT
= 3;
68 public static final int DEFAULT
= MEDIUM
;
70 /* These constants need to have these exact values. They
71 * correspond to index positions within the localPatternChars
72 * string for a given locale. For example, the US locale uses
73 * the string "GyMdkHmsSEDFwWahKz", where 'G' is the character
74 * for era, 'y' for year, and so on down to 'z' for time zone.
76 public static final int ERA_FIELD
= 0;
77 public static final int YEAR_FIELD
= 1;
78 public static final int MONTH_FIELD
= 2;
79 public static final int DATE_FIELD
= 3;
80 public static final int HOUR_OF_DAY1_FIELD
= 4;
81 public static final int HOUR_OF_DAY0_FIELD
= 5;
82 public static final int MINUTE_FIELD
= 6;
83 public static final int SECOND_FIELD
= 7;
84 public static final int MILLISECOND_FIELD
= 8;
85 public static final int DAY_OF_WEEK_FIELD
= 9;
86 public static final int DAY_OF_YEAR_FIELD
= 10;
87 public static final int DAY_OF_WEEK_IN_MONTH_FIELD
= 11;
88 public static final int WEEK_OF_YEAR_FIELD
= 12;
89 public static final int WEEK_OF_MONTH_FIELD
= 13;
90 public static final int AM_PM_FIELD
= 14;
91 public static final int HOUR1_FIELD
= 15;
92 public static final int HOUR0_FIELD
= 16;
93 public static final int TIMEZONE_FIELD
= 17;
96 public static class Field
extends Format
.Field
98 static final long serialVersionUID
= 7441350119349544720L;
100 private int calendarField
;
102 public static final DateFormat
.Field ERA
103 = new Field("era", Calendar
.ERA
);
104 public static final DateFormat
.Field YEAR
105 = new Field("year", Calendar
.YEAR
);
106 public static final DateFormat
.Field MONTH
107 = new Field("month", Calendar
.MONTH
);
108 public static final DateFormat
.Field DAY_OF_MONTH
109 = new Field("day of month", Calendar
.DAY_OF_MONTH
);
110 public static final DateFormat
.Field HOUR_OF_DAY1
111 = new Field("hour of day 1", Calendar
.HOUR_OF_DAY
);
112 public static final DateFormat
.Field HOUR_OF_DAY0
113 = new Field("hour of day 0", Calendar
.HOUR_OF_DAY
);
114 public static final DateFormat
.Field MINUTE
115 = new Field("minute", Calendar
.MINUTE
);
116 public static final DateFormat
.Field SECOND
117 = new Field("second", Calendar
.SECOND
);
118 public static final DateFormat
.Field MILLISECOND
119 = new Field("millisecond", Calendar
.MILLISECOND
);
120 public static final DateFormat
.Field DAY_OF_WEEK
121 = new Field("day of week", Calendar
.DAY_OF_WEEK
);
122 public static final DateFormat
.Field DAY_OF_YEAR
123 = new Field("day of year", Calendar
.DAY_OF_YEAR
);
124 public static final DateFormat
.Field DAY_OF_WEEK_IN_MONTH
125 = new Field("day of week in month", Calendar
.DAY_OF_WEEK_IN_MONTH
);
126 public static final DateFormat
.Field WEEK_OF_YEAR
127 = new Field("week of year", Calendar
.WEEK_OF_YEAR
);
128 public static final DateFormat
.Field WEEK_OF_MONTH
129 = new Field("week of month", Calendar
.WEEK_OF_MONTH
);
130 public static final DateFormat
.Field AM_PM
131 = new Field("am/pm", Calendar
.AM_PM
);
132 public static final DateFormat
.Field HOUR1
133 = new Field("hour1", Calendar
.HOUR
);
134 public static final DateFormat
.Field HOUR0
135 = new Field("hour0", Calendar
.HOUR
);
136 public static final DateFormat
.Field TIME_ZONE
137 = new Field("timezone", Calendar
.ZONE_OFFSET
);
139 public static final DateFormat
.Field
[] allFields
=
141 ERA
, YEAR
, MONTH
, DAY_OF_MONTH
, HOUR_OF_DAY1
,
142 HOUR_OF_DAY0
, MINUTE
, SECOND
, MILLISECOND
,
143 DAY_OF_WEEK
, DAY_OF_YEAR
, DAY_OF_WEEK_IN_MONTH
,
144 WEEK_OF_YEAR
, WEEK_OF_MONTH
, AM_PM
, HOUR1
, HOUR0
,
148 // For deserialization
154 protected Field(String name
, int calendarField
)
157 this.calendarField
= calendarField
;
160 public int getCalendarField()
162 return calendarField
;
165 public static Field
ofCalendarField(int calendarField
)
167 if (calendarField
>= allFields
.length
|| calendarField
< 0)
168 throw new IllegalArgumentException("no such calendar field ("
169 + calendarField
+ ")");
171 return allFields
[calendarField
];
174 protected Object
readResolve() throws InvalidObjectException
176 String s
= getName();
178 for (int i
=0;i
<allFields
.length
;i
++)
179 if (s
.equals(allFields
[i
].getName()))
182 throw new InvalidObjectException("no such DateFormat field called " + s
);
187 * This method initializes a new instance of <code>DateFormat</code>.
189 protected DateFormat ()
194 * This method tests this object for equality against the specified object.
195 * The two objects will be considered equal if an only if the specified
199 * <li>Is not <code>null</code>.
200 * <li>Is an instance of <code>DateFormat</code>.
201 * <li>Has the same numberFormat field value as this object.
204 * @param obj The object to test for equality against.
206 * @return <code>true</code> if the specified object is equal to this object,
207 * <code>false</code> otherwise.
209 public boolean equals (Object obj
)
211 if (!(obj
instanceof DateFormat
))
214 DateFormat d
= (DateFormat
) obj
;
216 return numberFormat
.equals(d
.numberFormat
);
220 * This method returns a copy of this object.
222 * @return A copy of this object.
224 public Object
clone ()
226 // We know the superclass just call's Object's generic cloner.
227 return super.clone ();
231 * This method formats the specified <code>Object</code> into a date string
232 * and appends it to the specified <code>StringBuffer</code>.
233 * The specified object must be an instance of <code>Number</code> or
234 * <code>Date</code> or an <code>IllegalArgumentException</code> will be
237 * @param obj The <code>Object</code> to format.
238 * @param toAppendTo The <code>StringBuffer</code> to append the resultant
239 * <code>String</code> to.
240 * @param fieldPosition Is updated to the start and end index of the
243 * @return The <code>StringBuffer</code> supplied on input, with the
244 * formatted date/time appended.
246 public final StringBuffer
format (Object obj
,
247 StringBuffer buf
, FieldPosition pos
)
249 if (obj
instanceof Number
)
250 obj
= new Date(((Number
) obj
).longValue());
251 else if (! (obj
instanceof Date
))
252 throw new IllegalArgumentException
253 ("Cannot format given Object as a Date");
255 return format ((Date
) obj
, buf
, pos
);
259 * Formats the date argument according to the pattern specified.
261 * @param date The formatted date.
263 public final String
format (Date date
)
265 StringBuffer sb
= new StringBuffer ();
266 format (date
, sb
, new FieldPosition (MONTH_FIELD
));
267 return sb
.toString();
271 * This method formats a <code>Date</code> into a string and appends it
272 * to the specified <code>StringBuffer</code>.
274 * @param date The <code>Date</code> value to format.
275 * @param toAppendTo The <code>StringBuffer</code> to append the resultant
276 * <code>String</code> to.
277 * @param fieldPosition Is updated to the start and end index of the
280 * @return The <code>StringBuffer</code> supplied on input, with the
281 * formatted date/time appended.
283 public abstract StringBuffer
format (Date date
,
284 StringBuffer buf
, FieldPosition pos
);
287 * This method returns a list of available locales supported by this
290 public static Locale
[] getAvailableLocales ()
293 Locale
[] l
= new Locale
[1];
299 * This method returns the <code>Calendar</code> object being used by
300 * this object to parse/format datetimes.
302 * @return The <code>Calendar</code> being used by this object.
304 * @see java.util.Calendar
306 public Calendar
getCalendar ()
311 private static final DateFormat
computeInstance (int style
, Locale loc
,
315 return computeInstance (style
, style
, loc
, use_date
, use_time
);
318 private static final DateFormat
computeInstance (int dateStyle
,
327 res
= ResourceBundle
.getBundle("gnu.java.locale.LocaleInformation",
330 catch (MissingResourceException x
)
335 String pattern
= null;
342 name
= "fullDateFormat";
343 def
= "EEEE MMMM d, yyyy G";
346 name
= "longDateFormat";
347 def
= "MMMM d, yyyy";
350 name
= "mediumDateFormat";
354 name
= "shortDateFormat";
358 throw new IllegalArgumentException ();
362 pattern
= res
== null ? def
: res
.getString(name
);
364 catch (MissingResourceException x
)
381 name
= "fullTimeFormat";
382 def
= "h:mm:ss;S 'o''clock' a z";
385 name
= "longTimeFormat";
389 name
= "mediumTimeFormat";
393 name
= "shortTimeFormat";
397 throw new IllegalArgumentException ();
403 s
= res
== null ? def
: res
.getString(name
);
405 catch (MissingResourceException x
)
412 return new SimpleDateFormat (pattern
, loc
);
416 * This method returns an instance of <code>DateFormat</code> that will
417 * format using the default formatting style for dates.
419 * @return A new <code>DateFormat</code> instance.
421 public static final DateFormat
getDateInstance ()
423 return getDateInstance (DEFAULT
, Locale
.getDefault());
427 * This method returns an instance of <code>DateFormat</code> that will
428 * format using the specified formatting style for dates.
430 * @param style The type of formatting to perform.
432 * @return A new <code>DateFormat</code> instance.
434 public static final DateFormat
getDateInstance (int style
)
436 return getDateInstance (style
, Locale
.getDefault());
440 * This method returns an instance of <code>DateFormat</code> that will
441 * format using the specified formatting style for dates. The specified
442 * localed will be used in place of the default.
444 * @param style The type of formatting to perform.
445 * @param aLocale The desired locale.
447 * @return A new <code>DateFormat</code> instance.
449 public static final DateFormat
getDateInstance (int style
, Locale loc
)
451 return computeInstance (style
, loc
, true, false);
455 * This method returns a new instance of <code>DateFormat</code> that
456 * formats both dates and times using the <code>SHORT</code> style.
458 * @return A new <code>DateFormat</code>instance.
460 public static final DateFormat
getDateTimeInstance ()
462 return getDateTimeInstance (DEFAULT
, DEFAULT
, Locale
.getDefault());
466 * This method returns a new instance of <code>DateFormat</code> that
467 * formats both dates and times using the <code>DEFAULT</code> style.
469 * @return A new <code>DateFormat</code>instance.
471 public static final DateFormat
getDateTimeInstance (int dateStyle
,
474 return getDateTimeInstance (dateStyle
, timeStyle
, Locale
.getDefault());
478 * This method returns a new instance of <code>DateFormat</code> that
479 * formats both dates and times using the specified styles.
481 * @param dateStyle The desired style for date formatting.
482 * @param timeStyle The desired style for time formatting
484 * @return A new <code>DateFormat</code>instance.
486 public static final DateFormat
getDateTimeInstance (int dateStyle
,
490 return computeInstance (dateStyle
, timeStyle
, loc
, true, true);
494 * This method returns a new instance of <code>DateFormat</code> that
495 * formats both dates and times using the <code>SHORT</code> style.
497 * @return A new <code>DateFormat</code>instance.
499 public static final DateFormat
getInstance ()
501 // JCL book says SHORT.
502 return getDateTimeInstance (SHORT
, SHORT
, Locale
.getDefault());
506 * This method returns the <code>NumberFormat</code> object being used
507 * by this object to parse/format time values.
509 * @return The <code>NumberFormat</code> in use by this object.
511 public NumberFormat
getNumberFormat ()
517 * This method returns an instance of <code>DateFormat</code> that will
518 * format using the default formatting style for times.
520 * @return A new <code>DateFormat</code> instance.
522 public static final DateFormat
getTimeInstance ()
524 return getTimeInstance (DEFAULT
, Locale
.getDefault());
528 * This method returns an instance of <code>DateFormat</code> that will
529 * format using the specified formatting style for times.
531 * @param style The type of formatting to perform.
533 * @return A new <code>DateFormat</code> instance.
535 public static final DateFormat
getTimeInstance (int style
)
537 return getTimeInstance (style
, Locale
.getDefault());
541 * This method returns an instance of <code>DateFormat</code> that will
542 * format using the specified formatting style for times. The specified
543 * localed will be used in place of the default.
545 * @param style The type of formatting to perform.
546 * @param aLocale The desired locale.
548 * @return A new <code>DateFormat</code> instance.
550 public static final DateFormat
getTimeInstance (int style
, Locale loc
)
552 return computeInstance (style
, loc
, false, true);
556 * This method returns the <code>TimeZone</code> object being used by
559 * @return The time zone in use.
561 public TimeZone
getTimeZone ()
563 return calendar
.getTimeZone();
567 * This method returns a hash value for this object.
569 * @return A hash value for this object.
571 public int hashCode ()
573 if (numberFormat
!= null)
574 return numberFormat
.hashCode();
580 * This method indicates whether or not the parsing of date and time
581 * values should be done in a lenient value.
583 * @return <code>true</code> if date/time parsing is lenient,
584 * <code>false</code> otherwise.
586 public boolean isLenient ()
588 return calendar
.isLenient();
592 * This method parses the specified date/time string.
594 * @return The resultant date.
596 * @exception ParseException If the specified string cannot be parsed.
598 public Date
parse (String source
) throws ParseException
600 ParsePosition pos
= new ParsePosition(0);
601 Date result
= parse (source
, pos
);
604 int index
= pos
.getErrorIndex();
606 index
= pos
.getIndex();
607 throw new ParseException("invalid Date syntax", index
);
613 * This method parses the specified <code>String</code> into a
614 * <code>Date</code>. The <code>pos</code> argument contains the
615 * starting parse position on method entry and the ending parse
616 * position on method exit.
618 * @param text The string to parse.
619 * @param pos The starting parse position in entry, the ending parse
622 * @return The parsed date, or <code>null</code> if the string cannot
625 public abstract Date
parse (String source
, ParsePosition pos
);
628 * This method is identical to <code>parse(String, ParsePosition)</code>,
629 * but returns its result as an <code>Object</code> instead of a
632 * @param source The string to parse.
633 * @param pos The starting parse position in entry, the ending parse
636 * @return The parsed date, or <code>null</code> if the string cannot
639 public Object
parseObject (String source
, ParsePosition pos
)
641 return parse(source
, pos
);
645 * This method specified the <code>Calendar</code> that should be used
646 * by this object to parse/format datetimes.
648 * @param The new <code>Calendar</code> for this object.
650 * @see java.util.Calendar
652 public void setCalendar (Calendar calendar
)
654 this.calendar
= calendar
;
658 * This method specifies whether or not this object should be lenient in
659 * the syntax it accepts while parsing date/time values.
661 * @param lenient <code>true</code> if parsing should be lenient,
662 * <code>false</code> otherwise.
664 public void setLenient (boolean lenient
)
666 calendar
.setLenient(lenient
);
670 * This method specifies the <code>NumberFormat</code> object that should
671 * be used by this object to parse/format times.
673 * @param The <code>NumberFormat</code> in use by this object.
675 public void setNumberFormat (NumberFormat numberFormat
)
677 this.numberFormat
= numberFormat
;
681 * This method sets the time zone that should be used by this object.
683 * @param The new time zone.
685 public void setTimeZone (TimeZone timeZone
)
687 calendar
.setTimeZone(timeZone
);