1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/rt/emul/compact/src/main/java/java/text/DateFormat.java Thu Oct 03 15:40:35 2013 +0200
1.3 @@ -0,0 +1,1030 @@
1.4 +/*
1.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 + *
1.8 + * This code is free software; you can redistribute it and/or modify it
1.9 + * under the terms of the GNU General Public License version 2 only, as
1.10 + * published by the Free Software Foundation. Oracle designates this
1.11 + * particular file as subject to the "Classpath" exception as provided
1.12 + * by Oracle in the LICENSE file that accompanied this code.
1.13 + *
1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 + * version 2 for more details (a copy is included in the LICENSE file that
1.18 + * accompanied this code).
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License version
1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 + *
1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 + * or visit www.oracle.com if you need additional information or have any
1.26 + * questions.
1.27 + */
1.28 +
1.29 +/*
1.30 + * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
1.31 + * (C) Copyright IBM Corp. 1996 - All Rights Reserved
1.32 + *
1.33 + * The original version of this source code and documentation is copyrighted
1.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
1.35 + * materials are provided under terms of a License Agreement between Taligent
1.36 + * and Sun. This technology is protected by multiple US and International
1.37 + * patents. This notice and attribution to Taligent may not be removed.
1.38 + * Taligent is a registered trademark of Taligent, Inc.
1.39 + *
1.40 + */
1.41 +
1.42 +package java.text;
1.43 +
1.44 +import java.io.InvalidObjectException;
1.45 +import java.text.spi.DateFormatProvider;
1.46 +import java.util.Calendar;
1.47 +import java.util.Date;
1.48 +import java.util.GregorianCalendar;
1.49 +import java.util.HashMap;
1.50 +import java.util.Locale;
1.51 +import java.util.Map;
1.52 +import java.util.MissingResourceException;
1.53 +import java.util.ResourceBundle;
1.54 +import java.util.TimeZone;
1.55 +import java.util.spi.LocaleServiceProvider;
1.56 +import sun.util.LocaleServiceProviderPool;
1.57 +
1.58 +/**
1.59 + * {@code DateFormat} is an abstract class for date/time formatting subclasses which
1.60 + * formats and parses dates or time in a language-independent manner.
1.61 + * The date/time formatting subclass, such as {@link SimpleDateFormat}, allows for
1.62 + * formatting (i.e., date -> text), parsing (text -> date), and
1.63 + * normalization. The date is represented as a <code>Date</code> object or
1.64 + * as the milliseconds since January 1, 1970, 00:00:00 GMT.
1.65 + *
1.66 + * <p>{@code DateFormat} provides many class methods for obtaining default date/time
1.67 + * formatters based on the default or a given locale and a number of formatting
1.68 + * styles. The formatting styles include {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, and {@link #SHORT}. More
1.69 + * detail and examples of using these styles are provided in the method
1.70 + * descriptions.
1.71 + *
1.72 + * <p>{@code DateFormat} helps you to format and parse dates for any locale.
1.73 + * Your code can be completely independent of the locale conventions for
1.74 + * months, days of the week, or even the calendar format: lunar vs. solar.
1.75 + *
1.76 + * <p>To format a date for the current Locale, use one of the
1.77 + * static factory methods:
1.78 + * <pre>
1.79 + * myString = DateFormat.getDateInstance().format(myDate);
1.80 + * </pre>
1.81 + * <p>If you are formatting multiple dates, it is
1.82 + * more efficient to get the format and use it multiple times so that
1.83 + * the system doesn't have to fetch the information about the local
1.84 + * language and country conventions multiple times.
1.85 + * <pre>
1.86 + * DateFormat df = DateFormat.getDateInstance();
1.87 + * for (int i = 0; i < myDate.length; ++i) {
1.88 + * output.println(df.format(myDate[i]) + "; ");
1.89 + * }
1.90 + * </pre>
1.91 + * <p>To format a date for a different Locale, specify it in the
1.92 + * call to {@link #getDateInstance(int, Locale) getDateInstance()}.
1.93 + * <pre>
1.94 + * DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE);
1.95 + * </pre>
1.96 + * <p>You can use a DateFormat to parse also.
1.97 + * <pre>
1.98 + * myDate = df.parse(myString);
1.99 + * </pre>
1.100 + * <p>Use {@code getDateInstance} to get the normal date format for that country.
1.101 + * There are other static factory methods available.
1.102 + * Use {@code getTimeInstance} to get the time format for that country.
1.103 + * Use {@code getDateTimeInstance} to get a date and time format. You can pass in
1.104 + * different options to these factory methods to control the length of the
1.105 + * result; from {@link #SHORT} to {@link #MEDIUM} to {@link #LONG} to {@link #FULL}. The exact result depends
1.106 + * on the locale, but generally:
1.107 + * <ul><li>{@link #SHORT} is completely numeric, such as {@code 12.13.52} or {@code 3:30pm}
1.108 + * <li>{@link #MEDIUM} is longer, such as {@code Jan 12, 1952}
1.109 + * <li>{@link #LONG} is longer, such as {@code January 12, 1952} or {@code 3:30:32pm}
1.110 + * <li>{@link #FULL} is pretty completely specified, such as
1.111 + * {@code Tuesday, April 12, 1952 AD or 3:30:42pm PST}.
1.112 + * </ul>
1.113 + *
1.114 + * <p>You can also set the time zone on the format if you wish.
1.115 + * If you want even more control over the format or parsing,
1.116 + * (or want to give your users more control),
1.117 + * you can try casting the {@code DateFormat} you get from the factory methods
1.118 + * to a {@link SimpleDateFormat}. This will work for the majority
1.119 + * of countries; just remember to put it in a {@code try} block in case you
1.120 + * encounter an unusual one.
1.121 + *
1.122 + * <p>You can also use forms of the parse and format methods with
1.123 + * {@link ParsePosition} and {@link FieldPosition} to
1.124 + * allow you to
1.125 + * <ul><li>progressively parse through pieces of a string.
1.126 + * <li>align any particular field, or find out where it is for selection
1.127 + * on the screen.
1.128 + * </ul>
1.129 + *
1.130 + * <h4><a name="synchronization">Synchronization</a></h4>
1.131 + *
1.132 + * <p>
1.133 + * Date formats are not synchronized.
1.134 + * It is recommended to create separate format instances for each thread.
1.135 + * If multiple threads access a format concurrently, it must be synchronized
1.136 + * externally.
1.137 + *
1.138 + * @see Format
1.139 + * @see NumberFormat
1.140 + * @see SimpleDateFormat
1.141 + * @see java.util.Calendar
1.142 + * @see java.util.GregorianCalendar
1.143 + * @see java.util.TimeZone
1.144 + * @author Mark Davis, Chen-Lieh Huang, Alan Liu
1.145 + */
1.146 +public abstract class DateFormat extends Format {
1.147 +
1.148 + /**
1.149 + * The {@link Calendar} instance used for calculating the date-time fields
1.150 + * and the instant of time. This field is used for both formatting and
1.151 + * parsing.
1.152 + *
1.153 + * <p>Subclasses should initialize this field to a {@link Calendar}
1.154 + * appropriate for the {@link Locale} associated with this
1.155 + * <code>DateFormat</code>.
1.156 + * @serial
1.157 + */
1.158 + protected Calendar calendar;
1.159 +
1.160 + /**
1.161 + * The number formatter that <code>DateFormat</code> uses to format numbers
1.162 + * in dates and times. Subclasses should initialize this to a number format
1.163 + * appropriate for the locale associated with this <code>DateFormat</code>.
1.164 + * @serial
1.165 + */
1.166 + protected NumberFormat numberFormat;
1.167 +
1.168 + /**
1.169 + * Useful constant for ERA field alignment.
1.170 + * Used in FieldPosition of date/time formatting.
1.171 + */
1.172 + public final static int ERA_FIELD = 0;
1.173 + /**
1.174 + * Useful constant for YEAR field alignment.
1.175 + * Used in FieldPosition of date/time formatting.
1.176 + */
1.177 + public final static int YEAR_FIELD = 1;
1.178 + /**
1.179 + * Useful constant for MONTH field alignment.
1.180 + * Used in FieldPosition of date/time formatting.
1.181 + */
1.182 + public final static int MONTH_FIELD = 2;
1.183 + /**
1.184 + * Useful constant for DATE field alignment.
1.185 + * Used in FieldPosition of date/time formatting.
1.186 + */
1.187 + public final static int DATE_FIELD = 3;
1.188 + /**
1.189 + * Useful constant for one-based HOUR_OF_DAY field alignment.
1.190 + * Used in FieldPosition of date/time formatting.
1.191 + * HOUR_OF_DAY1_FIELD is used for the one-based 24-hour clock.
1.192 + * For example, 23:59 + 01:00 results in 24:59.
1.193 + */
1.194 + public final static int HOUR_OF_DAY1_FIELD = 4;
1.195 + /**
1.196 + * Useful constant for zero-based HOUR_OF_DAY field alignment.
1.197 + * Used in FieldPosition of date/time formatting.
1.198 + * HOUR_OF_DAY0_FIELD is used for the zero-based 24-hour clock.
1.199 + * For example, 23:59 + 01:00 results in 00:59.
1.200 + */
1.201 + public final static int HOUR_OF_DAY0_FIELD = 5;
1.202 + /**
1.203 + * Useful constant for MINUTE field alignment.
1.204 + * Used in FieldPosition of date/time formatting.
1.205 + */
1.206 + public final static int MINUTE_FIELD = 6;
1.207 + /**
1.208 + * Useful constant for SECOND field alignment.
1.209 + * Used in FieldPosition of date/time formatting.
1.210 + */
1.211 + public final static int SECOND_FIELD = 7;
1.212 + /**
1.213 + * Useful constant for MILLISECOND field alignment.
1.214 + * Used in FieldPosition of date/time formatting.
1.215 + */
1.216 + public final static int MILLISECOND_FIELD = 8;
1.217 + /**
1.218 + * Useful constant for DAY_OF_WEEK field alignment.
1.219 + * Used in FieldPosition of date/time formatting.
1.220 + */
1.221 + public final static int DAY_OF_WEEK_FIELD = 9;
1.222 + /**
1.223 + * Useful constant for DAY_OF_YEAR field alignment.
1.224 + * Used in FieldPosition of date/time formatting.
1.225 + */
1.226 + public final static int DAY_OF_YEAR_FIELD = 10;
1.227 + /**
1.228 + * Useful constant for DAY_OF_WEEK_IN_MONTH field alignment.
1.229 + * Used in FieldPosition of date/time formatting.
1.230 + */
1.231 + public final static int DAY_OF_WEEK_IN_MONTH_FIELD = 11;
1.232 + /**
1.233 + * Useful constant for WEEK_OF_YEAR field alignment.
1.234 + * Used in FieldPosition of date/time formatting.
1.235 + */
1.236 + public final static int WEEK_OF_YEAR_FIELD = 12;
1.237 + /**
1.238 + * Useful constant for WEEK_OF_MONTH field alignment.
1.239 + * Used in FieldPosition of date/time formatting.
1.240 + */
1.241 + public final static int WEEK_OF_MONTH_FIELD = 13;
1.242 + /**
1.243 + * Useful constant for AM_PM field alignment.
1.244 + * Used in FieldPosition of date/time formatting.
1.245 + */
1.246 + public final static int AM_PM_FIELD = 14;
1.247 + /**
1.248 + * Useful constant for one-based HOUR field alignment.
1.249 + * Used in FieldPosition of date/time formatting.
1.250 + * HOUR1_FIELD is used for the one-based 12-hour clock.
1.251 + * For example, 11:30 PM + 1 hour results in 12:30 AM.
1.252 + */
1.253 + public final static int HOUR1_FIELD = 15;
1.254 + /**
1.255 + * Useful constant for zero-based HOUR field alignment.
1.256 + * Used in FieldPosition of date/time formatting.
1.257 + * HOUR0_FIELD is used for the zero-based 12-hour clock.
1.258 + * For example, 11:30 PM + 1 hour results in 00:30 AM.
1.259 + */
1.260 + public final static int HOUR0_FIELD = 16;
1.261 + /**
1.262 + * Useful constant for TIMEZONE field alignment.
1.263 + * Used in FieldPosition of date/time formatting.
1.264 + */
1.265 + public final static int TIMEZONE_FIELD = 17;
1.266 +
1.267 + // Proclaim serial compatibility with 1.1 FCS
1.268 + private static final long serialVersionUID = 7218322306649953788L;
1.269 +
1.270 + /**
1.271 + * Overrides Format.
1.272 + * Formats a time object into a time string. Examples of time objects
1.273 + * are a time value expressed in milliseconds and a Date object.
1.274 + * @param obj must be a Number or a Date.
1.275 + * @param toAppendTo the string buffer for the returning time string.
1.276 + * @return the string buffer passed in as toAppendTo, with formatted text appended.
1.277 + * @param fieldPosition keeps track of the position of the field
1.278 + * within the returned string.
1.279 + * On input: an alignment field,
1.280 + * if desired. On output: the offsets of the alignment field. For
1.281 + * example, given a time text "1996.07.10 AD at 15:08:56 PDT",
1.282 + * if the given fieldPosition is DateFormat.YEAR_FIELD, the
1.283 + * begin index and end index of fieldPosition will be set to
1.284 + * 0 and 4, respectively.
1.285 + * Notice that if the same time field appears
1.286 + * more than once in a pattern, the fieldPosition will be set for the first
1.287 + * occurrence of that time field. For instance, formatting a Date to
1.288 + * the time string "1 PM PDT (Pacific Daylight Time)" using the pattern
1.289 + * "h a z (zzzz)" and the alignment field DateFormat.TIMEZONE_FIELD,
1.290 + * the begin index and end index of fieldPosition will be set to
1.291 + * 5 and 8, respectively, for the first occurrence of the timezone
1.292 + * pattern character 'z'.
1.293 + * @see java.text.Format
1.294 + */
1.295 + public final StringBuffer format(Object obj, StringBuffer toAppendTo,
1.296 + FieldPosition fieldPosition)
1.297 + {
1.298 + if (obj instanceof Date)
1.299 + return format( (Date)obj, toAppendTo, fieldPosition );
1.300 + else if (obj instanceof Number)
1.301 + return format( new Date(((Number)obj).longValue()),
1.302 + toAppendTo, fieldPosition );
1.303 + else
1.304 + throw new IllegalArgumentException("Cannot format given Object as a Date");
1.305 + }
1.306 +
1.307 + /**
1.308 + * Formats a Date into a date/time string.
1.309 + * @param date a Date to be formatted into a date/time string.
1.310 + * @param toAppendTo the string buffer for the returning date/time string.
1.311 + * @param fieldPosition keeps track of the position of the field
1.312 + * within the returned string.
1.313 + * On input: an alignment field,
1.314 + * if desired. On output: the offsets of the alignment field. For
1.315 + * example, given a time text "1996.07.10 AD at 15:08:56 PDT",
1.316 + * if the given fieldPosition is DateFormat.YEAR_FIELD, the
1.317 + * begin index and end index of fieldPosition will be set to
1.318 + * 0 and 4, respectively.
1.319 + * Notice that if the same time field appears
1.320 + * more than once in a pattern, the fieldPosition will be set for the first
1.321 + * occurrence of that time field. For instance, formatting a Date to
1.322 + * the time string "1 PM PDT (Pacific Daylight Time)" using the pattern
1.323 + * "h a z (zzzz)" and the alignment field DateFormat.TIMEZONE_FIELD,
1.324 + * the begin index and end index of fieldPosition will be set to
1.325 + * 5 and 8, respectively, for the first occurrence of the timezone
1.326 + * pattern character 'z'.
1.327 + * @return the string buffer passed in as toAppendTo, with formatted text appended.
1.328 + */
1.329 + public abstract StringBuffer format(Date date, StringBuffer toAppendTo,
1.330 + FieldPosition fieldPosition);
1.331 +
1.332 + /**
1.333 + * Formats a Date into a date/time string.
1.334 + * @param date the time value to be formatted into a time string.
1.335 + * @return the formatted time string.
1.336 + */
1.337 + public final String format(Date date)
1.338 + {
1.339 + return format(date, new StringBuffer(),
1.340 + DontCareFieldPosition.INSTANCE).toString();
1.341 + }
1.342 +
1.343 + /**
1.344 + * Parses text from the beginning of the given string to produce a date.
1.345 + * The method may not use the entire text of the given string.
1.346 + * <p>
1.347 + * See the {@link #parse(String, ParsePosition)} method for more information
1.348 + * on date parsing.
1.349 + *
1.350 + * @param source A <code>String</code> whose beginning should be parsed.
1.351 + * @return A <code>Date</code> parsed from the string.
1.352 + * @exception ParseException if the beginning of the specified string
1.353 + * cannot be parsed.
1.354 + */
1.355 + public Date parse(String source) throws ParseException
1.356 + {
1.357 + ParsePosition pos = new ParsePosition(0);
1.358 + Date result = parse(source, pos);
1.359 + if (pos.index == 0)
1.360 + throw new ParseException("Unparseable date: \"" + source + "\"" ,
1.361 + pos.errorIndex);
1.362 + return result;
1.363 + }
1.364 +
1.365 + /**
1.366 + * Parse a date/time string according to the given parse position. For
1.367 + * example, a time text {@code "07/10/96 4:5 PM, PDT"} will be parsed into a {@code Date}
1.368 + * that is equivalent to {@code Date(837039900000L)}.
1.369 + *
1.370 + * <p> By default, parsing is lenient: If the input is not in the form used
1.371 + * by this object's format method but can still be parsed as a date, then
1.372 + * the parse succeeds. Clients may insist on strict adherence to the
1.373 + * format by calling {@link #setLenient(boolean) setLenient(false)}.
1.374 + *
1.375 + * <p>This parsing operation uses the {@link #calendar} to produce
1.376 + * a {@code Date}. As a result, the {@code calendar}'s date-time
1.377 + * fields and the {@code TimeZone} value may have been
1.378 + * overwritten, depending on subclass implementations. Any {@code
1.379 + * TimeZone} value that has previously been set by a call to
1.380 + * {@link #setTimeZone(java.util.TimeZone) setTimeZone} may need
1.381 + * to be restored for further operations.
1.382 + *
1.383 + * @param source The date/time string to be parsed
1.384 + *
1.385 + * @param pos On input, the position at which to start parsing; on
1.386 + * output, the position at which parsing terminated, or the
1.387 + * start position if the parse failed.
1.388 + *
1.389 + * @return A {@code Date}, or {@code null} if the input could not be parsed
1.390 + */
1.391 + public abstract Date parse(String source, ParsePosition pos);
1.392 +
1.393 + /**
1.394 + * Parses text from a string to produce a <code>Date</code>.
1.395 + * <p>
1.396 + * The method attempts to parse text starting at the index given by
1.397 + * <code>pos</code>.
1.398 + * If parsing succeeds, then the index of <code>pos</code> is updated
1.399 + * to the index after the last character used (parsing does not necessarily
1.400 + * use all characters up to the end of the string), and the parsed
1.401 + * date is returned. The updated <code>pos</code> can be used to
1.402 + * indicate the starting point for the next call to this method.
1.403 + * If an error occurs, then the index of <code>pos</code> is not
1.404 + * changed, the error index of <code>pos</code> is set to the index of
1.405 + * the character where the error occurred, and null is returned.
1.406 + * <p>
1.407 + * See the {@link #parse(String, ParsePosition)} method for more information
1.408 + * on date parsing.
1.409 + *
1.410 + * @param source A <code>String</code>, part of which should be parsed.
1.411 + * @param pos A <code>ParsePosition</code> object with index and error
1.412 + * index information as described above.
1.413 + * @return A <code>Date</code> parsed from the string. In case of
1.414 + * error, returns null.
1.415 + * @exception NullPointerException if <code>pos</code> is null.
1.416 + */
1.417 + public Object parseObject(String source, ParsePosition pos) {
1.418 + return parse(source, pos);
1.419 + }
1.420 +
1.421 + /**
1.422 + * Constant for full style pattern.
1.423 + */
1.424 + public static final int FULL = 0;
1.425 + /**
1.426 + * Constant for long style pattern.
1.427 + */
1.428 + public static final int LONG = 1;
1.429 + /**
1.430 + * Constant for medium style pattern.
1.431 + */
1.432 + public static final int MEDIUM = 2;
1.433 + /**
1.434 + * Constant for short style pattern.
1.435 + */
1.436 + public static final int SHORT = 3;
1.437 + /**
1.438 + * Constant for default style pattern. Its value is MEDIUM.
1.439 + */
1.440 + public static final int DEFAULT = MEDIUM;
1.441 +
1.442 + /**
1.443 + * Gets the time formatter with the default formatting style
1.444 + * for the default locale.
1.445 + * @return a time formatter.
1.446 + */
1.447 + public final static DateFormat getTimeInstance()
1.448 + {
1.449 + return get(DEFAULT, 0, 1, Locale.getDefault(Locale.Category.FORMAT));
1.450 + }
1.451 +
1.452 + /**
1.453 + * Gets the time formatter with the given formatting style
1.454 + * for the default locale.
1.455 + * @param style the given formatting style. For example,
1.456 + * SHORT for "h:mm a" in the US locale.
1.457 + * @return a time formatter.
1.458 + */
1.459 + public final static DateFormat getTimeInstance(int style)
1.460 + {
1.461 + return get(style, 0, 1, Locale.getDefault(Locale.Category.FORMAT));
1.462 + }
1.463 +
1.464 + /**
1.465 + * Gets the time formatter with the given formatting style
1.466 + * for the given locale.
1.467 + * @param style the given formatting style. For example,
1.468 + * SHORT for "h:mm a" in the US locale.
1.469 + * @param aLocale the given locale.
1.470 + * @return a time formatter.
1.471 + */
1.472 + public final static DateFormat getTimeInstance(int style,
1.473 + Locale aLocale)
1.474 + {
1.475 + return get(style, 0, 1, aLocale);
1.476 + }
1.477 +
1.478 + /**
1.479 + * Gets the date formatter with the default formatting style
1.480 + * for the default locale.
1.481 + * @return a date formatter.
1.482 + */
1.483 + public final static DateFormat getDateInstance()
1.484 + {
1.485 + return get(0, DEFAULT, 2, Locale.getDefault(Locale.Category.FORMAT));
1.486 + }
1.487 +
1.488 + /**
1.489 + * Gets the date formatter with the given formatting style
1.490 + * for the default locale.
1.491 + * @param style the given formatting style. For example,
1.492 + * SHORT for "M/d/yy" in the US locale.
1.493 + * @return a date formatter.
1.494 + */
1.495 + public final static DateFormat getDateInstance(int style)
1.496 + {
1.497 + return get(0, style, 2, Locale.getDefault(Locale.Category.FORMAT));
1.498 + }
1.499 +
1.500 + /**
1.501 + * Gets the date formatter with the given formatting style
1.502 + * for the given locale.
1.503 + * @param style the given formatting style. For example,
1.504 + * SHORT for "M/d/yy" in the US locale.
1.505 + * @param aLocale the given locale.
1.506 + * @return a date formatter.
1.507 + */
1.508 + public final static DateFormat getDateInstance(int style,
1.509 + Locale aLocale)
1.510 + {
1.511 + return get(0, style, 2, aLocale);
1.512 + }
1.513 +
1.514 + /**
1.515 + * Gets the date/time formatter with the default formatting style
1.516 + * for the default locale.
1.517 + * @return a date/time formatter.
1.518 + */
1.519 + public final static DateFormat getDateTimeInstance()
1.520 + {
1.521 + return get(DEFAULT, DEFAULT, 3, Locale.getDefault(Locale.Category.FORMAT));
1.522 + }
1.523 +
1.524 + /**
1.525 + * Gets the date/time formatter with the given date and time
1.526 + * formatting styles for the default locale.
1.527 + * @param dateStyle the given date formatting style. For example,
1.528 + * SHORT for "M/d/yy" in the US locale.
1.529 + * @param timeStyle the given time formatting style. For example,
1.530 + * SHORT for "h:mm a" in the US locale.
1.531 + * @return a date/time formatter.
1.532 + */
1.533 + public final static DateFormat getDateTimeInstance(int dateStyle,
1.534 + int timeStyle)
1.535 + {
1.536 + return get(timeStyle, dateStyle, 3, Locale.getDefault(Locale.Category.FORMAT));
1.537 + }
1.538 +
1.539 + /**
1.540 + * Gets the date/time formatter with the given formatting styles
1.541 + * for the given locale.
1.542 + * @param dateStyle the given date formatting style.
1.543 + * @param timeStyle the given time formatting style.
1.544 + * @param aLocale the given locale.
1.545 + * @return a date/time formatter.
1.546 + */
1.547 + public final static DateFormat
1.548 + getDateTimeInstance(int dateStyle, int timeStyle, Locale aLocale)
1.549 + {
1.550 + return get(timeStyle, dateStyle, 3, aLocale);
1.551 + }
1.552 +
1.553 + /**
1.554 + * Get a default date/time formatter that uses the SHORT style for both the
1.555 + * date and the time.
1.556 + */
1.557 + public final static DateFormat getInstance() {
1.558 + return getDateTimeInstance(SHORT, SHORT);
1.559 + }
1.560 +
1.561 + /**
1.562 + * Returns an array of all locales for which the
1.563 + * <code>get*Instance</code> methods of this class can return
1.564 + * localized instances.
1.565 + * The returned array represents the union of locales supported by the Java
1.566 + * runtime and by installed
1.567 + * {@link java.text.spi.DateFormatProvider DateFormatProvider} implementations.
1.568 + * It must contain at least a <code>Locale</code> instance equal to
1.569 + * {@link java.util.Locale#US Locale.US}.
1.570 + *
1.571 + * @return An array of locales for which localized
1.572 + * <code>DateFormat</code> instances are available.
1.573 + */
1.574 + public static Locale[] getAvailableLocales()
1.575 + {
1.576 + LocaleServiceProviderPool pool =
1.577 + LocaleServiceProviderPool.getPool(DateFormatProvider.class);
1.578 + return pool.getAvailableLocales();
1.579 + }
1.580 +
1.581 + /**
1.582 + * Set the calendar to be used by this date format. Initially, the default
1.583 + * calendar for the specified or default locale is used.
1.584 + *
1.585 + * <p>Any {@link java.util.TimeZone TimeZone} and {@linkplain
1.586 + * #isLenient() leniency} values that have previously been set are
1.587 + * overwritten by {@code newCalendar}'s values.
1.588 + *
1.589 + * @param newCalendar the new {@code Calendar} to be used by the date format
1.590 + */
1.591 + public void setCalendar(Calendar newCalendar)
1.592 + {
1.593 + this.calendar = newCalendar;
1.594 + }
1.595 +
1.596 + /**
1.597 + * Gets the calendar associated with this date/time formatter.
1.598 + *
1.599 + * @return the calendar associated with this date/time formatter.
1.600 + */
1.601 + public Calendar getCalendar()
1.602 + {
1.603 + return calendar;
1.604 + }
1.605 +
1.606 + /**
1.607 + * Allows you to set the number formatter.
1.608 + * @param newNumberFormat the given new NumberFormat.
1.609 + */
1.610 + public void setNumberFormat(NumberFormat newNumberFormat)
1.611 + {
1.612 + this.numberFormat = newNumberFormat;
1.613 + }
1.614 +
1.615 + /**
1.616 + * Gets the number formatter which this date/time formatter uses to
1.617 + * format and parse a time.
1.618 + * @return the number formatter which this date/time formatter uses.
1.619 + */
1.620 + public NumberFormat getNumberFormat()
1.621 + {
1.622 + return numberFormat;
1.623 + }
1.624 +
1.625 + /**
1.626 + * Sets the time zone for the calendar of this {@code DateFormat} object.
1.627 + * This method is equivalent to the following call.
1.628 + * <blockquote><pre>
1.629 + * getCalendar().setTimeZone(zone)
1.630 + * </pre></blockquote>
1.631 + *
1.632 + * <p>The {@code TimeZone} set by this method is overwritten by a
1.633 + * {@link #setCalendar(java.util.Calendar) setCalendar} call.
1.634 + *
1.635 + * <p>The {@code TimeZone} set by this method may be overwritten as
1.636 + * a result of a call to the parse method.
1.637 + *
1.638 + * @param zone the given new time zone.
1.639 + */
1.640 + public void setTimeZone(TimeZone zone)
1.641 + {
1.642 + calendar.setTimeZone(zone);
1.643 + }
1.644 +
1.645 + /**
1.646 + * Gets the time zone.
1.647 + * This method is equivalent to the following call.
1.648 + * <blockquote><pre>
1.649 + * getCalendar().getTimeZone()
1.650 + * </pre></blockquote>
1.651 + *
1.652 + * @return the time zone associated with the calendar of DateFormat.
1.653 + */
1.654 + public TimeZone getTimeZone()
1.655 + {
1.656 + return calendar.getTimeZone();
1.657 + }
1.658 +
1.659 + /**
1.660 + * Specify whether or not date/time parsing is to be lenient. With
1.661 + * lenient parsing, the parser may use heuristics to interpret inputs that
1.662 + * do not precisely match this object's format. With strict parsing,
1.663 + * inputs must match this object's format.
1.664 + *
1.665 + * <p>This method is equivalent to the following call.
1.666 + * <blockquote><pre>
1.667 + * getCalendar().setLenient(lenient)
1.668 + * </pre></blockquote>
1.669 + *
1.670 + * <p>This leniency value is overwritten by a call to {@link
1.671 + * #setCalendar(java.util.Calendar) setCalendar()}.
1.672 + *
1.673 + * @param lenient when {@code true}, parsing is lenient
1.674 + * @see java.util.Calendar#setLenient(boolean)
1.675 + */
1.676 + public void setLenient(boolean lenient)
1.677 + {
1.678 + calendar.setLenient(lenient);
1.679 + }
1.680 +
1.681 + /**
1.682 + * Tell whether date/time parsing is to be lenient.
1.683 + * This method is equivalent to the following call.
1.684 + * <blockquote><pre>
1.685 + * getCalendar().isLenient()
1.686 + * </pre></blockquote>
1.687 + *
1.688 + * @return {@code true} if the {@link #calendar} is lenient;
1.689 + * {@code false} otherwise.
1.690 + * @see java.util.Calendar#isLenient()
1.691 + */
1.692 + public boolean isLenient()
1.693 + {
1.694 + return calendar.isLenient();
1.695 + }
1.696 +
1.697 + /**
1.698 + * Overrides hashCode
1.699 + */
1.700 + public int hashCode() {
1.701 + return numberFormat.hashCode();
1.702 + // just enough fields for a reasonable distribution
1.703 + }
1.704 +
1.705 + /**
1.706 + * Overrides equals
1.707 + */
1.708 + public boolean equals(Object obj) {
1.709 + if (this == obj) return true;
1.710 + if (obj == null || getClass() != obj.getClass()) return false;
1.711 + DateFormat other = (DateFormat) obj;
1.712 + return (// calendar.equivalentTo(other.calendar) // THIS API DOESN'T EXIST YET!
1.713 + calendar.getFirstDayOfWeek() == other.calendar.getFirstDayOfWeek() &&
1.714 + calendar.getMinimalDaysInFirstWeek() == other.calendar.getMinimalDaysInFirstWeek() &&
1.715 + calendar.isLenient() == other.calendar.isLenient() &&
1.716 + calendar.getTimeZone().equals(other.calendar.getTimeZone()) &&
1.717 + numberFormat.equals(other.numberFormat));
1.718 + }
1.719 +
1.720 + /**
1.721 + * Overrides Cloneable
1.722 + */
1.723 + public Object clone()
1.724 + {
1.725 + DateFormat other = (DateFormat) super.clone();
1.726 + other.calendar = (Calendar) calendar.clone();
1.727 + other.numberFormat = (NumberFormat) numberFormat.clone();
1.728 + return other;
1.729 + }
1.730 +
1.731 + /**
1.732 + * Creates a DateFormat with the given time and/or date style in the given
1.733 + * locale.
1.734 + * @param timeStyle a value from 0 to 3 indicating the time format,
1.735 + * ignored if flags is 2
1.736 + * @param dateStyle a value from 0 to 3 indicating the time format,
1.737 + * ignored if flags is 1
1.738 + * @param flags either 1 for a time format, 2 for a date format,
1.739 + * or 3 for a date/time format
1.740 + * @param loc the locale for the format
1.741 + */
1.742 + private static DateFormat get(int timeStyle, int dateStyle,
1.743 + int flags, Locale loc) {
1.744 + if ((flags & 1) != 0) {
1.745 + if (timeStyle < 0 || timeStyle > 3) {
1.746 + throw new IllegalArgumentException("Illegal time style " + timeStyle);
1.747 + }
1.748 + } else {
1.749 + timeStyle = -1;
1.750 + }
1.751 + if ((flags & 2) != 0) {
1.752 + if (dateStyle < 0 || dateStyle > 3) {
1.753 + throw new IllegalArgumentException("Illegal date style " + dateStyle);
1.754 + }
1.755 + } else {
1.756 + dateStyle = -1;
1.757 + }
1.758 + try {
1.759 + // Check whether a provider can provide an implementation that's closer
1.760 + // to the requested locale than what the Java runtime itself can provide.
1.761 + LocaleServiceProviderPool pool =
1.762 + LocaleServiceProviderPool.getPool(DateFormatProvider.class);
1.763 + if (pool.hasProviders()) {
1.764 + DateFormat providersInstance = pool.getLocalizedObject(
1.765 + DateFormatGetter.INSTANCE,
1.766 + loc,
1.767 + timeStyle,
1.768 + dateStyle,
1.769 + flags);
1.770 + if (providersInstance != null) {
1.771 + return providersInstance;
1.772 + }
1.773 + }
1.774 +
1.775 + return new SimpleDateFormat(timeStyle, dateStyle, loc);
1.776 + } catch (MissingResourceException e) {
1.777 + return new SimpleDateFormat("M/d/yy h:mm a");
1.778 + }
1.779 + }
1.780 +
1.781 + /**
1.782 + * Create a new date format.
1.783 + */
1.784 + protected DateFormat() {}
1.785 +
1.786 + /**
1.787 + * Defines constants that are used as attribute keys in the
1.788 + * <code>AttributedCharacterIterator</code> returned
1.789 + * from <code>DateFormat.formatToCharacterIterator</code> and as
1.790 + * field identifiers in <code>FieldPosition</code>.
1.791 + * <p>
1.792 + * The class also provides two methods to map
1.793 + * between its constants and the corresponding Calendar constants.
1.794 + *
1.795 + * @since 1.4
1.796 + * @see java.util.Calendar
1.797 + */
1.798 + public static class Field extends Format.Field {
1.799 +
1.800 + // Proclaim serial compatibility with 1.4 FCS
1.801 + private static final long serialVersionUID = 7441350119349544720L;
1.802 +
1.803 + // table of all instances in this class, used by readResolve
1.804 + private static final Map instanceMap = new HashMap(18);
1.805 + // Maps from Calendar constant (such as Calendar.ERA) to Field
1.806 + // constant (such as Field.ERA).
1.807 + private static final Field[] calendarToFieldMapping =
1.808 + new Field[Calendar.FIELD_COUNT];
1.809 +
1.810 + /** Calendar field. */
1.811 + private int calendarField;
1.812 +
1.813 + /**
1.814 + * Returns the <code>Field</code> constant that corresponds to
1.815 + * the <code>Calendar</code> constant <code>calendarField</code>.
1.816 + * If there is no direct mapping between the <code>Calendar</code>
1.817 + * constant and a <code>Field</code>, null is returned.
1.818 + *
1.819 + * @throws IllegalArgumentException if <code>calendarField</code> is
1.820 + * not the value of a <code>Calendar</code> field constant.
1.821 + * @param calendarField Calendar field constant
1.822 + * @return Field instance representing calendarField.
1.823 + * @see java.util.Calendar
1.824 + */
1.825 + public static Field ofCalendarField(int calendarField) {
1.826 + if (calendarField < 0 || calendarField >=
1.827 + calendarToFieldMapping.length) {
1.828 + throw new IllegalArgumentException("Unknown Calendar constant "
1.829 + + calendarField);
1.830 + }
1.831 + return calendarToFieldMapping[calendarField];
1.832 + }
1.833 +
1.834 + /**
1.835 + * Creates a <code>Field</code>.
1.836 + *
1.837 + * @param name the name of the <code>Field</code>
1.838 + * @param calendarField the <code>Calendar</code> constant this
1.839 + * <code>Field</code> corresponds to; any value, even one
1.840 + * outside the range of legal <code>Calendar</code> values may
1.841 + * be used, but <code>-1</code> should be used for values
1.842 + * that don't correspond to legal <code>Calendar</code> values
1.843 + */
1.844 + protected Field(String name, int calendarField) {
1.845 + super(name);
1.846 + this.calendarField = calendarField;
1.847 + if (this.getClass() == DateFormat.Field.class) {
1.848 + instanceMap.put(name, this);
1.849 + if (calendarField >= 0) {
1.850 + // assert(calendarField < Calendar.FIELD_COUNT);
1.851 + calendarToFieldMapping[calendarField] = this;
1.852 + }
1.853 + }
1.854 + }
1.855 +
1.856 + /**
1.857 + * Returns the <code>Calendar</code> field associated with this
1.858 + * attribute. For example, if this represents the hours field of
1.859 + * a <code>Calendar</code>, this would return
1.860 + * <code>Calendar.HOUR</code>. If there is no corresponding
1.861 + * <code>Calendar</code> constant, this will return -1.
1.862 + *
1.863 + * @return Calendar constant for this field
1.864 + * @see java.util.Calendar
1.865 + */
1.866 + public int getCalendarField() {
1.867 + return calendarField;
1.868 + }
1.869 +
1.870 + /**
1.871 + * Resolves instances being deserialized to the predefined constants.
1.872 + *
1.873 + * @throws InvalidObjectException if the constant could not be
1.874 + * resolved.
1.875 + * @return resolved DateFormat.Field constant
1.876 + */
1.877 + protected Object readResolve() throws InvalidObjectException {
1.878 + if (this.getClass() != DateFormat.Field.class) {
1.879 + throw new InvalidObjectException("subclass didn't correctly implement readResolve");
1.880 + }
1.881 +
1.882 + Object instance = instanceMap.get(getName());
1.883 + if (instance != null) {
1.884 + return instance;
1.885 + } else {
1.886 + throw new InvalidObjectException("unknown attribute name");
1.887 + }
1.888 + }
1.889 +
1.890 + //
1.891 + // The constants
1.892 + //
1.893 +
1.894 + /**
1.895 + * Constant identifying the era field.
1.896 + */
1.897 + public final static Field ERA = new Field("era", Calendar.ERA);
1.898 +
1.899 + /**
1.900 + * Constant identifying the year field.
1.901 + */
1.902 + public final static Field YEAR = new Field("year", Calendar.YEAR);
1.903 +
1.904 + /**
1.905 + * Constant identifying the month field.
1.906 + */
1.907 + public final static Field MONTH = new Field("month", Calendar.MONTH);
1.908 +
1.909 + /**
1.910 + * Constant identifying the day of month field.
1.911 + */
1.912 + public final static Field DAY_OF_MONTH = new
1.913 + Field("day of month", Calendar.DAY_OF_MONTH);
1.914 +
1.915 + /**
1.916 + * Constant identifying the hour of day field, where the legal values
1.917 + * are 1 to 24.
1.918 + */
1.919 + public final static Field HOUR_OF_DAY1 = new Field("hour of day 1",-1);
1.920 +
1.921 + /**
1.922 + * Constant identifying the hour of day field, where the legal values
1.923 + * are 0 to 23.
1.924 + */
1.925 + public final static Field HOUR_OF_DAY0 = new
1.926 + Field("hour of day", Calendar.HOUR_OF_DAY);
1.927 +
1.928 + /**
1.929 + * Constant identifying the minute field.
1.930 + */
1.931 + public final static Field MINUTE =new Field("minute", Calendar.MINUTE);
1.932 +
1.933 + /**
1.934 + * Constant identifying the second field.
1.935 + */
1.936 + public final static Field SECOND =new Field("second", Calendar.SECOND);
1.937 +
1.938 + /**
1.939 + * Constant identifying the millisecond field.
1.940 + */
1.941 + public final static Field MILLISECOND = new
1.942 + Field("millisecond", Calendar.MILLISECOND);
1.943 +
1.944 + /**
1.945 + * Constant identifying the day of week field.
1.946 + */
1.947 + public final static Field DAY_OF_WEEK = new
1.948 + Field("day of week", Calendar.DAY_OF_WEEK);
1.949 +
1.950 + /**
1.951 + * Constant identifying the day of year field.
1.952 + */
1.953 + public final static Field DAY_OF_YEAR = new
1.954 + Field("day of year", Calendar.DAY_OF_YEAR);
1.955 +
1.956 + /**
1.957 + * Constant identifying the day of week field.
1.958 + */
1.959 + public final static Field DAY_OF_WEEK_IN_MONTH =
1.960 + new Field("day of week in month",
1.961 + Calendar.DAY_OF_WEEK_IN_MONTH);
1.962 +
1.963 + /**
1.964 + * Constant identifying the week of year field.
1.965 + */
1.966 + public final static Field WEEK_OF_YEAR = new
1.967 + Field("week of year", Calendar.WEEK_OF_YEAR);
1.968 +
1.969 + /**
1.970 + * Constant identifying the week of month field.
1.971 + */
1.972 + public final static Field WEEK_OF_MONTH = new
1.973 + Field("week of month", Calendar.WEEK_OF_MONTH);
1.974 +
1.975 + /**
1.976 + * Constant identifying the time of day indicator
1.977 + * (e.g. "a.m." or "p.m.") field.
1.978 + */
1.979 + public final static Field AM_PM = new
1.980 + Field("am pm", Calendar.AM_PM);
1.981 +
1.982 + /**
1.983 + * Constant identifying the hour field, where the legal values are
1.984 + * 1 to 12.
1.985 + */
1.986 + public final static Field HOUR1 = new Field("hour 1", -1);
1.987 +
1.988 + /**
1.989 + * Constant identifying the hour field, where the legal values are
1.990 + * 0 to 11.
1.991 + */
1.992 + public final static Field HOUR0 = new
1.993 + Field("hour", Calendar.HOUR);
1.994 +
1.995 + /**
1.996 + * Constant identifying the time zone field.
1.997 + */
1.998 + public final static Field TIME_ZONE = new Field("time zone", -1);
1.999 + }
1.1000 +
1.1001 + /**
1.1002 + * Obtains a DateFormat instance from a DateFormatProvider
1.1003 + * implementation.
1.1004 + */
1.1005 + private static class DateFormatGetter
1.1006 + implements LocaleServiceProviderPool.LocalizedObjectGetter<DateFormatProvider, DateFormat> {
1.1007 + private static final DateFormatGetter INSTANCE = new DateFormatGetter();
1.1008 +
1.1009 + public DateFormat getObject(DateFormatProvider dateFormatProvider,
1.1010 + Locale locale,
1.1011 + String key,
1.1012 + Object... params) {
1.1013 + assert params.length == 3;
1.1014 +
1.1015 + int timeStyle = (Integer)params[0];
1.1016 + int dateStyle = (Integer)params[1];
1.1017 + int flags = (Integer)params[2];
1.1018 +
1.1019 + switch (flags) {
1.1020 + case 1:
1.1021 + return dateFormatProvider.getTimeInstance(timeStyle, locale);
1.1022 + case 2:
1.1023 + return dateFormatProvider.getDateInstance(dateStyle, locale);
1.1024 + case 3:
1.1025 + return dateFormatProvider.getDateTimeInstance(dateStyle, timeStyle, locale);
1.1026 + default:
1.1027 + assert false : "should not happen";
1.1028 + }
1.1029 +
1.1030 + return null;
1.1031 + }
1.1032 + }
1.1033 +}