DateFormatSymbols.java revision f6c387128427e121477c1b32ad35cdcaa5101ba3
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17/** 18******************************************************************************* 19* Copyright (C) 1996-2007, International Business Machines Corporation and * 20* others. All Rights Reserved. * 21******************************************************************************* 22*/ 23 24// BEGIN android-note 25// The class javadoc and some of the method descriptions are copied from ICU4J 26// source files. Changes have been made to the copied descriptions. 27// The icu license header was added to this file. 28// END android-note 29 30package java.text; 31 32import java.io.Serializable; 33// BEGIN android-added 34import java.io.IOException; 35import java.io.ObjectOutputStream; 36// END android-added 37import java.util.Arrays; 38import java.util.Locale; 39import java.util.ResourceBundle; 40 41// BEGIN android-added 42import com.ibm.icu4jni.util.Resources; 43// END android-added 44/** 45 * Encapsulates localizable date-time formatting data, such as the names of the 46 * months, the names of the days of the week, and the time zone data. 47 * {@code DateFormat} and {@code SimpleDateFormat} both use 48 * {@code DateFormatSymbols} to encapsulate this information. 49 * <p> 50 * Typically you shouldn't use {@code DateFormatSymbols} directly. Rather, you 51 * are encouraged to create a date/time formatter with the {@code DateFormat} 52 * class's factory methods: {@code getTimeInstance}, {@code getDateInstance}, 53 * or {@code getDateTimeInstance}. These methods automatically create a 54 * {@code DateFormatSymbols} for the formatter so that you don't have to. After 55 * the formatter is created, you may modify its format pattern using the 56 * {@code setPattern} method. For more information about creating formatters 57 * using {@code DateFormat}'s factory methods, see {@link DateFormat}. 58 * </p> 59 * <p> 60 * If you decide to create a date/time formatter with a specific format pattern 61 * for a specific locale, you can do so with: 62 * </p> 63 * <blockquote> 64 * 65 * <pre> 66 * new SimpleDateFormat(aPattern, new DateFormatSymbols(aLocale)). 67 * </pre> 68 * 69 * </blockquote> 70 * <p> 71 * {@code DateFormatSymbols} objects can be cloned. When you obtain a 72 * {@code DateFormatSymbols} object, feel free to modify the date/time 73 * formatting data. For instance, you can replace the localized date/time format 74 * pattern characters with the ones that you feel easy to remember or you can 75 * change the representative cities to your favorite ones. 76 * </p> 77 * <p> 78 * New {@code DateFormatSymbols} subclasses may be added to support 79 * {@code SimpleDateFormat} for date/time formatting for additional locales. 80 * </p> 81 * 82 * @see DateFormat 83 * @see SimpleDateFormat 84 * @since Android 1.0 85 */ 86public class DateFormatSymbols implements Serializable, Cloneable { 87 88 private static final long serialVersionUID = -5987973545549424702L; 89 90 private String localPatternChars; 91 92 String[] ampms, eras, months, shortMonths, shortWeekdays, weekdays; 93 94 String[][] zoneStrings; 95 96// BEGIN android-added 97 /** 98 * Locale, necessary to lazily load time zone strings. We force the time 99 * zone names to load upon serialization, so this will never be needed 100 * post deserialization. 101 */ 102 transient final Locale locale; 103 104 /** 105 * Gets zone strings, initializing them if necessary. Does not create 106 * a defensive copy, so make sure you do so before exposing the returned 107 * arrays to clients. 108 */ 109 synchronized String[][] internalZoneStrings() { 110 if (zoneStrings == null) { 111 zoneStrings = Resources.getDisplayTimeZones(locale.toString()); 112 } 113 return zoneStrings; 114 } 115// END android-added 116 117 /** 118 * Constructs a new {@code DateFormatSymbols} instance containing the 119 * symbols for the default locale. 120 * 121 * @since Android 1.0 122 */ 123 public DateFormatSymbols() { 124 this(Locale.getDefault()); 125 } 126 127 /** 128 * Constructs a new {@code DateFormatSymbols} instance containing the 129 * symbols for the specified locale. 130 * 131 * @param locale 132 * the locale. 133 * @since Android 1.0 134 */ 135 public DateFormatSymbols(Locale locale) { 136 ResourceBundle bundle = Format.getBundle(locale); 137 localPatternChars = bundle.getString("LocalPatternChars"); //$NON-NLS-1$ 138 ampms = bundle.getStringArray("ampm"); //$NON-NLS-1$ 139 eras = bundle.getStringArray("eras"); //$NON-NLS-1$ 140 months = bundle.getStringArray("months"); //$NON-NLS-1$ 141 shortMonths = bundle.getStringArray("shortMonths"); //$NON-NLS-1$ 142 shortWeekdays = bundle.getStringArray("shortWeekdays"); //$NON-NLS-1$ 143 weekdays = bundle.getStringArray("weekdays"); //$NON-NLS-1$ 144 // BEGIN android-changed 145 // zoneStrings = (String[][]) bundle.getObject("timezones"); //$NON-NLS-1$ 146 this.locale = locale; 147 // END android-changed 148 } 149 150 @Override 151 public Object clone() { 152 // BEGIN android-changed 153 try { 154 return super.clone(); 155 } catch (CloneNotSupportedException e) { 156 throw new AssertionError(); 157 } 158 // END android-changed 159 } 160 161 /** 162 * Compares this object with the specified object and indicates if they are 163 * equal. 164 * 165 * @param object 166 * the object to compare with this object. 167 * @return {@code true} if {@code object} is an instance of 168 * {@code DateFormatSymbols} and has the same symbols as this 169 * object, {@code false} otherwise. 170 * @see #hashCode 171 * @since Android 1.0 172 */ 173 @Override 174 public boolean equals(Object object) { 175 if (this == object) { 176 return true; 177 } 178 if (!(object instanceof DateFormatSymbols)) { 179 return false; 180 } 181 DateFormatSymbols obj = (DateFormatSymbols) object; 182 if (!localPatternChars.equals(obj.localPatternChars)) { 183 return false; 184 } 185 if (!Arrays.equals(ampms, obj.ampms)) { 186 return false; 187 } 188 if (!Arrays.equals(eras, obj.eras)) { 189 return false; 190 } 191 if (!Arrays.equals(months, obj.months)) { 192 return false; 193 } 194 if (!Arrays.equals(shortMonths, obj.shortMonths)) { 195 return false; 196 } 197 if (!Arrays.equals(shortWeekdays, obj.shortWeekdays)) { 198 return false; 199 } 200 if (!Arrays.equals(weekdays, obj.weekdays)) { 201 return false; 202 } 203 // BEGIN android-changed 204 // Quick check that may keep us from having to load the zone strings. 205 if (zoneStrings == null && obj.zoneStrings == null 206 && !locale.equals(obj.locale)) { 207 return false; 208 } 209 // Make sure zone strings are loaded. 210 internalZoneStrings(); 211 obj.internalZoneStrings(); 212 // END android-changed 213 if (zoneStrings.length != obj.zoneStrings.length) { 214 return false; 215 } 216 for (String[] element : zoneStrings) { 217 if (element.length != element.length) { 218 return false; 219 } 220 for (int j = 0; j < element.length; j++) { 221 if (element[j] != element[j] 222 && !(element[j].equals(element[j]))) { 223 return false; 224 } 225 } 226 } 227 return true; 228 } 229 230 /** 231 * Returns the array of strings which represent AM and PM. Use the 232 * {@link java.util.Calendar} constants {@code Calendar.AM} and 233 * {@code Calendar.PM} as indices for the array. 234 * 235 * @return an array of strings. 236 * @since Android 1.0 237 */ 238 public String[] getAmPmStrings() { 239 return ampms.clone(); 240 } 241 242 /** 243 * Returns the array of strings which represent BC and AD. Use the 244 * {@link java.util.Calendar} constants {@code GregorianCalendar.BC} and 245 * {@code GregorianCalendar.AD} as indices for the array. 246 * 247 * @return an array of strings. 248 * @since Android 1.0 249 */ 250 public String[] getEras() { 251 return eras.clone(); 252 } 253 254 /** 255 * Returns the pattern characters used by {@link SimpleDateFormat} to 256 * specify date and time fields. 257 * 258 * @return a string containing the pattern characters. 259 * @since Android 1.0 260 */ 261 public String getLocalPatternChars() { 262 return localPatternChars; 263 } 264 265 /** 266 * Returns the array of strings containing the full names of the months. Use 267 * the {@link java.util.Calendar} constants {@code Calendar.JANUARY} etc. as 268 * indices for the array. 269 * 270 * @return an array of strings. 271 * @since Android 1.0 272 */ 273 public String[] getMonths() { 274 return months.clone(); 275 } 276 277 /** 278 * Returns the array of strings containing the abbreviated names of the 279 * months. Use the {@link java.util.Calendar} constants 280 * {@code Calendar.JANUARY} etc. as indices for the array. 281 * 282 * @return an array of strings. 283 * @since Android 1.0 284 */ 285 public String[] getShortMonths() { 286 return shortMonths.clone(); 287 } 288 289 /** 290 * Returns the array of strings containing the abbreviated names of the days 291 * of the week. Use the {@link java.util.Calendar} constants 292 * {@code Calendar.SUNDAY} etc. as indices for the array. 293 * 294 * @return an array of strings. 295 * @since Android 1.0 296 */ 297 public String[] getShortWeekdays() { 298 return shortWeekdays.clone(); 299 } 300 301 /** 302 * Returns the array of strings containing the full names of the days of the 303 * week. Use the {@link java.util.Calendar} constants 304 * {@code Calendar.SUNDAY} etc. as indices for the array. 305 * 306 * @return an array of strings. 307 * @since Android 1.0 308 */ 309 public String[] getWeekdays() { 310 return weekdays.clone(); 311 } 312 313 /** 314 * Returns the two-dimensional array of strings containing the names of the 315 * time zones. Each element in the array is an array of five strings, the 316 * first is a TimeZone ID, the second and third are the full and abbreviated 317 * time zone names for standard time, and the fourth and fifth are the full 318 * and abbreviated names for daylight time. 319 * 320 * @return a two-dimensional array of strings. 321 * @since Android 1.0 322 */ 323 public String[][] getZoneStrings() { 324 // BEGIN android-added 325 String[][] zoneStrings = internalZoneStrings(); 326 // END android-added 327 String[][] clone = new String[zoneStrings.length][]; 328 for (int i = zoneStrings.length; --i >= 0;) { 329 clone[i] = zoneStrings[i].clone(); 330 } 331 return clone; 332 } 333 334 @Override 335 public int hashCode() { 336 int hashCode; 337 hashCode = localPatternChars.hashCode(); 338 for (String element : ampms) { 339 hashCode += element.hashCode(); 340 } 341 for (String element : eras) { 342 hashCode += element.hashCode(); 343 } 344 for (String element : months) { 345 hashCode += element.hashCode(); 346 } 347 for (String element : shortMonths) { 348 hashCode += element.hashCode(); 349 } 350 for (String element : shortWeekdays) { 351 hashCode += element.hashCode(); 352 } 353 for (String element : weekdays) { 354 hashCode += element.hashCode(); 355 } 356 // BEGIN android-added 357 String[][] zoneStrings = internalZoneStrings(); 358 // END android-added 359 for (String[] element : zoneStrings) { 360 for (int j = 0; j < element.length; j++) { 361 hashCode += element[j].hashCode(); 362 } 363 } 364 return hashCode; 365 } 366 367 /** 368 * Sets the array of strings which represent AM and PM. Use the 369 * {@link java.util.Calendar} constants {@code Calendar.AM} and 370 * {@code Calendar.PM} as indices for the array. 371 * 372 * @param data 373 * the array of strings for AM and PM. 374 * @since Android 1.0 375 */ 376 public void setAmPmStrings(String[] data) { 377 ampms = data.clone(); 378 } 379 380 /** 381 * Sets the array of Strings which represent BC and AD. Use the 382 * {@link java.util.Calendar} constants {@code GregorianCalendar.BC} and 383 * {@code GregorianCalendar.AD} as indices for the array. 384 * 385 * @param data 386 * the array of strings for BC and AD. 387 * @since Android 1.0 388 */ 389 public void setEras(String[] data) { 390 eras = data.clone(); 391 } 392 393 /** 394 * Sets the pattern characters used by {@link SimpleDateFormat} to specify 395 * date and time fields. 396 * 397 * @param data 398 * the string containing the pattern characters. 399 * @since Android 1.0 400 */ 401 public void setLocalPatternChars(String data) { 402 if (data == null) { 403 throw new NullPointerException(); 404 } 405 localPatternChars = data; 406 } 407 408 /** 409 * Sets the array of strings containing the full names of the months. Use 410 * the {@link java.util.Calendar} constants {@code Calendar.JANUARY} etc. as 411 * indices for the array. 412 * 413 * @param data 414 * the array of strings. 415 * @since Android 1.0 416 */ 417 public void setMonths(String[] data) { 418 months = data.clone(); 419 } 420 421 /** 422 * Sets the array of strings containing the abbreviated names of the months. 423 * Use the {@link java.util.Calendar} constants {@code Calendar.JANUARY} 424 * etc. as indices for the array. 425 * 426 * @param data 427 * the array of strings. 428 * @since Android 1.0 429 */ 430 public void setShortMonths(String[] data) { 431 shortMonths = data.clone(); 432 } 433 434 /** 435 * Sets the array of strings containing the abbreviated names of the days of 436 * the week. Use the {@link java.util.Calendar} constants 437 * {@code Calendar.SUNDAY} etc. as indices for the array. 438 * 439 * @param data 440 * the array of strings. 441 * @since Android 1.0 442 */ 443 public void setShortWeekdays(String[] data) { 444 shortWeekdays = data.clone(); 445 } 446 447 /** 448 * Sets the array of strings containing the full names of the days of the 449 * week. Use the {@link java.util.Calendar} constants 450 * {@code Calendar.SUNDAY} etc. as indices for the array. 451 * 452 * @param data 453 * the array of strings. 454 * @since Android 1.0 455 */ 456 public void setWeekdays(String[] data) { 457 weekdays = data.clone(); 458 } 459 460 /** 461 * Sets the two-dimensional array of strings containing the names of the 462 * time zones. Each element in the array is an array of five strings, the 463 * first is a TimeZone ID, and second and third are the full and abbreviated 464 * time zone names for standard time, and the fourth and fifth are the full 465 * and abbreviated names for daylight time. 466 * 467 * @param data 468 * the two-dimensional array of strings. 469 * @since Android 1.0 470 */ 471 public void setZoneStrings(String[][] data) { 472 zoneStrings = data.clone(); 473 } 474 475 // BEGIN android-added 476 private void writeObject(ObjectOutputStream out) 477 throws IOException { 478 // Ensure internal zone strings are initialized to ensure backward 479 // compatibility. 480 internalZoneStrings(); 481 482 out.defaultWriteObject(); 483 } 484 // END android-added 485} 486