| /* DateFormatSymbols.java -- Format over a range of numbers | |
| Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005, 2006 Free Software Foundation, Inc. | |
| This file is part of GNU Classpath. | |
| GNU Classpath is free software; you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation; either version 2, or (at your option) | |
| any later version. | |
| GNU Classpath is distributed in the hope that it will be useful, but | |
| WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| General Public License for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with GNU Classpath; see the file COPYING. If not, write to the | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| 02110-1301 USA. | |
| Linking this library statically or dynamically with other modules is | |
| making a combined work based on this library. Thus, the terms and | |
| conditions of the GNU General Public License cover the whole | |
| combination. | |
| As a special exception, the copyright holders of this library give you | |
| permission to link this library with independent modules to produce an | |
| executable, regardless of the license terms of these independent | |
| modules, and to copy and distribute the resulting executable under | |
| terms of your choice, provided that you also meet, for each linked | |
| independent module, the terms and conditions of the license of that | |
| module. An independent module is a module which is not derived from | |
| or based on this library. If you modify this library, you may extend | |
| this exception to your version of the library, but you are not | |
| obligated to do so. If you do not wish to do so, delete this | |
| exception statement from your version. */ | |
| package java.text; | |
| import gnu.java.locale.LocaleHelper; | |
| import java.io.IOException; | |
| import java.text.spi.DateFormatSymbolsProvider; | |
| import java.util.ArrayList; | |
| import java.util.Arrays; | |
| import java.util.HashMap; | |
| import java.util.List; | |
| import java.util.Locale; | |
| import java.util.Map; | |
| import java.util.MissingResourceException; | |
| import java.util.Properties; | |
| import java.util.ResourceBundle; | |
| import java.util.ServiceLoader; | |
| import java.util.TimeZone; | |
| import java.util.concurrent.ConcurrentMap; | |
| import java.util.concurrent.ConcurrentHashMap; | |
| import java.util.regex.Pattern; | |
| import java.util.spi.TimeZoneNameProvider; | |
| /** | |
| * This class acts as container for locale specific date/time formatting | |
| * information such as the days of the week and the months of the year. | |
| * | |
| * @author Per Bothner (bothner@cygnus.com) | |
| * @author Andrew John Hughes (gnu_andrew@member.fsf.org) | |
| * @date October 24, 1998. | |
| */ | |
| /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3. | |
| * Status: Believed complete and correct. | |
| */ | |
| public class DateFormatSymbols implements java.io.Serializable, Cloneable | |
| { | |
| /** | |
| * The set of properties for obtaining the metazone data. | |
| */ | |
| private static transient final Properties properties; | |
| /** | |
| * Reads in the properties. | |
| */ | |
| static | |
| { | |
| properties = new Properties(); | |
| try | |
| { | |
| properties.load(DateFormatSymbols.class.getResourceAsStream("metazones.properties")); | |
| } | |
| catch (IOException exception) | |
| { | |
| System.out.println("Failed to load weeks resource: " + exception); | |
| } | |
| } | |
| private static final Pattern ZONE_SEP = Pattern.compile("\u00a9"); | |
| private static final Pattern FIELD_SEP = Pattern.compile("\u00ae"); | |
| /** | |
| * Class for storing DateFormatSymbols data parsed from the property files. | |
| */ | |
| private static class DFSData | |
| { | |
| private String[] ampms; | |
| private String[] eras; | |
| private String localPatternChars; | |
| private String[] months; | |
| private String[] shortMonths; | |
| private String[] weekdays; | |
| private String[] shortWeekdays; | |
| private String[] dateFormats; | |
| private String[] timeFormats; | |
| private String[][] runtimeZoneStrings; | |
| /** | |
| * Construct a new instance with the parsed data. | |
| * | |
| * @param ampms strings for "am" and "pm". | |
| * @param eras strings for calendar eras. | |
| * @param localPatternChars localised pattern characters. | |
| * @param months strings for the months of the year. | |
| * @param shortMonths short strings for the months of the year. | |
| * @param weekdays strings for the days of the week. | |
| * @param shortWeekdays short strings for the days of the week. | |
| * @param dateFormats localised date formats. | |
| * @param timeFormats localised time formats. | |
| * @param runtimeZoneStrings localised time zone names. | |
| */ | |
| public DFSData(String[] ampms, String[] eras, String localPatternChars, | |
| String[] months, String[] shortMonths, String[] weekdays, | |
| String[] shortWeekdays, String[] dateFormats, | |
| String[] timeFormats, String[][] runtimeZoneStrings) | |
| { | |
| this.ampms = ampms; | |
| this.eras = eras; | |
| this.localPatternChars = localPatternChars; | |
| this.months = months; | |
| this.shortMonths = shortMonths; | |
| this.weekdays = weekdays; | |
| this.shortWeekdays = shortWeekdays; | |
| this.dateFormats = dateFormats; | |
| this.timeFormats = timeFormats; | |
| this.runtimeZoneStrings = runtimeZoneStrings; | |
| } | |
| /** | |
| * Accessor for the AM/PM data. | |
| * | |
| * @return the AM/PM strings. | |
| */ | |
| public String[] getAMPMs() | |
| { | |
| return ampms.clone(); | |
| } | |
| /** | |
| * Accessor for the era data. | |
| * | |
| * @return the era strings. | |
| */ | |
| public String[] getEras() | |
| { | |
| return eras.clone(); | |
| } | |
| /** | |
| * Accessor for the local pattern characters. | |
| * | |
| * @return the local pattern characters. | |
| */ | |
| public String getLocalPatternChars() | |
| { | |
| return localPatternChars; | |
| } | |
| /** | |
| * Accessor for the months of the year (long form). | |
| * | |
| * @return the months of the year (long form). | |
| */ | |
| public String[] getMonths() | |
| { | |
| return months.clone(); | |
| } | |
| /** | |
| * Accessor for the months of the year (short form). | |
| * | |
| * @return the months of the year (short form). | |
| */ | |
| public String[] getShortMonths() | |
| { | |
| return shortMonths.clone(); | |
| } | |
| /** | |
| * Accessor for the days of the week (long form). | |
| * | |
| * @return the days of the week (long form). | |
| */ | |
| public String[] getWeekdays() | |
| { | |
| return weekdays.clone(); | |
| } | |
| /** | |
| * Accessor for the days of the week (short form). | |
| * | |
| * @return the days of the week (short form). | |
| */ | |
| public String[] getShortWeekdays() | |
| { | |
| return shortWeekdays.clone(); | |
| } | |
| /** | |
| * Accessor for the date formats. | |
| * | |
| * @return the date formats. | |
| */ | |
| public String[] getDateFormats() | |
| { | |
| return dateFormats.clone(); | |
| } | |
| /** | |
| * Accessor for the time formats. | |
| * | |
| * @return the time formats. | |
| */ | |
| public String[] getTimeFormats() | |
| { | |
| return timeFormats.clone(); | |
| } | |
| /** | |
| * Accessor for the zone strings. | |
| * | |
| * @return the zone strings. | |
| */ | |
| public String[][] getZoneStrings() | |
| { | |
| // Perform a deep clone so subarrays aren't modifiable | |
| String[][] clone = runtimeZoneStrings.clone(); | |
| for (int a = 0; a < clone.length; ++a) | |
| clone[a] = runtimeZoneStrings[a].clone(); | |
| return clone; | |
| } | |
| } | |
| private static final ConcurrentMap<Locale, DFSData> dataCache = new ConcurrentHashMap<Locale, DFSData>(); | |
| String[] ampms; | |
| String[] eras; | |
| private String localPatternChars; | |
| String[] months; | |
| String[] shortMonths; | |
| String[] shortWeekdays; | |
| String[] weekdays; | |
| /** | |
| * The timezone strings supplied by the runtime. | |
| */ | |
| private String[][] runtimeZoneStrings; | |
| /** | |
| * Custom timezone strings supplied by {@link #setZoneStrings()}. | |
| */ | |
| private String[][] zoneStrings; | |
| private static final long serialVersionUID = -5987973545549424702L; | |
| // The order of these prefixes must be the same as in DateFormat | |
| private static final String[] formatPrefixes = | |
| { | |
| "full", "long", "medium", "short" | |
| }; | |
| // These are each arrays with a value for SHORT, MEDIUM, LONG, FULL, | |
| // and DEFAULT (constants defined in java.text.DateFormat). While | |
| // not part of the official spec, we need a way to get at locale-specific | |
| // default formatting patterns. They are declared package scope so | |
| // as to be easily accessible where needed (DateFormat, SimpleDateFormat). | |
| transient String[] dateFormats; | |
| transient String[] timeFormats; | |
| /** | |
| * Compiles a string array for a property using data from each of the locales in the | |
| * hierarchy as necessary. | |
| * | |
| * @param bundles the locale hierarchy, starting with the most specific. | |
| * @param name the name of the property. | |
| * @param size the size the array should be when complete. | |
| * @return a completed string array. | |
| */ | |
| private static String[] getStringArray(List<ResourceBundle> bundles, String name, int size) | |
| { | |
| return getStringArray(bundles, name, size, null); | |
| } | |
| /** | |
| * Compiles a string array for a property using data from each of the locales in the | |
| * hierarchy as necessary. If non-null, the fallback array is also used for "sideways" | |
| * inheritance (e.g. if there is no short name for a month, the long name is used rather | |
| * than the empty string). | |
| * | |
| * @param bundles the locale hierarchy, starting with the most specific. | |
| * @param name the name of the property. | |
| * @param size the size the array should be when complete. | |
| * @param fallback an array of long name fallback strings for data with both long and short names. | |
| * @return a completed string array. | |
| */ | |
| private static String[] getStringArray(List<ResourceBundle> bundles, String name, int size, | |
| String[] fallback) | |
| { | |
| String[] data = new String[size]; | |
| Arrays.fill(data, ""); | |
| // Populate array with data from each locale back to the root, starting with the most specific | |
| for (int a = 0; a < bundles.size(); ++a) | |
| { | |
| String localeData = bundles.get(a).getString(name); | |
| String[] array = FIELD_SEP.split(localeData, size); | |
| for (int b = 0; b < data.length; ++b) | |
| { | |
| if (array.length > b && array[b] != null && data[b].isEmpty() && !array[b].isEmpty()) | |
| data[b] = array[b]; | |
| } | |
| } | |
| // Replace any remaining empty strings with data from the fallback array, if non-null | |
| if (fallback != null && fallback.length == size) | |
| { | |
| for (int a = 0; a < data.length; ++a) | |
| { | |
| if (data[a].isEmpty() && fallback[a] != null && !fallback[a].isEmpty()) | |
| data[a] = fallback[a]; | |
| } | |
| } | |
| return data; | |
| } | |
| private static String[][] getZoneStrings(List<ResourceBundle> bundles, Locale locale) | |
| { | |
| List<String[]> allZones = new ArrayList<String[]>(); | |
| try | |
| { | |
| Map<String,String[]> systemZones = new HashMap<String,String[]>(); | |
| for (ResourceBundle bundle : bundles) | |
| { | |
| String country = locale.getCountry(); | |
| String data = bundle.getString("zoneStrings"); | |
| String[] zones = ZONE_SEP.split(data); | |
| for (int a = 0; a < zones.length; ++a) | |
| { | |
| String[] strings = FIELD_SEP.split(zones[a]); | |
| String type = properties.getProperty(strings[0] + "." + country); | |
| if (type == null) | |
| type = properties.getProperty(strings[0] + ".DEFAULT"); | |
| if (type != null) | |
| strings[0] = type; | |
| if (strings.length < 5) | |
| { | |
| String[] newStrings = new String[5]; | |
| System.arraycopy(strings, 0, newStrings, 0, strings.length); | |
| for (int b = strings.length; b < newStrings.length; ++b) | |
| newStrings[b] = ""; | |
| strings = newStrings; | |
| } | |
| String[] existing = systemZones.get(strings[0]); | |
| if (existing != null && existing.length > 1) | |
| { | |
| for (int b = 1; b < existing.length; ++b) | |
| if (!existing[b].equals("")) | |
| strings[b] = existing[b]; | |
| } | |
| systemZones.put(strings[0], strings); | |
| } | |
| } | |
| /* Final sanity check for missing values */ | |
| for (String[] zstrings : systemZones.values()) | |
| { | |
| if (zstrings[1].equals("") && zstrings[2].equals("")) | |
| { | |
| for (Map.Entry<Object,Object> entry : properties.entrySet()) | |
| { | |
| String val = (String) entry.getValue(); | |
| if (val.equals(zstrings[0])) | |
| { | |
| String key = (String) entry.getKey(); | |
| String metazone = key.substring(0, key.indexOf(".")); | |
| String type = properties.getProperty(metazone + "." + locale.getCountry()); | |
| if (type == null) | |
| type = properties.getProperty(metazone + ".DEFAULT"); | |
| if (type != null) | |
| { | |
| String[] ostrings = systemZones.get(type); | |
| zstrings[1] = ostrings[1]; | |
| zstrings[2] = ostrings[2]; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| allZones.addAll(systemZones.values()); | |
| } | |
| catch (MissingResourceException e) | |
| { | |
| /* This means runtime support for the locale | |
| * is not available, so we just include providers. */ | |
| } | |
| for (TimeZoneNameProvider p : | |
| ServiceLoader.load(TimeZoneNameProvider.class)) | |
| { | |
| for (Locale loc : p.getAvailableLocales()) | |
| { | |
| if (loc.equals(locale)) | |
| { | |
| for (String id : TimeZone.getAvailableIDs()) | |
| { | |
| String[] z = new String[5]; | |
| z[0] = id; | |
| z[1] = p.getDisplayName(id, false, | |
| TimeZone.LONG, | |
| locale); | |
| z[2] = p.getDisplayName(id, false, | |
| TimeZone.SHORT, | |
| locale); | |
| z[3] = p.getDisplayName(id, true, | |
| TimeZone.LONG, | |
| locale); | |
| z[4] = p.getDisplayName(id, true, | |
| TimeZone.SHORT, | |
| locale); | |
| allZones.add(z); | |
| } | |
| break; | |
| } | |
| } | |
| } | |
| return allZones.toArray(new String[allZones.size()][]); | |
| } | |
| /** | |
| * Retrieve the date or time formats for a specific key e.g. | |
| * asking for "DateFormat" will return an array containing the | |
| * full, long, medium and short date formats localised for | |
| * the locales in the specified bundle. | |
| * | |
| * @param bundles the stack of bundles to check, most-specific first. | |
| * @param key the type of format to retrieve. | |
| * @param an array of localised strings for each format prefix. | |
| */ | |
| private static String[] formatsForKey(List<ResourceBundle> bundles, String key) | |
| { | |
| String[] values = new String[formatPrefixes.length]; | |
| for (int i = 0; i < formatPrefixes.length; i++) | |
| values[i] = getString(bundles, formatPrefixes[i] + key); | |
| return values; | |
| } | |
| /** | |
| * Simple wrapper around extracting a {@code String} from a | |
| * {@code ResourceBundle}. Keep searching less-specific locales | |
| * until a non-null non-empty value is found. | |
| * | |
| * @param bundles the stack of bundles to check, most-specific first. | |
| * @param key the key of the value to retrieve. | |
| * @return the first non-null non-empty String found or the last | |
| * retrieved if one isn't found. | |
| */ | |
| private static String getString(List<ResourceBundle> bundles, String key) | |
| { | |
| String val = null; | |
| for (ResourceBundle bundle : bundles) | |
| { | |
| val = bundle.getString(key); | |
| if (val != null && !val.isEmpty()) | |
| return val; | |
| } | |
| return val; | |
| } | |
| /** | |
| * Retrieves the locale data from the property files and constructs a | |
| * {@code DFSData} instance for it. | |
| * | |
| * @param the locale for which data should be retrieved. | |
| * @return the parsed data. | |
| * @throws MissingResourceException if the resources for the specified | |
| * locale could not be found or loaded. | |
| */ | |
| private static DFSData retrieveData(Locale locale) | |
| throws MissingResourceException | |
| { | |
| DFSData data = dataCache.get(locale); | |
| if (data == null) | |
| { | |
| ClassLoader ldr = ClassLoader.getSystemClassLoader(); | |
| List<ResourceBundle> bundles = new ArrayList<ResourceBundle>(); | |
| ResourceBundle res | |
| = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation", locale, ldr); | |
| bundles.add(res); | |
| Locale resLocale = res.getLocale(); | |
| while (resLocale != Locale.ROOT) | |
| { | |
| res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation", | |
| LocaleHelper.getFallbackLocale(resLocale), ldr); | |
| bundles.add(res); | |
| resLocale = res.getLocale(); | |
| } | |
| String[] lMonths = getStringArray(bundles, "months", 13); | |
| String[] lWeekdays = getStringArray(bundles, "weekdays", 8); | |
| data = new DFSData(getStringArray(bundles, "ampms", 2), | |
| getStringArray(bundles, "eras", 2), | |
| getString(bundles, "localPatternChars"), | |
| lMonths, getStringArray(bundles, "shortMonths", 13, lMonths), | |
| lWeekdays, getStringArray(bundles, "shortWeekdays", 8, lWeekdays), | |
| formatsForKey(bundles, "DateFormat"), | |
| formatsForKey(bundles, "TimeFormat"), | |
| getZoneStrings(bundles, locale)); | |
| DFSData cachedData = dataCache.putIfAbsent(locale, data); | |
| // Use the earlier version if another thread beat us to it. | |
| if (cachedData != null) | |
| data = cachedData; | |
| } | |
| return data; | |
| } | |
| /** | |
| * This method initializes a new instance of <code>DateFormatSymbols</code> | |
| * by loading the date format information for the specified locale. | |
| * This constructor only obtains instances using the runtime's resources; | |
| * to also include {@link java.text.spi.DateFormatSymbolsProvider} instances, | |
| * call {@link #getInstance(java.util.Locale)} instead. | |
| * | |
| * @param locale The locale for which date formatting symbols should | |
| * be loaded. | |
| * @throws MissingResourceException if the resources for the specified | |
| * locale could not be found or loaded. | |
| * @see #getInstance(java.util.Locale) | |
| */ | |
| public DateFormatSymbols (Locale locale) | |
| throws MissingResourceException | |
| { | |
| DFSData data = retrieveData(locale); | |
| ampms = data.getAMPMs(); | |
| eras = data.getEras(); | |
| localPatternChars = data.getLocalPatternChars(); | |
| months = data.getMonths(); | |
| shortMonths = data.getShortMonths(); | |
| weekdays = data.getWeekdays(); | |
| shortWeekdays = data.getShortWeekdays(); | |
| dateFormats = data.getDateFormats(); | |
| timeFormats = data.getTimeFormats(); | |
| runtimeZoneStrings = data.getZoneStrings(); | |
| } | |
| /** | |
| * This method loads the format symbol information for the default | |
| * locale. This constructor only obtains instances using the runtime's resources; | |
| * to also include {@link java.text.spi.DateFormatSymbolsProvider} instances, | |
| * call {@link #getInstance()} instead. | |
| * | |
| * @throws MissingResourceException if the resources for the default | |
| * locale could not be found or loaded. | |
| * @see #getInstance() | |
| */ | |
| public DateFormatSymbols() | |
| throws MissingResourceException | |
| { | |
| this (Locale.getDefault()); | |
| } | |
| /** | |
| * This method returns the list of strings used for displaying AM or PM. | |
| * This is a two element <code>String</code> array indexed by | |
| * <code>Calendar.AM</code> and <code>Calendar.PM</code> | |
| * | |
| * @return The list of AM/PM display strings. | |
| */ | |
| public String[] getAmPmStrings() | |
| { | |
| return ampms; | |
| } | |
| /** | |
| * This method returns the list of strings used for displaying eras | |
| * (e.g., "BC" and "AD"). This is a two element <code>String</code> | |
| * array indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>. | |
| * | |
| * @return The list of era disply strings. | |
| */ | |
| public String[] getEras() | |
| { | |
| return eras; | |
| } | |
| /** | |
| * This method returns the pattern character information for this | |
| * object. This is an 18 character string that contains the characters | |
| * that are used in creating the date formatting strings in | |
| * <code>SimpleDateFormat</code>. The following are the character | |
| * positions in the string and which format character they correspond | |
| * to (the character in parentheses is the default value in the US English | |
| * locale): | |
| * <p> | |
| * <ul> | |
| * <li>0 - era (G)</li> | |
| * <li>1 - year (y)</li> | |
| * <li>2 - month (M)</li> | |
| * <li>3 - day of month (d)</li> | |
| * <li>4 - hour out of 12, from 1-12 (h)</li> | |
| * <li>5 - hour out of 24, from 0-23 (H)</li> | |
| * <li>6 - minute (m)</li> | |
| * <li>7 - second (s)</li> | |
| * <li>8 - millisecond (S)</li> | |
| * <li>9 - date of week (E)</li> | |
| * <li>10 - date of year (D)</li> | |
| * <li>11 - day of week in month, eg. "4th Thur in Nov" (F)</li> | |
| * <li>12 - week in year (w)</li> | |
| * <li>13 - week in month (W)</li> | |
| * <li>14 - am/pm (a)</li> | |
| * <li>15 - hour out of 24, from 1-24 (k)</li> | |
| * <li>16 - hour out of 12, from 0-11 (K)</li> | |
| * <li>17 - time zone (z)</li> | |
| * </ul> | |
| * | |
| * @return The format patter characters | |
| */ | |
| public String getLocalPatternChars() | |
| { | |
| return localPatternChars; | |
| } | |
| /** | |
| * This method returns the list of strings used for displaying month | |
| * names (e.g., "January" and "February"). This is a thirteen element | |
| * string array indexed by <code>Calendar.JANUARY</code> through | |
| * <code>Calendar.UNDECEMBER</code>. Note that there are thirteen | |
| * elements because some calendars have thriteen months. | |
| * | |
| * @return The list of month display strings. | |
| */ | |
| public String[] getMonths () | |
| { | |
| return months; | |
| } | |
| /** | |
| * This method returns the list of strings used for displaying abbreviated | |
| * month names (e.g., "Jan" and "Feb"). This is a thirteen element | |
| * <code>String</code> array indexed by <code>Calendar.JANUARY</code> | |
| * through <code>Calendar.UNDECEMBER</code>. Note that there are thirteen | |
| * elements because some calendars have thirteen months. | |
| * | |
| * @return The list of abbreviated month display strings. | |
| */ | |
| public String[] getShortMonths () | |
| { | |
| return shortMonths; | |
| } | |
| /** | |
| * This method returns the list of strings used for displaying abbreviated | |
| * weekday names (e.g., "Sun" and "Mon"). This is an eight element | |
| * <code>String</code> array indexed by <code>Calendar.SUNDAY</code> | |
| * through <code>Calendar.SATURDAY</code>. Note that the first element | |
| * of this array is ignored. | |
| * | |
| * @return This list of abbreviated weekday display strings. | |
| */ | |
| public String[] getShortWeekdays () | |
| { | |
| return shortWeekdays; | |
| } | |
| /** | |
| * This method returns the list of strings used for displaying weekday | |
| * names (e.g., "Sunday" and "Monday"). This is an eight element | |
| * <code>String</code> array indexed by <code>Calendar.SUNDAY</code> | |
| * through <code>Calendar.SATURDAY</code>. Note that the first element | |
| * of this array is ignored. | |
| * | |
| * @return This list of weekday display strings. | |
| */ | |
| public String[] getWeekdays () | |
| { | |
| return weekdays; | |
| } | |
| /** | |
| * This method returns this list of localized timezone display strings. | |
| * This is a two dimensional <code>String</code> array where each row in | |
| * the array contains five values: | |
| * <P> | |
| * <ul> | |
| * <li>0 - The non-localized time zone id string.</li> | |
| * <li>1 - The long name of the time zone (standard time).</li> | |
| * <li>2 - The short name of the time zone (standard time).</li> | |
| * <li>3 - The long name of the time zone (daylight savings time).</li> | |
| * <li>4 - the short name of the time zone (daylight savings time).</li> | |
| * </ul> | |
| * <p> | |
| * If {@link #setZoneStrings(String[][])} has been called, then the value | |
| * passed to this will be returned. Otherwise the returned array contains | |
| * zone names provided by the runtime environment and any | |
| * {@link java.util.spi.TimeZoneProvider} instances. | |
| * </p> | |
| * | |
| * @return The list of time zone display strings. | |
| * @see #setZoneStrings(String[][]) | |
| */ | |
| public String[][] getZoneStrings() | |
| { | |
| if (zoneStrings != null) | |
| return zoneStrings; | |
| return runtimeZoneStrings; | |
| } | |
| /** | |
| * This method sets the list of strings used to display AM/PM values to | |
| * the specified list. | |
| * This is a two element <code>String</code> array indexed by | |
| * <code>Calendar.AM</code> and <code>Calendar.PM</code> | |
| * | |
| * @param value The new list of AM/PM display strings. | |
| */ | |
| public void setAmPmStrings (String[] value) | |
| { | |
| if(value==null) | |
| throw new NullPointerException(); | |
| ampms = value; | |
| } | |
| /** | |
| * This method sets the list of strings used to display time eras to | |
| * to the specified list. | |
| * This is a two element <code>String</code> | |
| * array indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>. | |
| * | |
| * @param labels The new list of era display strings. | |
| */ | |
| public void setEras (String[] labels) | |
| { | |
| if(labels==null) | |
| throw new NullPointerException(); | |
| eras = labels; | |
| } | |
| /** | |
| * This method sets the list of characters used to specific date/time | |
| * formatting strings. | |
| * This is an 18 character string that contains the characters | |
| * that are used in creating the date formatting strings in | |
| * <code>SimpleDateFormat</code>. The following are the character | |
| * positions in the string and which format character they correspond | |
| * to (the character in parentheses is the default value in the US English | |
| * locale): | |
| * <p> | |
| * <ul> | |
| * <li>0 - era (G)</li> | |
| * <li>1 - year (y)</li> | |
| * <li>2 - month (M)</li> | |
| * <li>3 - day of month (d)</li> | |
| * <li>4 - hour out of 12, from 1-12 (h)</li> | |
| * <li>5 - hour out of 24, from 0-23 (H)</li> | |
| * <li>6 - minute (m)</li> | |
| * <li>7 - second (s)</li> | |
| * <li>8 - millisecond (S)</li> | |
| * <li>9 - date of week (E)</li> | |
| * <li>10 - date of year (D)</li> | |
| * <li>11 - day of week in month, eg. "4th Thur in Nov" (F)</li> | |
| * <li>12 - week in year (w)</li> | |
| * <li>13 - week in month (W)</li> | |
| * <li>14 - am/pm (a)</li> | |
| * <li>15 - hour out of 24, from 1-24 (k)</li> | |
| * <li>16 - hour out of 12, from 0-11 (K)</li> | |
| * <li>17 - time zone (z)</li> | |
| * </ul> | |
| * | |
| * @param chars The new format pattern characters | |
| */ | |
| public void setLocalPatternChars (String chars) | |
| { | |
| if(chars==null) | |
| throw new NullPointerException(); | |
| localPatternChars = chars; | |
| } | |
| /** | |
| * This method sets the list of strings used to display month names. | |
| * This is a thirteen element | |
| * string array indexed by <code>Calendar.JANUARY</code> through | |
| * <code>Calendar.UNDECEMBER</code>. Note that there are thirteen | |
| * elements because some calendars have thriteen months. | |
| * | |
| * @param labels The list of month display strings. | |
| */ | |
| public void setMonths (String[] labels) | |
| { | |
| if(labels==null) | |
| throw new NullPointerException(); | |
| months = labels; | |
| } | |
| /** | |
| * This method sets the list of strings used to display abbreviated month | |
| * names. | |
| * This is a thirteen element | |
| * <code>String</code> array indexed by <code>Calendar.JANUARY</code> | |
| * through <code>Calendar.UNDECEMBER</code>. Note that there are thirteen | |
| * elements because some calendars have thirteen months. | |
| * | |
| * @param labels The new list of abbreviated month display strings. | |
| */ | |
| public void setShortMonths (String[] labels) | |
| { | |
| if(labels==null) | |
| throw new NullPointerException(); | |
| shortMonths = labels; | |
| } | |
| /** | |
| * This method sets the list of strings used to display abbreviated | |
| * weekday names. | |
| * This is an eight element | |
| * <code>String</code> array indexed by <code>Calendar.SUNDAY</code> | |
| * through <code>Calendar.SATURDAY</code>. Note that the first element | |
| * of this array is ignored. | |
| * | |
| * @param labels This list of abbreviated weekday display strings. | |
| */ | |
| public void setShortWeekdays (String[] labels) | |
| { | |
| if(labels==null) | |
| throw new NullPointerException(); | |
| shortWeekdays = labels; | |
| } | |
| /** | |
| * This method sets the list of strings used to display weekday names. | |
| * This is an eight element | |
| * <code>String</code> array indexed by <code>Calendar.SUNDAY</code> | |
| * through <code>Calendar.SATURDAY</code>. Note that the first element | |
| * of this array is ignored. | |
| * | |
| * @param labels This list of weekday display strings. | |
| */ | |
| public void setWeekdays (String[] labels) | |
| { | |
| if(labels==null) | |
| throw new NullPointerException(); | |
| weekdays = labels; | |
| } | |
| /** | |
| * This method sets the list of display strings for time zones. | |
| * This is a two dimensional <code>String</code> array where each row in | |
| * the array contains five values: | |
| * <P> | |
| * <ul> | |
| * <li>0 - The non-localized time zone id string.</li> | |
| * <li>1 - The long name of the time zone (standard time).</li> | |
| * <li>2 - The short name of the time zone (standard time).</li> | |
| * <li>3 - The long name of the time zone (daylight savings time).</li> | |
| * <li>4 - the short name of the time zone (daylight savings time).</li> | |
| * </ul> | |
| * | |
| * @params zones The list of time zone display strings. | |
| */ | |
| public void setZoneStrings (String[][] zones) | |
| { | |
| if(zones==null) | |
| throw new NullPointerException(); | |
| zoneStrings = zones; | |
| } | |
| /* Does a "deep" equality test - recurses into arrays. */ | |
| private static boolean equals (Object x, Object y) | |
| { | |
| if (x == y) | |
| return true; | |
| if (x == null || y == null) | |
| return false; | |
| if (! (x instanceof Object[]) || ! (y instanceof Object[])) | |
| return x.equals(y); | |
| Object[] xa = (Object[]) x; | |
| Object[] ya = (Object[]) y; | |
| if (xa.length != ya.length) | |
| return false; | |
| for (int i = xa.length; --i >= 0; ) | |
| { | |
| if (! equals(xa[i], ya[i])) | |
| return false; | |
| } | |
| return true; | |
| } | |
| private static int hashCode (Object x) | |
| { | |
| if (x == null) | |
| return 0; | |
| if (! (x instanceof Object[])) | |
| return x.hashCode(); | |
| Object[] xa = (Object[]) x; | |
| int hash = 0; | |
| for (int i = 0; i < xa.length; i++) | |
| hash = 37 * hashCode(xa[i]); | |
| return hash; | |
| } | |
| /** | |
| * This method tests a specified object for equality against this object. | |
| * This will be true if and only if the specified object: | |
| * <p> | |
| * <ul> | |
| * <li> Is not <code>null</code>.</li> | |
| * <li> Is an instance of <code>DateFormatSymbols</code>.</li> | |
| * <li> Contains identical formatting symbols to this object.</li> | |
| * </ul> | |
| * | |
| * @param obj The <code>Object</code> to test for equality against. | |
| * | |
| * @return <code>true</code> if the specified object is equal to this one, | |
| * <code>false</code> otherwise. | |
| */ | |
| public boolean equals (Object obj) | |
| { | |
| if (! (obj instanceof DateFormatSymbols)) | |
| return false; | |
| DateFormatSymbols other = (DateFormatSymbols) obj; | |
| return (equals(ampms, other.ampms) | |
| && equals(eras, other.eras) | |
| && equals(localPatternChars, other.localPatternChars) | |
| && equals(months, other.months) | |
| && equals(shortMonths, other.shortMonths) | |
| && equals(shortWeekdays, other.shortWeekdays) | |
| && equals(weekdays, other.weekdays) | |
| && equals(zoneStrings, other.zoneStrings)); | |
| } | |
| /** | |
| * Returns a new copy of this object. | |
| * | |
| * @return A copy of this object | |
| */ | |
| public Object clone () | |
| { | |
| try | |
| { | |
| return super.clone (); | |
| } | |
| catch (CloneNotSupportedException e) | |
| { | |
| return null; | |
| } | |
| } | |
| /** | |
| * This method returns a hash value for this object. | |
| * | |
| * @return A hash value for this object. | |
| */ | |
| public int hashCode () | |
| { | |
| return (hashCode(ampms) | |
| ^ hashCode(eras) | |
| ^ hashCode(localPatternChars) | |
| ^ hashCode(months) | |
| ^ hashCode(shortMonths) | |
| ^ hashCode(shortWeekdays) | |
| ^ hashCode(weekdays) | |
| ^ hashCode(zoneStrings)); | |
| } | |
| /** | |
| * Returns a {@link DateFormatSymbols} instance for the | |
| * default locale obtained from either the runtime itself | |
| * or one of the installed | |
| * {@link java.text.spi.DateFormatSymbolsProvider} instances. | |
| * This is equivalent to calling | |
| * <code>getInstance(Locale.getDefault())</code>. | |
| * | |
| * @return a {@link DateFormatSymbols} instance for the default | |
| * locale. | |
| * @since 1.6 | |
| */ | |
| public static final DateFormatSymbols getInstance() | |
| { | |
| return getInstance(Locale.getDefault()); | |
| } | |
| /** | |
| * Returns a {@link DateFormatSymbols} instance for the | |
| * specified locale obtained from either the runtime itself | |
| * or one of the installed | |
| * {@link java.text.spi.DateFormatSymbolsProvider} instances. | |
| * | |
| * @param locale the locale for which an instance should be | |
| * returned. | |
| * @return a {@link DateFormatSymbols} instance for the specified | |
| * locale. | |
| * @throws NullPointerException if <code>locale</code> is | |
| * <code>null</code>. | |
| * @since 1.6 | |
| */ | |
| public static final DateFormatSymbols getInstance(Locale locale) | |
| { | |
| try | |
| { | |
| DateFormatSymbols syms = new DateFormatSymbols(locale); | |
| return syms; | |
| } | |
| catch (MissingResourceException e) | |
| { | |
| /* This means runtime support for the locale | |
| * is not available, so we check providers. */ | |
| } | |
| for (DateFormatSymbolsProvider p : | |
| ServiceLoader.load(DateFormatSymbolsProvider.class)) | |
| { | |
| for (Locale loc : p.getAvailableLocales()) | |
| { | |
| if (loc.equals(locale)) | |
| { | |
| DateFormatSymbols syms = p.getInstance(locale); | |
| if (syms != null) | |
| return syms; | |
| break; | |
| } | |
| } | |
| } | |
| return getInstance(LocaleHelper.getFallbackLocale(locale)); | |
| } | |
| } |