1/* GENERATED SOURCE. DO NOT MODIFY. */ 2// © 2016 and later: Unicode, Inc. and others. 3// License & terms of use: http://www.unicode.org/copyright.html#License 4/* 5 ******************************************************************************* 6 * Copyright (C) 1996-2016, International Business Machines Corporation and 7 * others. All Rights Reserved. 8 ******************************************************************************* 9 */ 10 11package android.icu.text; 12 13import java.io.IOException; 14import java.io.ObjectInputStream; 15import java.io.Serializable; 16import java.util.ArrayList; 17import java.util.HashMap; 18import java.util.HashSet; 19import java.util.List; 20import java.util.Locale; 21import java.util.Map; 22import java.util.MissingResourceException; 23import java.util.ResourceBundle; 24import java.util.Set; 25import java.util.TreeMap; 26 27import android.icu.impl.CacheBase; 28import android.icu.impl.CalendarUtil; 29import android.icu.impl.ICUData; 30import android.icu.impl.ICUResourceBundle; 31import android.icu.impl.SoftCache; 32import android.icu.impl.UResource; 33import android.icu.impl.Utility; 34import android.icu.text.TimeZoneNames.NameType; 35import android.icu.util.Calendar; 36import android.icu.util.ICUCloneNotSupportedException; 37import android.icu.util.ICUException; 38import android.icu.util.TimeZone; 39import android.icu.util.ULocale; 40import android.icu.util.ULocale.Category; 41import android.icu.util.UResourceBundle; 42import android.icu.util.UResourceBundleIterator; 43 44/** 45 * <strong>[icu enhancement]</strong> ICU's replacement for {@link java.text.DateFormatSymbols}. Methods, fields, and other functionality specific to ICU are labeled '<strong>[icu]</strong>'. 46 * 47 * <p><code>DateFormatSymbols</code> is a public class for encapsulating 48 * localizable date-time formatting data, such as the names of the 49 * months, the names of the days of the week, and the time zone data. 50 * <code>DateFormat</code> and <code>SimpleDateFormat</code> both use 51 * <code>DateFormatSymbols</code> to encapsulate this information. 52 * 53 * <p>Typically you shouldn't use <code>DateFormatSymbols</code> directly. 54 * Rather, you are encouraged to create a date-time formatter with the 55 * <code>DateFormat</code> class's factory methods: <code>getTimeInstance</code>, 56 * <code>getDateInstance</code>, or <code>getDateTimeInstance</code>. 57 * These methods automatically create a <code>DateFormatSymbols</code> for 58 * the formatter so that you don't have to. After the 59 * formatter is created, you may modify its format pattern using the 60 * <code>setPattern</code> method. For more information about 61 * creating formatters using <code>DateFormat</code>'s factory methods, 62 * see {@link DateFormat}. 63 * 64 * <p>If you decide to create a date-time formatter with a specific 65 * format pattern for a specific locale, you can do so with: 66 * <blockquote> 67 * <pre> 68 * new SimpleDateFormat(aPattern, new DateFormatSymbols(aLocale)). 69 * </pre> 70 * </blockquote> 71 * 72 * <p><code>DateFormatSymbols</code> objects are clonable. When you obtain 73 * a <code>DateFormatSymbols</code> object, feel free to modify the 74 * date-time formatting data. For instance, you can replace the localized 75 * date-time format pattern characters with the ones that you feel easy 76 * to remember. Or you can change the representative cities 77 * to your favorite ones. 78 * 79 * <p>New <code>DateFormatSymbols</code> subclasses may be added to support 80 * <code>SimpleDateFormat</code> for date-time formatting for additional locales. 81 * 82 * @see DateFormat 83 * @see SimpleDateFormat 84 * @see android.icu.util.SimpleTimeZone 85 * @author Chen-Lieh Huang 86 */ 87public class DateFormatSymbols implements Serializable, Cloneable { 88 89 // TODO make sure local pattern char string is 18 characters long, 90 // that is, that it encompasses the new 'u' char for 91 // EXTENDED_YEAR. Two options: 1. Make sure resource data is 92 // correct; 2. Make code add in 'u' at end if len == 17. 93 94 // Constants for context 95 /** 96 * <strong>[icu]</strong> Constant for context. 97 */ 98 public static final int FORMAT = 0; 99 100 /** 101 * <strong>[icu]</strong> Constant for context. 102 */ 103 public static final int STANDALONE = 1; 104 105 /** 106 * <strong>[icu]</strong> Constant for context. NUMERIC context 107 * is only supported for leapMonthPatterns. 108 * @deprecated This API is ICU internal only. 109 * @hide original deprecated declaration 110 * @hide draft / provisional / internal are hidden on Android 111 */ 112 @Deprecated 113 public static final int NUMERIC = 2; 114 115 /** 116 * <strong>[icu]</strong> Constant for context. 117 * @deprecated This API is ICU internal only. 118 * @hide original deprecated declaration 119 * @hide draft / provisional / internal are hidden on Android 120 */ 121 @Deprecated 122 public static final int DT_CONTEXT_COUNT = 3; 123 124 // Constants for width 125 126 /** 127 * <strong>[icu]</strong> Constant for width. 128 */ 129 public static final int ABBREVIATED = 0; 130 131 /** 132 * <strong>[icu]</strong> Constant for width. 133 */ 134 public static final int WIDE = 1; 135 136 /** 137 * <strong>[icu]</strong> Constant for width. 138 */ 139 public static final int NARROW = 2; 140 141 /** 142 * <strong>[icu]</strong> Constant for width; only supported for weekdays. 143 */ 144 public static final int SHORT = 3; 145 146 /** 147 * <strong>[icu]</strong> Constant for width. 148 * @deprecated This API is ICU internal only. 149 * @hide original deprecated declaration 150 * @hide draft / provisional / internal are hidden on Android 151 */ 152 @Deprecated 153 public static final int DT_WIDTH_COUNT = 4; 154 155 /** 156 * <strong>[icu]</strong> Somewhat temporary constant for leap month pattern type, adequate for Chinese calendar. 157 * @hide draft / provisional / internal are hidden on Android 158 */ 159 static final int DT_LEAP_MONTH_PATTERN_FORMAT_WIDE = 0; 160 161 /** 162 * <strong>[icu]</strong> Somewhat temporary constant for leap month pattern type, adequate for Chinese calendar. 163 * @hide draft / provisional / internal are hidden on Android 164 */ 165 static final int DT_LEAP_MONTH_PATTERN_FORMAT_ABBREV = 1; 166 167 /** 168 * <strong>[icu]</strong> Somewhat temporary constant for leap month pattern type, adequate for Chinese calendar. 169 * @hide draft / provisional / internal are hidden on Android 170 */ 171 static final int DT_LEAP_MONTH_PATTERN_FORMAT_NARROW = 2; 172 173 /** 174 * <strong>[icu]</strong> Somewhat temporary constant for leap month pattern type, adequate for Chinese calendar. 175 * @hide draft / provisional / internal are hidden on Android 176 */ 177 static final int DT_LEAP_MONTH_PATTERN_STANDALONE_WIDE = 3; 178 179 /** 180 * <strong>[icu]</strong> Somewhat temporary constant for leap month pattern type, adequate for Chinese calendar. 181 * @hide draft / provisional / internal are hidden on Android 182 */ 183 static final int DT_LEAP_MONTH_PATTERN_STANDALONE_ABBREV = 4; 184 185 /** 186 * <strong>[icu]</strong> Somewhat temporary constant for leap month pattern type, adequate for Chinese calendar. 187 * @hide draft / provisional / internal are hidden on Android 188 */ 189 static final int DT_LEAP_MONTH_PATTERN_STANDALONE_NARROW = 5; 190 191 /** 192 * <strong>[icu]</strong> Somewhat temporary constant for leap month pattern type, adequate for Chinese calendar. 193 * @hide draft / provisional / internal are hidden on Android 194 */ 195 static final int DT_LEAP_MONTH_PATTERN_NUMERIC = 6; 196 197 /** 198 * <strong>[icu]</strong> Somewhat temporary constant for month pattern count, adequate for Chinese calendar. 199 * @hide draft / provisional / internal are hidden on Android 200 */ 201 static final int DT_MONTH_PATTERN_COUNT = 7; 202 203 /** 204 * <strong>[icu]</strong> This default time separator is used for formatting when the locale 205 * doesn't specify any time separator, and always recognized when parsing. 206 * @hide draft / provisional / internal are hidden on Android 207 */ 208 static final String DEFAULT_TIME_SEPARATOR = ":"; 209 210 /** 211 * <strong>[icu]</strong> This alternate time separator is always recognized when parsing. 212 * @hide draft / provisional / internal are hidden on Android 213 */ 214 static final String ALTERNATE_TIME_SEPARATOR = "."; 215 216 /** 217 * Constructs a DateFormatSymbols object by loading format data from 218 * resources for the default <code>FORMAT</code> locale. 219 * 220 * @throws java.util.MissingResourceException if the resources for the default locale 221 * cannot be found or cannot be loaded. 222 * @see Category#FORMAT 223 */ 224 public DateFormatSymbols() 225 { 226 this(ULocale.getDefault(Category.FORMAT)); 227 } 228 229 /** 230 * Constructs a DateFormatSymbols object by loading format data from 231 * resources for the given locale. 232 * 233 * @throws java.util.MissingResourceException if the resources for the specified 234 * locale cannot be found or cannot be loaded. 235 */ 236 public DateFormatSymbols(Locale locale) 237 { 238 this(ULocale.forLocale(locale)); 239 } 240 241 /** 242 * <strong>[icu]</strong> Constructs a DateFormatSymbols object by loading format data from 243 * resources for the given ulocale. 244 * 245 * @throws java.util.MissingResourceException if the resources for the specified 246 * locale cannot be found or cannot be loaded. 247 */ 248 public DateFormatSymbols(ULocale locale) 249 { 250 initializeData(locale, CalendarUtil.getCalendarType(locale)); 251 } 252 253 /** 254 * Returns a DateFormatSymbols instance for the default locale. 255 * 256 * <strong>[icu] Note:</strong> Unlike <code>java.text.DateFormatSymbols#getInstance</code>, 257 * this method simply returns <code>new android.icu.text.DateFormatSymbols()</code>. 258 * ICU does not support <code>DateFormatSymbolsProvider</code> introduced in Java 6 259 * or its equivalent implementation for now. 260 * 261 * @return A DateFormatSymbols instance. 262 */ 263 public static DateFormatSymbols getInstance() { 264 return new DateFormatSymbols(); 265 } 266 267 /** 268 * Returns a DateFormatSymbols instance for the given locale. 269 * 270 * <strong>[icu] Note:</strong> Unlike <code>java.text.DateFormatSymbols#getInstance</code>, 271 * this method simply returns <code>new android.icu.text.DateFormatSymbols(locale)</code>. 272 * ICU does not support <code>DateFormatSymbolsProvider</code> introduced in Java 6 273 * or its equivalent implementation for now. 274 * 275 * @param locale the locale. 276 * @return A DateFormatSymbols instance. 277 */ 278 public static DateFormatSymbols getInstance(Locale locale) { 279 return new DateFormatSymbols(locale); 280 } 281 282 /** 283 * <strong>[icu]</strong> Returns a DateFormatSymbols instance for the given locale. 284 * 285 * <strong>[icu] Note:</strong> Unlike <code>java.text.DateFormatSymbols#getInstance</code>, 286 * this method simply returns <code>new android.icu.text.DateFormatSymbols(locale)</code>. 287 * ICU does not support <code>DateFormatSymbolsProvider</code> introduced in Java 6 288 * or its equivalent implementation for now. 289 * 290 * @param locale the locale. 291 * @return A DateFormatSymbols instance. 292 */ 293 public static DateFormatSymbols getInstance(ULocale locale) { 294 return new DateFormatSymbols(locale); 295 } 296 297 /** 298 * Returns an array of all locales for which the <code>getInstance</code> methods of 299 * this class can return localized instances. 300 * 301 * <strong>[icu] Note:</strong> Unlike <code>java.text.DateFormatSymbols#getAvailableLocales</code>, 302 * this method simply returns the array of <code>Locale</code>s available in this 303 * class. ICU does not support <code>DateFormatSymbolsProvider</code> introduced in 304 * Java 6 or its equivalent implementation for now. 305 * 306 * @return An array of <code>Locale</code>s for which localized 307 * <code>DateFormatSymbols</code> instances are available. 308 */ 309 public static Locale[] getAvailableLocales() { 310 return ICUResourceBundle.getAvailableLocales(); 311 } 312 313 /** 314 * <strong>[icu]</strong> Returns an array of all locales for which the <code>getInstance</code> 315 * methods of this class can return localized instances. 316 * 317 * <strong>[icu] Note:</strong> Unlike <code>java.text.DateFormatSymbols#getAvailableLocales</code>, 318 * this method simply returns the array of <code>ULocale</code>s available in this 319 * class. ICU does not support <code>DateFormatSymbolsProvider</code> introduced in 320 * Java 6 or its equivalent implementation for now. 321 * 322 * @return An array of <code>ULocale</code>s for which localized 323 * <code>DateFormatSymbols</code> instances are available. 324 * @hide draft / provisional / internal are hidden on Android 325 */ 326 public static ULocale[] getAvailableULocales() { 327 return ICUResourceBundle.getAvailableULocales(); 328 } 329 330 /** 331 * Era strings. For example: "AD" and "BC". An array of 2 strings, 332 * indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>. 333 * @serial 334 */ 335 String eras[] = null; 336 337 /** 338 * Era name strings. For example: "Anno Domini" and "Before Christ". An array of 2 strings, 339 * indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>. 340 * @serial 341 */ 342 String eraNames[] = null; 343 344 /** 345 * Narrow era names. For example: "A" and "B". An array of 2 strings, 346 * indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>. 347 * @serial 348 */ 349 String narrowEras[] = null; 350 351 /** 352 * Month strings. For example: "January", "February", etc. An array 353 * of 13 strings (some calendars have 13 months), indexed by 354 * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc. 355 * @serial 356 */ 357 String months[] = null; 358 359 /** 360 * Short month strings. For example: "Jan", "Feb", etc. An array of 361 * 13 strings (some calendars have 13 months), indexed by 362 * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc. 363 364 * @serial 365 */ 366 String shortMonths[] = null; 367 368 /** 369 * Narrow month strings. For example: "J", "F", etc. An array of 370 * 13 strings (some calendars have 13 months), indexed by 371 * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc. 372 373 * @serial 374 */ 375 String narrowMonths[] = null; 376 377 /** 378 * Standalone month strings. For example: "January", "February", etc. An array 379 * of 13 strings (some calendars have 13 months), indexed by 380 * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc. 381 * @serial 382 */ 383 String standaloneMonths[] = null; 384 385 /** 386 * Standalone short month strings. For example: "Jan", "Feb", etc. An array of 387 * 13 strings (some calendars have 13 months), indexed by 388 * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc. 389 390 * @serial 391 */ 392 String standaloneShortMonths[] = null; 393 394 /** 395 * Standalone narrow month strings. For example: "J", "F", etc. An array of 396 * 13 strings (some calendars have 13 months), indexed by 397 * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc. 398 399 * @serial 400 */ 401 String standaloneNarrowMonths[] = null; 402 403 /** 404 * Format wide weekday strings, for example: "Sunday", "Monday", etc. 405 * An array of 8 strings, indexed by <code>Calendar.SUNDAY</code>, 406 * <code>Calendar.MONDAY</code>, etc. 407 * The element <code>weekdays[0]</code> is ignored. 408 * @serial 409 */ 410 String weekdays[] = null; 411 412 /** 413 * CLDR-style format abbreviated (not short) weekday strings, 414 * for example: "Sun", "Mon", etc. 415 * An array of 8 strings, indexed by <code>Calendar.SUNDAY</code>, 416 * <code>Calendar.MONDAY</code>, etc. 417 * The element <code>shortWeekdays[0]</code> is ignored. 418 * @serial 419 */ 420 String shortWeekdays[] = null; 421 422 /** 423 * CLDR-style format short weekday strings, for example: "Su", "Mo", etc. 424 * An array of 8 strings, indexed by <code>Calendar.SUNDAY</code>, 425 * <code>Calendar.MONDAY</code>, etc. 426 * The element <code>shorterWeekdays[0]</code> is ignored. 427 * @serial 428 */ 429 // Note, serialization restore from pre-ICU-51 will leave this null. 430 String shorterWeekdays[] = null; 431 432 /** 433 * CLDR-style format narrow weekday strings, for example: "S", "M", etc. 434 * An array of 8 strings, indexed by <code>Calendar.SUNDAY</code>, 435 * <code>Calendar.MONDAY</code>, etc. 436 * The element <code>narrowWeekdays[0]</code> is ignored. 437 * @serial 438 */ 439 String narrowWeekdays[] = null; 440 441 /** 442 * Standalone wide weekday strings. For example: "Sunday", "Monday", etc. 443 * An array of 8 strings, indexed by <code>Calendar.SUNDAY</code>, 444 * <code>Calendar.MONDAY</code>, etc. 445 * The element <code>standaloneWeekdays[0]</code> is ignored. 446 * @serial 447 */ 448 String standaloneWeekdays[] = null; 449 450 /** 451 * CLDR-style standalone abbreviated (not short) weekday strings, 452 * for example: "Sun", "Mon", etc. 453 * An array of 8 strings, indexed by <code>Calendar.SUNDAY</code>, 454 * <code>Calendar.MONDAY</code>, etc. 455 * The element <code>standaloneShortWeekdays[0]</code> is ignored. 456 * @serial 457 */ 458 String standaloneShortWeekdays[] = null; 459 460 /** 461 * CLDR-style standalone short weekday strings, for example: "Sun", "Mon", etc. 462 * An array of 8 strings, indexed by <code>Calendar.SUNDAY</code>, 463 * <code>Calendar.MONDAY</code>, etc. 464 * The element <code>standaloneShorterWeekdays[0]</code> is ignored. 465 * @serial 466 */ 467 // Note, serialization restore from pre-ICU-51 will leave this null. 468 String standaloneShorterWeekdays[] = null; 469 470 /** 471 * Standalone narrow weekday strings. For example: "S", "M", etc. An array 472 * of 8 strings, indexed by <code>Calendar.SUNDAY</code>, 473 * <code>Calendar.MONDAY</code>, etc. 474 * The element <code>standaloneNarrowWeekdays[0]</code> is ignored. 475 * @serial 476 */ 477 String standaloneNarrowWeekdays[] = null; 478 479 /** 480 * AM and PM strings. For example: "AM" and "PM". An array of 481 * 2 strings, indexed by <code>Calendar.AM</code> and 482 * <code>Calendar.PM</code>. 483 * @serial 484 */ 485 String ampms[] = null; 486 487 /** 488 * narrow AM and PM strings. For example: "a" and "p". An array of 489 * 2 strings, indexed by <code>Calendar.AM</code> and 490 * <code>Calendar.PM</code>. 491 * @serial 492 */ 493 String ampmsNarrow[] = null; 494 495 /** 496 * Time separator string. For example: ":". 497 * @serial 498 */ 499 private String timeSeparator = null; 500 501 /** 502 * Abbreviated quarter names. For example: "Q1", "Q2", "Q3", "Q4". An array 503 * of 4 strings indexed by the month divided by 3. 504 * @serial 505 */ 506 String shortQuarters[] = null; 507 508 /** 509 * Full quarter names. For example: "1st Quarter", "2nd Quarter", "3rd Quarter", 510 * "4th Quarter". An array of 4 strings, indexed by the month divided by 3. 511 * @serial 512 */ 513 String quarters[] = null; 514 515 /** 516 * Standalone abbreviated quarter names. For example: "Q1", "Q2", "Q3", "Q4". An array 517 * of 4 strings indexed by the month divided by 3. 518 * @serial 519 */ 520 String standaloneShortQuarters[] = null; 521 522 /** 523 * Standalone full quarter names. For example: "1st Quarter", "2nd Quarter", "3rd Quarter", 524 * "4th Quarter". An array of 4 strings, indexed by the month divided by 3. 525 * @serial 526 */ 527 String standaloneQuarters[] = null; 528 529 /** 530 * All leap month patterns, for example "{0}bis". 531 * An array of DT_MONTH_PATTERN_COUNT strings, indexed by the DT_LEAP_MONTH_PATTERN_XXX value. 532 * @serial 533 */ 534 String leapMonthPatterns[] = null; 535 536 /** 537 * Cyclic year names, for example: "jia-zi", "yi-chou", ... "gui-hai". 538 * An array of (normally) 60 strings, corresponding to cyclic years 1-60 (in Calendar YEAR field). 539 * Currently we only have data for format/abbreviated. 540 * For the others, just get from format/abbreviated, ignore set. 541 * @serial 542 */ 543 String shortYearNames[] = null; 544 545 /** 546 * Cyclic zodiac names, for example: "Rat", "Ox", "Tiger", etc. 547 * An array of (normally) 12 strings. 548 * Currently we only have data for format/abbreviated. 549 * For the others, just get from format/abbreviated, ignore set. 550 * @serial 551 */ 552 String shortZodiacNames[] = null; 553 554 /** 555 * Localized names of time zones in this locale. This is a 556 * two-dimensional array of strings of size <em>n</em> by <em>m</em>, 557 * where <em>m</em> is at least 5 and up to 7. Each of the <em>n</em> rows is an 558 * entry containing the localized names for a single <code>TimeZone</code>. 559 * Each such row contains (with <code>i</code> ranging from 560 * 0..<em>n</em>-1): 561 * <ul> 562 * <li><code>zoneStrings[i][0]</code> - time zone ID</li> 563 * <li><code>zoneStrings[i][1]</code> - long name of zone in standard 564 * time</li> 565 * <li><code>zoneStrings[i][2]</code> - short name of zone in 566 * standard time</li> 567 * <li><code>zoneStrings[i][3]</code> - long name of zone in daylight 568 * savings time</li> 569 * <li><code>zoneStrings[i][4]</code> - short name of zone in daylight 570 * savings time</li> 571 * <li><code>zoneStrings[i][5]</code> - location name of zone</li> 572 * <li><code>zoneStrings[i][6]</code> - long generic name of zone</li> 573 * <li><code>zoneStrings[i][7]</code> - short generic of zone</li> 574 * </ul> 575 * The zone ID is <em>not</em> localized; it corresponds to the ID 576 * value associated with a system time zone object. All other entries 577 * are localized names. If a zone does not implement daylight savings 578 * time, the daylight savings time names are ignored. 579 * <em>Note:</em>CLDR 1.5 introduced metazone and its historical mappings. 580 * This simple two-dimensional array is no longer sufficient to represent 581 * localized names and its historic changes. Since ICU 3.8.1, localized 582 * zone names extracted from ICU locale data is stored in a ZoneStringFormat 583 * instance. But we still need to support the old way of customizing 584 * localized zone names, so we keep this field for the purpose. 585 * @see android.icu.util.TimeZone 586 * @serial 587 */ 588 private String zoneStrings[][] = null; 589 590 /** 591 * Unlocalized date-time pattern characters. For example: 'y', 'd', etc. 592 * All locales use the same unlocalized pattern characters. 593 */ 594 static final String patternChars = "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB"; 595 596 /** 597 * Localized date-time pattern characters. For example, a locale may 598 * wish to use 'u' rather than 'y' to represent years in its date format 599 * pattern strings. 600 * This string must be exactly 18 characters long, with the index of 601 * the characters described by <code>DateFormat.ERA_FIELD</code>, 602 * <code>DateFormat.YEAR_FIELD</code>, etc. Thus, if the string were 603 * "Xz...", then localized patterns would use 'X' for era and 'z' for year. 604 * @serial 605 */ 606 String localPatternChars = null; 607 608 /** 609 * Localized names for abbreviated (== short) day periods. 610 * An array of strings, in the order of DayPeriod constants. 611 */ 612 String abbreviatedDayPeriods[] = null; 613 614 /** 615 * Localized names for wide day periods. 616 * An array of strings, in the order of DayPeriod constants. 617 */ 618 String wideDayPeriods[] = null; 619 620 /** 621 * Localized names for narrow day periods. 622 * An array of strings, in the order of DayPeriod constants. 623 */ 624 String narrowDayPeriods[] = null; 625 626 /** 627 * Localized names for standalone abbreviated (== short) day periods. 628 * An array of strings, in the order of DayPeriod constants. 629 */ 630 String standaloneAbbreviatedDayPeriods[] = null; 631 632 /** 633 * Localized names for standalone wide day periods. 634 * An array of strings, in the order of DayPeriod constants. 635 */ 636 String standaloneWideDayPeriods[] = null; 637 638 /** 639 * Localized names for standalone narrow day periods. 640 * An array of strings, in the order of DayPeriod constants. 641 */ 642 String standaloneNarrowDayPeriods[] = null; 643 644 /* use serialVersionUID from JDK 1.1.4 for interoperability */ 645 private static final long serialVersionUID = -5987973545549424702L; 646 647 private static final String[][] CALENDAR_CLASSES = { 648 {"GregorianCalendar", "gregorian"}, 649 {"JapaneseCalendar", "japanese"}, 650 {"BuddhistCalendar", "buddhist"}, 651 {"TaiwanCalendar", "roc"}, 652 {"PersianCalendar", "persian"}, 653 {"IslamicCalendar", "islamic"}, 654 {"HebrewCalendar", "hebrew"}, 655 {"ChineseCalendar", "chinese"}, 656 {"IndianCalendar", "indian"}, 657 {"CopticCalendar", "coptic"}, 658 {"EthiopicCalendar", "ethiopic"}, 659 }; 660 661 /** 662 * <strong>[icu]</strong> Constants for capitalization context usage types 663 * related to date formatting. 664 * @hide draft / provisional / internal are hidden on Android 665 */ 666 enum CapitalizationContextUsage { 667 OTHER, 668 MONTH_FORMAT, /* except narrow */ 669 MONTH_STANDALONE, /* except narrow */ 670 MONTH_NARROW, 671 DAY_FORMAT, /* except narrow */ 672 DAY_STANDALONE, /* except narrow */ 673 DAY_NARROW, 674 ERA_WIDE, 675 ERA_ABBREV, 676 ERA_NARROW, 677 ZONE_LONG, 678 ZONE_SHORT, 679 METAZONE_LONG, 680 METAZONE_SHORT 681 } 682 683 /** Map from resource key to CapitalizationContextUsage value 684 */ 685 private static final Map<String, CapitalizationContextUsage> contextUsageTypeMap; 686 static { 687 contextUsageTypeMap=new HashMap<String, CapitalizationContextUsage>(); 688 contextUsageTypeMap.put("month-format-except-narrow", CapitalizationContextUsage.MONTH_FORMAT); 689 contextUsageTypeMap.put("month-standalone-except-narrow", CapitalizationContextUsage.MONTH_STANDALONE); 690 contextUsageTypeMap.put("month-narrow", CapitalizationContextUsage.MONTH_NARROW); 691 contextUsageTypeMap.put("day-format-except-narrow", CapitalizationContextUsage.DAY_FORMAT); 692 contextUsageTypeMap.put("day-standalone-except-narrow", CapitalizationContextUsage.DAY_STANDALONE); 693 contextUsageTypeMap.put("day-narrow", CapitalizationContextUsage.DAY_NARROW); 694 contextUsageTypeMap.put("era-name", CapitalizationContextUsage.ERA_WIDE); 695 contextUsageTypeMap.put("era-abbr", CapitalizationContextUsage.ERA_ABBREV); 696 contextUsageTypeMap.put("era-narrow", CapitalizationContextUsage.ERA_NARROW); 697 contextUsageTypeMap.put("zone-long", CapitalizationContextUsage.ZONE_LONG); 698 contextUsageTypeMap.put("zone-short", CapitalizationContextUsage.ZONE_SHORT); 699 contextUsageTypeMap.put("metazone-long", CapitalizationContextUsage.METAZONE_LONG); 700 contextUsageTypeMap.put("metazone-short", CapitalizationContextUsage.METAZONE_SHORT); 701 } 702 703 /** 704 * Capitalization transforms. For each usage type, the first array element indicates 705 * whether to titlecase for uiListOrMenu context, the second indicates whether to 706 * titlecase for stand-alone context. 707 * @serial 708 */ 709 Map<CapitalizationContextUsage,boolean[]> capitalization = null; 710 711 /** 712 * Returns era strings. For example: "AD" and "BC". 713 * @return the era strings. 714 */ 715 public String[] getEras() { 716 return duplicate(eras); 717 } 718 719 /** 720 * Sets era strings. For example: "AD" and "BC". 721 * @param newEras the new era strings. 722 */ 723 public void setEras(String[] newEras) { 724 eras = duplicate(newEras); 725 } 726 727 /** 728 * <strong>[icu]</strong> Returns era name strings. For example: "Anno Domini" and "Before Christ". 729 * @return the era strings. 730 */ 731 public String[] getEraNames() { 732 return duplicate(eraNames); 733 } 734 735 /** 736 * <strong>[icu]</strong> Sets era name strings. For example: "Anno Domini" and "Before Christ". 737 * @param newEraNames the new era strings. 738 */ 739 public void setEraNames(String[] newEraNames) { 740 eraNames = duplicate(newEraNames); 741 } 742 743 // Android patch (http://b/30464240) start: Add getter for narrow eras. 744 /** 745 * <strong>[icu]</strong> Returns narrow era name strings. For example: "A" and "B". 746 * @return the era strings. 747 * @deprecated This API is ICU internal only. 748 * @hide draft / provisional / internal are hidden on Android 749 */ 750 @Deprecated 751 public String[] getNarrowEras() { 752 return duplicate(narrowEras); 753 } 754 // Android patch end. 755 756 /** 757 * Returns month strings. For example: "January", "February", etc. 758 * @return the month strings. 759 */ 760 public String[] getMonths() { 761 return duplicate(months); 762 } 763 764 /** 765 * Returns month strings. For example: "January", "February", etc. 766 * @param context The month context, FORMAT or STANDALONE. 767 * @param width The width or the returned month string, 768 * either WIDE, ABBREVIATED, or NARROW. 769 * @return the month strings. 770 */ 771 public String[] getMonths(int context, int width) { 772 String [] returnValue = null; 773 switch (context) { 774 case FORMAT : 775 switch(width) { 776 case WIDE : 777 returnValue = months; 778 break; 779 case ABBREVIATED : 780 case SHORT : // no month data for this, defaults to ABBREVIATED 781 returnValue = shortMonths; 782 break; 783 case NARROW : 784 returnValue = narrowMonths; 785 break; 786 } 787 break; 788 case STANDALONE : 789 switch(width) { 790 case WIDE : 791 returnValue = standaloneMonths; 792 break; 793 case ABBREVIATED : 794 case SHORT : // no month data for this, defaults to ABBREVIATED 795 returnValue = standaloneShortMonths; 796 break; 797 case NARROW : 798 returnValue = standaloneNarrowMonths; 799 break; 800 } 801 break; 802 } 803 if (returnValue == null) { 804 throw new IllegalArgumentException("Bad context or width argument"); 805 } 806 return duplicate(returnValue); 807 } 808 809 /** 810 * Sets month strings. For example: "January", "February", etc. 811 * @param newMonths the new month strings. 812 */ 813 public void setMonths(String[] newMonths) { 814 months = duplicate(newMonths); 815 } 816 817 /** 818 * Sets month strings. For example: "January", "February", etc. 819 * @param newMonths the new month strings. 820 * @param context The formatting context, FORMAT or STANDALONE. 821 * @param width The width of the month string, 822 * either WIDE, ABBREVIATED, or NARROW. 823 */ 824 public void setMonths(String[] newMonths, int context, int width) { 825 switch (context) { 826 case FORMAT : 827 switch(width) { 828 case WIDE : 829 months = duplicate(newMonths); 830 break; 831 case ABBREVIATED : 832 shortMonths = duplicate(newMonths); 833 break; 834 case NARROW : 835 narrowMonths = duplicate(newMonths); 836 break; 837 default : // HANDLE SHORT, etc. 838 break; 839 } 840 break; 841 case STANDALONE : 842 switch(width) { 843 case WIDE : 844 standaloneMonths = duplicate(newMonths); 845 break; 846 case ABBREVIATED : 847 standaloneShortMonths = duplicate(newMonths); 848 break; 849 case NARROW : 850 standaloneNarrowMonths = duplicate(newMonths); 851 break; 852 default : // HANDLE SHORT, etc. 853 break; 854 } 855 break; 856 } 857 } 858 859 /** 860 * Returns short month strings. For example: "Jan", "Feb", etc. 861 * @return the short month strings. 862 */ 863 public String[] getShortMonths() { 864 return duplicate(shortMonths); 865 } 866 867 /** 868 * Sets short month strings. For example: "Jan", "Feb", etc. 869 * @param newShortMonths the new short month strings. 870 */ 871 public void setShortMonths(String[] newShortMonths) { 872 shortMonths = duplicate(newShortMonths); 873 } 874 875 /** 876 * Returns wide weekday strings. For example: "Sunday", "Monday", etc. 877 * @return the weekday strings. Use <code>Calendar.SUNDAY</code>, 878 * <code>Calendar.MONDAY</code>, etc. to index the result array. 879 */ 880 public String[] getWeekdays() { 881 return duplicate(weekdays); 882 } 883 884 /** 885 * Returns weekday strings. For example: "Sunday", "Monday", etc. 886 * @return the weekday strings. Use <code>Calendar.SUNDAY</code>, 887 * <code>Calendar.MONDAY</code>, etc. to index the result array. 888 * @param context Formatting context, either FORMAT or STANDALONE. 889 * @param width Width of strings to be returned, either 890 * WIDE, ABBREVIATED, SHORT, or NARROW 891 */ 892 public String[] getWeekdays(int context, int width) { 893 String [] returnValue = null; 894 switch (context) { 895 case FORMAT : 896 switch(width) { 897 case WIDE : 898 returnValue = weekdays; 899 break; 900 case ABBREVIATED : 901 returnValue = shortWeekdays; 902 break; 903 case SHORT : 904 returnValue = (shorterWeekdays != null)? shorterWeekdays: shortWeekdays; 905 break; 906 case NARROW : 907 returnValue = narrowWeekdays; 908 break; 909 } 910 break; 911 case STANDALONE : 912 switch(width) { 913 case WIDE : 914 returnValue = standaloneWeekdays; 915 break; 916 case ABBREVIATED : 917 returnValue = standaloneShortWeekdays; 918 break; 919 case SHORT : 920 returnValue = (standaloneShorterWeekdays != null)? standaloneShorterWeekdays: standaloneShortWeekdays; 921 break; 922 case NARROW : 923 returnValue = standaloneNarrowWeekdays; 924 break; 925 } 926 break; 927 } 928 if (returnValue == null) { 929 throw new IllegalArgumentException("Bad context or width argument"); 930 } 931 return duplicate(returnValue); 932 } 933 934 /** 935 * Sets weekday strings. For example: "Sunday", "Monday", etc. 936 * @param newWeekdays The new weekday strings. 937 * @param context The formatting context, FORMAT or STANDALONE. 938 * @param width The width of the strings, 939 * either WIDE, ABBREVIATED, SHORT, or NARROW. 940 */ 941 public void setWeekdays(String[] newWeekdays, int context, int width) { 942 switch (context) { 943 case FORMAT : 944 switch(width) { 945 case WIDE : 946 weekdays = duplicate(newWeekdays); 947 break; 948 case ABBREVIATED : 949 shortWeekdays = duplicate(newWeekdays); 950 break; 951 case SHORT : 952 shorterWeekdays = duplicate(newWeekdays); 953 break; 954 case NARROW : 955 narrowWeekdays = duplicate(newWeekdays); 956 break; 957 } 958 break; 959 case STANDALONE : 960 switch(width) { 961 case WIDE : 962 standaloneWeekdays = duplicate(newWeekdays); 963 break; 964 case ABBREVIATED : 965 standaloneShortWeekdays = duplicate(newWeekdays); 966 break; 967 case SHORT : 968 standaloneShorterWeekdays = duplicate(newWeekdays); 969 break; 970 case NARROW : 971 standaloneNarrowWeekdays = duplicate(newWeekdays); 972 break; 973 } 974 break; 975 } 976 } 977 978 /** 979 * Sets wide weekday strings. For example: "Sunday", "Monday", etc. 980 * @param newWeekdays the new weekday strings. The array should 981 * be indexed by <code>Calendar.SUNDAY</code>, 982 * <code>Calendar.MONDAY</code>, etc. 983 */ 984 public void setWeekdays(String[] newWeekdays) { 985 weekdays = duplicate(newWeekdays); 986 } 987 988 /** 989 * Returns abbreviated weekday strings; for example: "Sun", "Mon", etc. 990 * (Note: the method name is misleading; it does not get the CLDR-style 991 * "short" weekday strings, e.g. "Su", "Mo", etc.) 992 * @return the abbreviated weekday strings. Use <code>Calendar.SUNDAY</code>, 993 * <code>Calendar.MONDAY</code>, etc. to index the result array. 994 */ 995 public String[] getShortWeekdays() { 996 return duplicate(shortWeekdays); 997 } 998 999 /** 1000 * Sets abbreviated weekday strings; for example: "Sun", "Mon", etc. 1001 * (Note: the method name is misleading; it does not set the CLDR-style 1002 * "short" weekday strings, e.g. "Su", "Mo", etc.) 1003 * @param newAbbrevWeekdays the new abbreviated weekday strings. The array should 1004 * be indexed by <code>Calendar.SUNDAY</code>, 1005 * <code>Calendar.MONDAY</code>, etc. 1006 */ 1007 public void setShortWeekdays(String[] newAbbrevWeekdays) { 1008 shortWeekdays = duplicate(newAbbrevWeekdays); 1009 } 1010 /** 1011 * <strong>[icu]</strong> Returns quarter strings. For example: "1st Quarter", "2nd Quarter", etc. 1012 * @param context The quarter context, FORMAT or STANDALONE. 1013 * @param width The width or the returned quarter string, 1014 * either WIDE or ABBREVIATED. There are no NARROW quarters. 1015 * @return the quarter strings. 1016 */ 1017 public String[] getQuarters(int context, int width) { 1018 String [] returnValue = null; 1019 switch (context) { 1020 case FORMAT : 1021 switch(width) { 1022 case WIDE : 1023 returnValue = quarters; 1024 break; 1025 case ABBREVIATED : 1026 case SHORT : // no quarter data for this, defaults to ABBREVIATED 1027 returnValue = shortQuarters; 1028 break; 1029 case NARROW : 1030 returnValue = null; 1031 break; 1032 } 1033 break; 1034 1035 case STANDALONE : 1036 switch(width) { 1037 case WIDE : 1038 returnValue = standaloneQuarters; 1039 break; 1040 case ABBREVIATED : 1041 case SHORT : // no quarter data for this, defaults to ABBREVIATED 1042 returnValue = standaloneShortQuarters; 1043 break; 1044 case NARROW: 1045 returnValue = null; 1046 break; 1047 } 1048 break; 1049 } 1050 if (returnValue == null) { 1051 throw new IllegalArgumentException("Bad context or width argument"); 1052 } 1053 return duplicate(returnValue); 1054 } 1055 1056 /** 1057 * <strong>[icu]</strong> Sets quarter strings. For example: "1st Quarter", "2nd Quarter", etc. 1058 * @param newQuarters the new quarter strings. 1059 * @param context The formatting context, FORMAT or STANDALONE. 1060 * @param width The width of the quarter string, 1061 * either WIDE or ABBREVIATED. There are no NARROW quarters. 1062 */ 1063 public void setQuarters(String[] newQuarters, int context, int width) { 1064 switch (context) { 1065 case FORMAT : 1066 switch(width) { 1067 case WIDE : 1068 quarters = duplicate(newQuarters); 1069 break; 1070 case ABBREVIATED : 1071 shortQuarters = duplicate(newQuarters); 1072 break; 1073 case NARROW : 1074 //narrowQuarters = duplicate(newQuarters); 1075 break; 1076 default : // HANDLE SHORT, etc. 1077 break; 1078 } 1079 break; 1080 case STANDALONE : 1081 switch(width) { 1082 case WIDE : 1083 standaloneQuarters = duplicate(newQuarters); 1084 break; 1085 case ABBREVIATED : 1086 standaloneShortQuarters = duplicate(newQuarters); 1087 break; 1088 case NARROW : 1089 //standaloneNarrowQuarters = duplicate(newQuarters); 1090 break; 1091 default : // HANDLE SHORT, etc. 1092 break; 1093 } 1094 break; 1095 } 1096 } 1097 1098 /** 1099 * Returns cyclic year name strings if the calendar has them, 1100 * for example: "jia-zi", "yi-chou", etc. 1101 * @param context The usage context: FORMAT, STANDALONE. 1102 * @param width The requested name width: WIDE, ABBREVIATED, SHORT, NARROW. 1103 * @return The year name strings, or null if they are not 1104 * available for this calendar. 1105 */ 1106 public String[] getYearNames(int context, int width) { 1107 // context & width ignored for now, one set of names for all uses 1108 if (shortYearNames != null) { 1109 return duplicate(shortYearNames); 1110 } 1111 return null; 1112 } 1113 1114 /** 1115 * Sets cyclic year name strings, for example: "jia-zi", "yi-chou", etc. 1116 * @param yearNames The new cyclic year name strings. 1117 * @param context The usage context: FORMAT, STANDALONE (currently only FORMAT is supported). 1118 * @param width The name width: WIDE, ABBREVIATED, NARROW (currently only ABBREVIATED is supported). 1119 */ 1120 public void setYearNames(String[] yearNames, int context, int width) { 1121 if (context == FORMAT && width == ABBREVIATED) { 1122 shortYearNames = duplicate(yearNames); 1123 } 1124 } 1125 1126 /** 1127 * Returns calendar zodiac name strings if the calendar has them, 1128 * for example: "Rat", "Ox", "Tiger", etc. 1129 * @param context The usage context: FORMAT, STANDALONE. 1130 * @param width The requested name width: WIDE, ABBREVIATED, SHORT, NARROW. 1131 * @return The zodiac name strings, or null if they are not 1132 * available for this calendar. 1133 */ 1134 public String[] getZodiacNames(int context, int width) { 1135 // context & width ignored for now, one set of names for all uses 1136 if (shortZodiacNames != null) { 1137 return duplicate(shortZodiacNames); 1138 } 1139 return null; 1140 } 1141 1142 /** 1143 * Sets calendar zodiac name strings, for example: "Rat", "Ox", "Tiger", etc. 1144 * @param zodiacNames The new zodiac name strings. 1145 * @param context The usage context: FORMAT, STANDALONE (currently only FORMAT is supported). 1146 * @param width The name width: WIDE, ABBREVIATED, NARROW (currently only ABBREVIATED is supported). 1147 */ 1148 public void setZodiacNames(String[] zodiacNames, int context, int width) { 1149 if (context == FORMAT && width == ABBREVIATED) { 1150 shortZodiacNames = duplicate(zodiacNames); 1151 } 1152 } 1153 1154 /** 1155 * Returns the appropriate leapMonthPattern if the calendar has them, 1156 * for example: "{0}bis" 1157 * @param context The usage context: FORMAT, STANDALONE, NUMERIC. 1158 * @param width The requested pattern width: WIDE, ABBREVIATED, SHORT, NARROW. 1159 * @return The leapMonthPattern, or null if not available for 1160 * this calendar. 1161 * @deprecated This API is ICU internal only. 1162 * @hide original deprecated declaration 1163 * @hide draft / provisional / internal are hidden on Android 1164 */ 1165 @Deprecated 1166 public String getLeapMonthPattern(int context, int width) { 1167 if (leapMonthPatterns != null) { 1168 int leapMonthPatternIndex = -1; 1169 switch (context) { 1170 case FORMAT : 1171 switch(width) { 1172 case WIDE : 1173 leapMonthPatternIndex = DT_LEAP_MONTH_PATTERN_FORMAT_WIDE; 1174 break; 1175 case ABBREVIATED : 1176 case SHORT : // no month data for this, defaults to ABBREVIATED 1177 leapMonthPatternIndex = DT_LEAP_MONTH_PATTERN_FORMAT_ABBREV; 1178 break; 1179 case NARROW : 1180 leapMonthPatternIndex = DT_LEAP_MONTH_PATTERN_FORMAT_NARROW; 1181 break; 1182 } 1183 break; 1184 case STANDALONE : 1185 switch(width) { 1186 case WIDE : 1187 leapMonthPatternIndex = DT_LEAP_MONTH_PATTERN_STANDALONE_WIDE; 1188 break; 1189 case ABBREVIATED : 1190 case SHORT : // no month data for this, defaults to ABBREVIATED 1191 leapMonthPatternIndex = DT_LEAP_MONTH_PATTERN_FORMAT_ABBREV; 1192 break; 1193 case NARROW : 1194 leapMonthPatternIndex = DT_LEAP_MONTH_PATTERN_STANDALONE_NARROW; 1195 break; 1196 } 1197 break; 1198 case NUMERIC : 1199 leapMonthPatternIndex = DT_LEAP_MONTH_PATTERN_NUMERIC; 1200 break; 1201 } 1202 if (leapMonthPatternIndex < 0) { 1203 throw new IllegalArgumentException("Bad context or width argument"); 1204 } 1205 return leapMonthPatterns[leapMonthPatternIndex]; 1206 } 1207 return null; 1208 } 1209 1210 /** 1211 * Sets a leapMonthPattern, for example: "{0}bis" 1212 * @param leapMonthPattern The new leapMonthPattern. 1213 * @param context The usage context: FORMAT, STANDALONE, NUMERIC. 1214 * @param width The name width: WIDE, ABBREVIATED, NARROW. 1215 * @deprecated This API is ICU internal only. 1216 * @hide original deprecated declaration 1217 * @hide draft / provisional / internal are hidden on Android 1218 */ 1219 @Deprecated 1220 public void setLeapMonthPattern(String leapMonthPattern, int context, int width) { 1221 if (leapMonthPatterns != null) { 1222 int leapMonthPatternIndex = -1; 1223 switch (context) { 1224 case FORMAT : 1225 switch(width) { 1226 case WIDE : 1227 leapMonthPatternIndex = DT_LEAP_MONTH_PATTERN_FORMAT_WIDE; 1228 break; 1229 case ABBREVIATED : 1230 leapMonthPatternIndex = DT_LEAP_MONTH_PATTERN_FORMAT_ABBREV; 1231 break; 1232 case NARROW : 1233 leapMonthPatternIndex = DT_LEAP_MONTH_PATTERN_FORMAT_NARROW; 1234 break; 1235 default : // HANDLE SHORT, etc. 1236 break; 1237 } 1238 break; 1239 case STANDALONE : 1240 switch(width) { 1241 case WIDE : 1242 leapMonthPatternIndex = DT_LEAP_MONTH_PATTERN_STANDALONE_WIDE; 1243 break; 1244 case ABBREVIATED : 1245 leapMonthPatternIndex = DT_LEAP_MONTH_PATTERN_FORMAT_ABBREV; 1246 break; 1247 case NARROW : 1248 leapMonthPatternIndex = DT_LEAP_MONTH_PATTERN_STANDALONE_NARROW; 1249 break; 1250 default : // HANDLE SHORT, etc. 1251 break; 1252 } 1253 break; 1254 case NUMERIC : 1255 leapMonthPatternIndex = DT_LEAP_MONTH_PATTERN_NUMERIC; 1256 break; 1257 default : 1258 break; 1259 } 1260 if (leapMonthPatternIndex >= 0) { 1261 leapMonthPatterns[leapMonthPatternIndex] = leapMonthPattern; 1262 } 1263 } 1264 } 1265 1266 /** 1267 * Returns am/pm strings. For example: "AM" and "PM". 1268 * @return the weekday strings. 1269 */ 1270 public String[] getAmPmStrings() { 1271 return duplicate(ampms); 1272 } 1273 1274 /** 1275 * Sets am/pm strings. For example: "AM" and "PM". 1276 * @param newAmpms the new ampm strings. 1277 */ 1278 public void setAmPmStrings(String[] newAmpms) { 1279 ampms = duplicate(newAmpms); 1280 } 1281 1282 /** 1283 * Returns the time separator string. For example: ":". 1284 * @return the time separator string. 1285 * @deprecated This API is ICU internal only. 1286 * @hide draft / provisional / internal are hidden on Android 1287 */ 1288 @Deprecated 1289 public String getTimeSeparatorString() { 1290 return timeSeparator; 1291 } 1292 1293 /** 1294 * Sets the time separator string. For example: ":". 1295 * @param newTimeSeparator the new time separator string. 1296 * @deprecated This API is ICU internal only. 1297 * @hide draft / provisional / internal are hidden on Android 1298 */ 1299 @Deprecated 1300 public void setTimeSeparatorString(String newTimeSeparator) { 1301 timeSeparator = newTimeSeparator; 1302 } 1303 1304 /** 1305 * Returns time zone strings. 1306 * <p> 1307 * The array returned by this API is a two dimensional String array and 1308 * each row contains at least following strings: 1309 * <ul> 1310 * <li>ZoneStrings[n][0] - System time zone ID 1311 * <li>ZoneStrings[n][1] - Long standard time display name 1312 * <li>ZoneStrings[n][2] - Short standard time display name 1313 * <li>ZoneStrings[n][3] - Long daylight saving time display name 1314 * <li>ZoneStrings[n][4] - Short daylight saving time display name 1315 * </ul> 1316 * When a localized display name is not available, the corresponding 1317 * array element will be <code>null</code>. 1318 * <p> 1319 * <b>Note</b>: ICU implements the time zone display name formatting algorithm 1320 * specified by <a href="http://www.unicode.org/reports/tr35/">UTS#35 Unicode 1321 * Locale Data Markup Language(LDML)</a>. The algorithm supports historic 1322 * display name changes and various different types of names not available in 1323 * {@link java.text.DateFormatSymbols#getZoneStrings()}. For accessing the full 1324 * set of time zone string data used by ICU implementation, you should use 1325 * {@link TimeZoneNames} APIs instead. 1326 * 1327 * @return the time zone strings. 1328 */ 1329 public String[][] getZoneStrings() { 1330 if (zoneStrings != null) { 1331 return duplicate(zoneStrings); 1332 } 1333 1334 String[] tzIDs = TimeZone.getAvailableIDs(); 1335 TimeZoneNames tznames = TimeZoneNames.getInstance(validLocale); 1336 tznames.loadAllDisplayNames(); 1337 NameType types[] = { 1338 NameType.LONG_STANDARD, NameType.SHORT_STANDARD, 1339 NameType.LONG_DAYLIGHT, NameType.SHORT_DAYLIGHT 1340 }; 1341 long now = System.currentTimeMillis(); 1342 String[][] array = new String[tzIDs.length][5]; 1343 for (int i = 0; i < tzIDs.length; i++) { 1344 String canonicalID = TimeZone.getCanonicalID(tzIDs[i]); 1345 if (canonicalID == null) { 1346 canonicalID = tzIDs[i]; 1347 } 1348 1349 array[i][0] = tzIDs[i]; 1350 tznames.getDisplayNames(canonicalID, types, now, array[i], 1); 1351 } 1352 1353 zoneStrings = array; 1354 return zoneStrings; 1355 } 1356 1357 /** 1358 * Sets time zone strings. 1359 * <p> 1360 * <b>Note</b>: {@link SimpleDateFormat} no longer uses the 1361 * zone strings stored in a <code>DateFormatSymbols</code>. 1362 * Therefore, the time zone strings set by this method have 1363 * no effects in an instance of <code>SimpleDateFormat</code> 1364 * for formatting time zones. If you want to customize time 1365 * zone display names formatted by <code>SimpleDateFormat</code>, 1366 * you should customize {@link TimeZoneFormat} and set the 1367 * instance by {@link SimpleDateFormat#setTimeZoneFormat(TimeZoneFormat)} 1368 * instead. 1369 * 1370 * @param newZoneStrings the new time zone strings. 1371 */ 1372 public void setZoneStrings(String[][] newZoneStrings) { 1373 zoneStrings = duplicate(newZoneStrings); 1374 } 1375 1376 /** 1377 * Returns localized date-time pattern characters. For example: 'u', 't', etc. 1378 * 1379 * <p>Note: ICU no longer provides localized date-time pattern characters for a locale 1380 * starting ICU 3.8. This method returns the non-localized date-time pattern 1381 * characters unless user defined localized data is set by setLocalPatternChars. 1382 * @return the localized date-time pattern characters. 1383 */ 1384 public String getLocalPatternChars() { 1385 return localPatternChars; 1386 } 1387 1388 /** 1389 * Sets localized date-time pattern characters. For example: 'u', 't', etc. 1390 * @param newLocalPatternChars the new localized date-time 1391 * pattern characters. 1392 */ 1393 public void setLocalPatternChars(String newLocalPatternChars) { 1394 localPatternChars = newLocalPatternChars; 1395 } 1396 1397 /** 1398 * Overrides clone. 1399 */ 1400 @Override 1401 public Object clone() 1402 { 1403 try { 1404 DateFormatSymbols other = (DateFormatSymbols)super.clone(); 1405 return other; 1406 } catch (CloneNotSupportedException e) { 1407 ///CLOVER:OFF 1408 throw new ICUCloneNotSupportedException(e); 1409 ///CLOVER:ON 1410 } 1411 } 1412 1413 /** 1414 * Override hashCode. 1415 * Generates a hash code for the DateFormatSymbols object. 1416 */ 1417 @Override 1418 public int hashCode() { 1419 // Is this sufficient? 1420 return requestedLocale.toString().hashCode(); 1421 } 1422 1423 /** 1424 * Overrides equals. 1425 */ 1426 @Override 1427 public boolean equals(Object obj) 1428 { 1429 if (this == obj) return true; 1430 if (obj == null || getClass() != obj.getClass()) return false; 1431 DateFormatSymbols that = (DateFormatSymbols) obj; 1432 return (Utility.arrayEquals(eras, that.eras) 1433 && Utility.arrayEquals(eraNames, that.eraNames) 1434 && Utility.arrayEquals(months, that.months) 1435 && Utility.arrayEquals(shortMonths, that.shortMonths) 1436 && Utility.arrayEquals(narrowMonths, that.narrowMonths) 1437 && Utility.arrayEquals(standaloneMonths, that.standaloneMonths) 1438 && Utility.arrayEquals(standaloneShortMonths, that.standaloneShortMonths) 1439 && Utility.arrayEquals(standaloneNarrowMonths, that.standaloneNarrowMonths) 1440 && Utility.arrayEquals(weekdays, that.weekdays) 1441 && Utility.arrayEquals(shortWeekdays, that.shortWeekdays) 1442 && Utility.arrayEquals(shorterWeekdays, that.shorterWeekdays) 1443 && Utility.arrayEquals(narrowWeekdays, that.narrowWeekdays) 1444 && Utility.arrayEquals(standaloneWeekdays, that.standaloneWeekdays) 1445 && Utility.arrayEquals(standaloneShortWeekdays, that.standaloneShortWeekdays) 1446 && Utility.arrayEquals(standaloneShorterWeekdays, that.standaloneShorterWeekdays) 1447 && Utility.arrayEquals(standaloneNarrowWeekdays, that.standaloneNarrowWeekdays) 1448 && Utility.arrayEquals(ampms, that.ampms) 1449 && Utility.arrayEquals(ampmsNarrow, that.ampmsNarrow) 1450 && Utility.arrayEquals(abbreviatedDayPeriods, that.abbreviatedDayPeriods) 1451 && Utility.arrayEquals(wideDayPeriods, that.wideDayPeriods) 1452 && Utility.arrayEquals(narrowDayPeriods, that.narrowDayPeriods) 1453 && Utility.arrayEquals(standaloneAbbreviatedDayPeriods, that.standaloneAbbreviatedDayPeriods) 1454 && Utility.arrayEquals(standaloneWideDayPeriods, that.standaloneWideDayPeriods) 1455 && Utility.arrayEquals(standaloneNarrowDayPeriods, that.standaloneNarrowDayPeriods) 1456 && Utility.arrayEquals(timeSeparator, that.timeSeparator) 1457 && arrayOfArrayEquals(zoneStrings, that.zoneStrings) 1458 // getDiplayName maps deprecated country and language codes to the current ones 1459 // too bad there is no way to get the current codes! 1460 // I thought canolicalize() would map the codes but .. alas! it doesn't. 1461 && requestedLocale.getDisplayName().equals(that.requestedLocale.getDisplayName()) 1462 && Utility.arrayEquals(localPatternChars, 1463 that.localPatternChars)); 1464 } 1465 1466 // =======================privates=============================== 1467 1468 /** 1469 * Useful constant for defining timezone offsets. 1470 */ 1471 static final int millisPerHour = 60*60*1000; 1472 1473 // DateFormatSymbols cache 1474 private static CacheBase<String, DateFormatSymbols, ULocale> DFSCACHE = 1475 new SoftCache<String, DateFormatSymbols, ULocale>() { 1476 @Override 1477 protected DateFormatSymbols createInstance(String key, ULocale locale) { 1478 // Extract the type string from the key. 1479 // Otherwise we would have to create a pair object that 1480 // carries both the locale and the type. 1481 int typeStart = key.indexOf('+') + 1; 1482 int typeLimit = key.indexOf('+', typeStart); 1483 if (typeLimit < 0) { 1484 // no numbers keyword value 1485 typeLimit = key.length(); 1486 } 1487 String type = key.substring(typeStart, typeLimit); 1488 return new DateFormatSymbols(locale, null, type); 1489 } 1490 }; 1491 1492 /** 1493 * Initializes format symbols for the locale and calendar type 1494 * @param desiredLocale The locale whose symbols are desired. 1495 * @param type The calendar type whose date format symbols are desired. 1496 */ 1497 //TODO: This protected seems to be marked as @stable accidentally. 1498 // We may need to deescalate this API to @internal. 1499 protected void initializeData(ULocale desiredLocale, String type) 1500 { 1501 String key = desiredLocale.getBaseName() + '+' + type; 1502 String ns = desiredLocale.getKeywordValue("numbers"); 1503 if (ns != null && ns.length() > 0) { 1504 key += '+' + ns; 1505 } 1506 DateFormatSymbols dfs = DFSCACHE.getInstance(key, desiredLocale); 1507 initializeData(dfs); 1508 } 1509 1510 /** 1511 * Initializes format symbols using another instance. 1512 * 1513 * TODO Clean up initialization methods for subclasses 1514 */ 1515 void initializeData(DateFormatSymbols dfs) { 1516 this.eras = dfs.eras; 1517 this.eraNames = dfs.eraNames; 1518 this.narrowEras = dfs.narrowEras; 1519 this.months = dfs.months; 1520 this.shortMonths = dfs.shortMonths; 1521 this.narrowMonths = dfs.narrowMonths; 1522 this.standaloneMonths = dfs.standaloneMonths; 1523 this.standaloneShortMonths = dfs.standaloneShortMonths; 1524 this.standaloneNarrowMonths = dfs.standaloneNarrowMonths; 1525 this.weekdays = dfs.weekdays; 1526 this.shortWeekdays = dfs.shortWeekdays; 1527 this.shorterWeekdays = dfs.shorterWeekdays; 1528 this.narrowWeekdays = dfs.narrowWeekdays; 1529 this.standaloneWeekdays = dfs.standaloneWeekdays; 1530 this.standaloneShortWeekdays = dfs.standaloneShortWeekdays; 1531 this.standaloneShorterWeekdays = dfs.standaloneShorterWeekdays; 1532 this.standaloneNarrowWeekdays = dfs.standaloneNarrowWeekdays; 1533 this.ampms = dfs.ampms; 1534 this.ampmsNarrow = dfs.ampmsNarrow; 1535 this.timeSeparator = dfs.timeSeparator; 1536 this.shortQuarters = dfs.shortQuarters; 1537 this.quarters = dfs.quarters; 1538 this.standaloneShortQuarters = dfs.standaloneShortQuarters; 1539 this.standaloneQuarters = dfs.standaloneQuarters; 1540 this.leapMonthPatterns = dfs.leapMonthPatterns; 1541 this.shortYearNames = dfs.shortYearNames; 1542 this.shortZodiacNames = dfs.shortZodiacNames; 1543 this.abbreviatedDayPeriods = dfs.abbreviatedDayPeriods; 1544 this.wideDayPeriods = dfs.wideDayPeriods; 1545 this.narrowDayPeriods = dfs.narrowDayPeriods; 1546 this.standaloneAbbreviatedDayPeriods = dfs.standaloneAbbreviatedDayPeriods; 1547 this.standaloneWideDayPeriods = dfs.standaloneWideDayPeriods; 1548 this.standaloneNarrowDayPeriods = dfs.standaloneNarrowDayPeriods; 1549 1550 this.zoneStrings = dfs.zoneStrings; // always null at initialization time for now 1551 this.localPatternChars = dfs.localPatternChars; 1552 1553 this.capitalization = dfs.capitalization; 1554 1555 this.actualLocale = dfs.actualLocale; 1556 this.validLocale = dfs.validLocale; 1557 this.requestedLocale = dfs.requestedLocale; 1558 } 1559 1560 1561 /** 1562 * Sink to enumerate the calendar data 1563 */ 1564 private static final class CalendarDataSink extends UResource.Sink { 1565 1566 // Data structures to store resources from the resource bundle 1567 Map<String, String[]> arrays = new TreeMap<String, String[]>(); 1568 Map<String, Map<String, String>> maps = new TreeMap<String, Map<String, String>>(); 1569 List<String> aliasPathPairs = new ArrayList<String>(); 1570 1571 // Current and next calendar resource table which should be loaded 1572 String currentCalendarType = null; 1573 String nextCalendarType = null; 1574 1575 // Resources to visit when enumerating fallback calendars 1576 private Set<String> resourcesToVisit; 1577 1578 // Alias' relative path populated when an alias is read 1579 private String aliasRelativePath; 1580 1581 /** 1582 * Initializes CalendarDataSink with default values 1583 */ 1584 CalendarDataSink() { } 1585 1586 /** 1587 * Configure the CalendarSink to visit all the resources 1588 */ 1589 void visitAllResources() { 1590 resourcesToVisit = null; 1591 } 1592 1593 /** 1594 * Actions to be done before enumerating 1595 */ 1596 void preEnumerate(String calendarType) { 1597 currentCalendarType = calendarType; 1598 nextCalendarType = null; 1599 aliasPathPairs.clear(); 1600 } 1601 1602 @Override 1603 public void put(UResource.Key key, UResource.Value value, boolean noFallback) { 1604 assert currentCalendarType != null && !currentCalendarType.isEmpty(); 1605 1606 // Stores the resources to visit on the next calendar. 1607 Set<String> resourcesToVisitNext = null; 1608 UResource.Table calendarData = value.getTable(); 1609 1610 // Enumerate all resources for this calendar 1611 for (int i = 0; calendarData.getKeyAndValue(i, key, value); i++) { 1612 String keyString = key.toString(); 1613 1614 // == Handle aliases == 1615 AliasType aliasType = processAliasFromValue(keyString, value); 1616 if (aliasType == AliasType.GREGORIAN) { 1617 // Ignore aliases to the gregorian calendar, all of its resources will be loaded anyways. 1618 continue; 1619 1620 } else if (aliasType == AliasType.DIFFERENT_CALENDAR) { 1621 // Whenever an alias to the next calendar (except gregorian) is encountered, register the 1622 // calendar type it's pointing to 1623 if (resourcesToVisitNext == null) { 1624 resourcesToVisitNext = new HashSet<String>(); 1625 } 1626 resourcesToVisitNext.add(aliasRelativePath); 1627 continue; 1628 1629 } else if (aliasType == AliasType.SAME_CALENDAR) { 1630 // Register same-calendar alias 1631 if (!arrays.containsKey(keyString) && !maps.containsKey(keyString)) { 1632 aliasPathPairs.add(aliasRelativePath); 1633 aliasPathPairs.add(keyString); 1634 } 1635 continue; 1636 } 1637 1638 // Only visit the resources that were referenced by an alias on the previous calendar 1639 // (AmPmMarkersAbbr is an exception). 1640 if (resourcesToVisit != null && !resourcesToVisit.isEmpty() && !resourcesToVisit.contains(keyString) 1641 && !keyString.equals("AmPmMarkersAbbr")) { continue; } 1642 1643 // == Handle data == 1644 if (keyString.startsWith("AmPmMarkers")) { 1645 if (!keyString.endsWith("%variant") && !arrays.containsKey(keyString)) { 1646 String[] dataArray = value.getStringArray(); 1647 arrays.put(keyString, dataArray); 1648 } 1649 } else if (keyString.equals("eras") 1650 || keyString.equals("dayNames") 1651 || keyString.equals("monthNames") 1652 || keyString.equals("quarters") 1653 || keyString.equals("dayPeriod") 1654 || keyString.equals("monthPatterns") 1655 || keyString.equals("cyclicNameSets")) { 1656 processResource(keyString, key, value); 1657 } 1658 } 1659 1660 // Apply same-calendar aliases 1661 boolean modified; 1662 do { 1663 modified = false; 1664 for (int i = 0; i < aliasPathPairs.size();) { 1665 boolean mod = false; 1666 String alias = aliasPathPairs.get(i); 1667 if (arrays.containsKey(alias)) { 1668 arrays.put(aliasPathPairs.get(i + 1), arrays.get(alias)); 1669 mod = true; 1670 } else if (maps.containsKey(alias)) { 1671 maps.put(aliasPathPairs.get(i + 1), maps.get(alias)); 1672 mod = true; 1673 } 1674 if (mod) { 1675 aliasPathPairs.remove(i + 1); 1676 aliasPathPairs.remove(i); 1677 modified = true; 1678 } else { 1679 i += 2; 1680 } 1681 } 1682 } while (modified && !aliasPathPairs.isEmpty()); 1683 1684 // Set the resources to visit on the next calendar 1685 if (resourcesToVisitNext != null) { 1686 resourcesToVisit = resourcesToVisitNext; 1687 } 1688 } 1689 1690 /** 1691 * Process the nested resource bundle tables 1692 * @param path Table's relative path to the calendar 1693 * @param key Resource bundle key 1694 * @param value Resource bundle value (has to have the table to read) 1695 */ 1696 protected void processResource(String path, UResource.Key key, UResource.Value value) { 1697 1698 UResource.Table table = value.getTable(); 1699 Map<String, String> stringMap = null; 1700 1701 // Iterate over all the elements of the table and add them to the map 1702 for(int i = 0; table.getKeyAndValue(i, key, value); i++) { 1703 // Ignore '%variant' keys 1704 if (key.endsWith("%variant")) { continue; } 1705 1706 String keyString = key.toString(); 1707 1708 // == Handle String elements == 1709 if (value.getType() == ICUResourceBundle.STRING) { 1710 // We are on a leaf, store the map elements into the stringMap 1711 if (i == 0) { 1712 stringMap = new HashMap<String, String>(); 1713 maps.put(path, stringMap); 1714 } 1715 assert stringMap != null; 1716 stringMap.put(keyString, value.getString()); 1717 continue; 1718 } 1719 assert stringMap == null; 1720 1721 String currentPath = path + "/" + keyString; 1722 // In cyclicNameSets ignore everything but years/format/abbreviated 1723 // and zodiacs/format/abbreviated 1724 if (currentPath.startsWith("cyclicNameSets")) { 1725 if (!"cyclicNameSets/years/format/abbreviated".startsWith(currentPath) 1726 && !"cyclicNameSets/zodiacs/format/abbreviated".startsWith(currentPath) 1727 && !"cyclicNameSets/dayParts/format/abbreviated".startsWith(currentPath)) 1728 { continue; } 1729 } 1730 1731 // == Handle aliases == 1732 if (arrays.containsKey(currentPath) 1733 || maps.containsKey(currentPath)) { continue; } 1734 1735 AliasType aliasType = processAliasFromValue(currentPath, value); 1736 if (aliasType == AliasType.SAME_CALENDAR) { 1737 aliasPathPairs.add(aliasRelativePath); 1738 aliasPathPairs.add(currentPath); 1739 continue; 1740 } 1741 assert aliasType == AliasType.NONE; 1742 1743 // == Handle data == 1744 if (value.getType() == ICUResourceBundle.ARRAY) { 1745 // We are on a leaf, store the array 1746 String[] dataArray = value.getStringArray(); 1747 arrays.put(currentPath, dataArray); 1748 } else if (value.getType() == ICUResourceBundle.TABLE) { 1749 // We are not on a leaf, recursively process the subtable. 1750 processResource(currentPath, key, value); 1751 } 1752 } 1753 } 1754 1755 // Alias' path prefix 1756 private static final String CALENDAR_ALIAS_PREFIX = "/LOCALE/calendar/"; 1757 1758 /** 1759 * Populates an AliasIdentifier with the alias information contained on the UResource.Value. 1760 * @param currentRelativePath Relative path of this alias' resource 1761 * @param value Value which contains the alias 1762 * @return The AliasType of the alias found on Value 1763 */ 1764 private AliasType processAliasFromValue(String currentRelativePath, UResource.Value value) { 1765 if (value.getType() == ICUResourceBundle.ALIAS) { 1766 String aliasPath = value.getAliasString(); 1767 if (aliasPath.startsWith(CALENDAR_ALIAS_PREFIX) && 1768 aliasPath.length() > CALENDAR_ALIAS_PREFIX.length()) { 1769 int typeLimit = aliasPath.indexOf('/', CALENDAR_ALIAS_PREFIX.length()); 1770 if (typeLimit > CALENDAR_ALIAS_PREFIX.length()) { 1771 String aliasCalendarType = aliasPath.substring(CALENDAR_ALIAS_PREFIX.length(), typeLimit); 1772 aliasRelativePath = aliasPath.substring(typeLimit + 1); 1773 1774 if (currentCalendarType.equals(aliasCalendarType) 1775 && !currentRelativePath.equals(aliasRelativePath)) { 1776 // If we have an alias to the same calendar, the path to the resource must be different 1777 return AliasType.SAME_CALENDAR; 1778 1779 } else if (!currentCalendarType.equals(aliasCalendarType) 1780 && currentRelativePath.equals(aliasRelativePath)) { 1781 // If we have an alias to a different calendar, the path to the resource must be the same 1782 if (aliasCalendarType.equals("gregorian")) { 1783 return AliasType.GREGORIAN; 1784 } else if (nextCalendarType == null || nextCalendarType.equals(aliasCalendarType)) { 1785 nextCalendarType = aliasCalendarType; 1786 return AliasType.DIFFERENT_CALENDAR; 1787 } 1788 } 1789 } 1790 } 1791 throw new ICUException("Malformed 'calendar' alias. Path: " + aliasPath); 1792 } 1793 return AliasType.NONE; 1794 } 1795 1796 /** 1797 * Enum which specifies the type of alias received, or no alias 1798 */ 1799 private enum AliasType { 1800 SAME_CALENDAR, 1801 DIFFERENT_CALENDAR, 1802 GREGORIAN, 1803 NONE 1804 } 1805 } 1806 1807 /** Private, for cache.getInstance(). */ 1808 private DateFormatSymbols(ULocale desiredLocale, ICUResourceBundle b, String calendarType) { 1809 initializeData(desiredLocale, b, calendarType); 1810 } 1811 1812 /** 1813 * Initializes format symbols for the locale and calendar type 1814 * @param desiredLocale The locale whose symbols are desired. 1815 * @param b Resource bundle provided externally 1816 * @param calendarType The calendar type being used 1817 * @deprecated This API is ICU internal only. 1818 * @hide draft / provisional / internal are hidden on Android 1819 */ 1820 @Deprecated 1821 // This API was accidentally marked as @stable ICU 3.0 formerly. 1822 protected void initializeData(ULocale desiredLocale, ICUResourceBundle b, String calendarType) 1823 { 1824 // Create a CalendarSink to load this data and a resource bundle 1825 CalendarDataSink calendarSink = new CalendarDataSink(); 1826 if (b == null) { 1827 b = (ICUResourceBundle) UResourceBundle 1828 .getBundleInstance(ICUData.ICU_BASE_NAME, desiredLocale); 1829 } 1830 1831 // Iterate over the resource bundle data following the fallbacks through different calendar types 1832 while (calendarType != null) { 1833 1834 // Enumerate this calendar type. If the calendar is not found fallback to gregorian. 1835 ICUResourceBundle dataForType = b.findWithFallback("calendar/" + calendarType); 1836 if (dataForType == null) { 1837 if (!"gregorian".equals(calendarType)) { 1838 calendarType = "gregorian"; 1839 calendarSink.visitAllResources(); 1840 continue; 1841 } 1842 throw new MissingResourceException("The 'gregorian' calendar type wasn't found for the locale: " 1843 + desiredLocale.getBaseName(), getClass().getName(), "gregorian"); 1844 } 1845 calendarSink.preEnumerate(calendarType); 1846 dataForType.getAllItemsWithFallback("", calendarSink); 1847 1848 // Stop loading when gregorian was loaded 1849 if (calendarType.equals("gregorian")) { 1850 break; 1851 } 1852 1853 // Get the next calendar type to process from the sink 1854 calendarType = calendarSink.nextCalendarType; 1855 1856 // Gregorian is always the last fallback 1857 if (calendarType == null) { 1858 calendarType = "gregorian"; 1859 calendarSink.visitAllResources(); 1860 } 1861 } 1862 1863 Map<String, String[]> arrays = calendarSink.arrays; 1864 Map<String, Map<String, String>> maps = calendarSink.maps; 1865 1866 eras = arrays.get("eras/abbreviated"); 1867 eraNames = arrays.get("eras/wide"); 1868 narrowEras = arrays.get("eras/narrow"); 1869 1870 months = arrays.get("monthNames/format/wide"); 1871 shortMonths = arrays.get("monthNames/format/abbreviated"); 1872 narrowMonths = arrays.get("monthNames/format/narrow"); 1873 1874 standaloneMonths = arrays.get("monthNames/stand-alone/wide"); 1875 standaloneShortMonths = arrays.get("monthNames/stand-alone/abbreviated"); 1876 standaloneNarrowMonths = arrays.get("monthNames/stand-alone/narrow"); 1877 1878 String[] lWeekdays = arrays.get("dayNames/format/wide"); 1879 weekdays = new String[8]; 1880 weekdays[0] = ""; // 1-based 1881 System.arraycopy(lWeekdays, 0, weekdays, 1, lWeekdays.length); 1882 1883 String[] aWeekdays = arrays.get("dayNames/format/abbreviated"); 1884 shortWeekdays = new String[8]; 1885 shortWeekdays[0] = ""; // 1-based 1886 System.arraycopy(aWeekdays, 0, shortWeekdays, 1, aWeekdays.length); 1887 1888 String[] sWeekdays = arrays.get("dayNames/format/short"); 1889 shorterWeekdays = new String[8]; 1890 shorterWeekdays[0] = ""; // 1-based 1891 System.arraycopy(sWeekdays, 0, shorterWeekdays, 1, sWeekdays.length); 1892 1893 String [] nWeekdays = arrays.get("dayNames/format/narrow"); 1894 if (nWeekdays == null) { 1895 nWeekdays = arrays.get("dayNames/stand-alone/narrow"); 1896 1897 if (nWeekdays == null) { 1898 nWeekdays = arrays.get("dayNames/format/abbreviated"); 1899 1900 if (nWeekdays == null) { 1901 throw new MissingResourceException("Resource not found", 1902 getClass().getName(), "dayNames/format/abbreviated"); 1903 } 1904 } 1905 } 1906 narrowWeekdays = new String[8]; 1907 narrowWeekdays[0] = ""; // 1-based 1908 System.arraycopy(nWeekdays, 0, narrowWeekdays, 1, nWeekdays.length); 1909 1910 String [] swWeekdays = null; 1911 swWeekdays = arrays.get("dayNames/stand-alone/wide"); 1912 standaloneWeekdays = new String[8]; 1913 standaloneWeekdays[0] = ""; // 1-based 1914 System.arraycopy(swWeekdays, 0, standaloneWeekdays, 1, swWeekdays.length); 1915 1916 String [] saWeekdays = null; 1917 saWeekdays = arrays.get("dayNames/stand-alone/abbreviated"); 1918 standaloneShortWeekdays = new String[8]; 1919 standaloneShortWeekdays[0] = ""; // 1-based 1920 System.arraycopy(saWeekdays, 0, standaloneShortWeekdays, 1, saWeekdays.length); 1921 1922 String [] ssWeekdays = null; 1923 ssWeekdays = arrays.get("dayNames/stand-alone/short"); 1924 standaloneShorterWeekdays = new String[8]; 1925 standaloneShorterWeekdays[0] = ""; // 1-based 1926 System.arraycopy(ssWeekdays, 0, standaloneShorterWeekdays, 1, ssWeekdays.length); 1927 1928 String [] snWeekdays = null; 1929 snWeekdays = arrays.get("dayNames/stand-alone/narrow"); 1930 standaloneNarrowWeekdays = new String[8]; 1931 standaloneNarrowWeekdays[0] = ""; // 1-based 1932 System.arraycopy(snWeekdays, 0, standaloneNarrowWeekdays, 1, snWeekdays.length); 1933 1934 ampms = arrays.get("AmPmMarkers"); 1935 ampmsNarrow = arrays.get("AmPmMarkersNarrow"); 1936 1937 quarters = arrays.get("quarters/format/wide"); 1938 shortQuarters = arrays.get("quarters/format/abbreviated"); 1939 1940 standaloneQuarters = arrays.get("quarters/stand-alone/wide"); 1941 standaloneShortQuarters = arrays.get("quarters/stand-alone/abbreviated"); 1942 1943 abbreviatedDayPeriods = loadDayPeriodStrings(maps.get("dayPeriod/format/abbreviated")); 1944 wideDayPeriods = loadDayPeriodStrings(maps.get("dayPeriod/format/wide")); 1945 narrowDayPeriods = loadDayPeriodStrings(maps.get("dayPeriod/format/narrow")); 1946 standaloneAbbreviatedDayPeriods = loadDayPeriodStrings(maps.get("dayPeriod/stand-alone/abbreviated")); 1947 standaloneWideDayPeriods = loadDayPeriodStrings(maps.get("dayPeriod/stand-alone/wide")); 1948 standaloneNarrowDayPeriods = loadDayPeriodStrings(maps.get("dayPeriod/stand-alone/narrow")); 1949 1950 for (int i = 0; i < DT_MONTH_PATTERN_COUNT; i++) { 1951 String monthPatternPath = LEAP_MONTH_PATTERNS_PATHS[i]; 1952 if (monthPatternPath != null) { 1953 Map<String, String> monthPatternMap = maps.get(monthPatternPath); 1954 if (monthPatternMap != null) { 1955 String leapMonthPattern = monthPatternMap.get("leap"); 1956 if (leapMonthPattern != null) { 1957 if (leapMonthPatterns == null) { 1958 leapMonthPatterns = new String[DT_MONTH_PATTERN_COUNT]; 1959 } 1960 leapMonthPatterns[i] = leapMonthPattern; 1961 } 1962 } 1963 } 1964 } 1965 1966 shortYearNames = arrays.get("cyclicNameSets/years/format/abbreviated"); 1967 shortZodiacNames = arrays.get("cyclicNameSets/zodiacs/format/abbreviated"); 1968 1969 requestedLocale = desiredLocale; 1970 1971 ICUResourceBundle rb = 1972 (ICUResourceBundle)UResourceBundle.getBundleInstance( 1973 ICUData.ICU_BASE_NAME, desiredLocale); 1974 1975 localPatternChars = patternChars; 1976 1977 // TODO: obtain correct actual/valid locale later 1978 ULocale uloc = rb.getULocale(); 1979 setLocale(uloc, uloc); 1980 1981 capitalization = new HashMap<CapitalizationContextUsage,boolean[]>(); 1982 boolean[] noTransforms = new boolean[2]; 1983 noTransforms[0] = false; 1984 noTransforms[1] = false; 1985 CapitalizationContextUsage allUsages[] = CapitalizationContextUsage.values(); 1986 for (CapitalizationContextUsage usage: allUsages) { 1987 capitalization.put(usage, noTransforms); 1988 } 1989 UResourceBundle contextTransformsBundle = null; 1990 try { 1991 contextTransformsBundle = rb.getWithFallback("contextTransforms"); 1992 } 1993 catch (MissingResourceException e) { 1994 contextTransformsBundle = null; // probably redundant 1995 } 1996 if (contextTransformsBundle != null) { 1997 UResourceBundleIterator ctIterator = contextTransformsBundle.getIterator(); 1998 while ( ctIterator.hasNext() ) { 1999 UResourceBundle contextTransformUsage = ctIterator.next(); 2000 int[] intVector = contextTransformUsage.getIntVector(); 2001 if (intVector.length >= 2) { 2002 String usageKey = contextTransformUsage.getKey(); 2003 CapitalizationContextUsage usage = contextUsageTypeMap.get(usageKey); 2004 if (usage != null) { 2005 boolean[] transforms = new boolean[2]; 2006 transforms[0] = (intVector[0] != 0); 2007 transforms[1] = (intVector[1] != 0); 2008 capitalization.put(usage, transforms); 2009 } 2010 } 2011 } 2012 } 2013 2014 NumberingSystem ns = NumberingSystem.getInstance(desiredLocale); 2015 String nsName = ns == null ? "latn" : ns.getName(); // Latin is default. 2016 String tsPath = "NumberElements/" + nsName + "/symbols/timeSeparator"; 2017 try { 2018 setTimeSeparatorString(rb.getStringWithFallback(tsPath)); 2019 } catch (MissingResourceException e) { 2020 setTimeSeparatorString(DEFAULT_TIME_SEPARATOR); 2021 } 2022 } 2023 2024 /** 2025 * Resource bundle paths for each leap month pattern 2026 */ 2027 private static final String[] LEAP_MONTH_PATTERNS_PATHS = new String[DT_MONTH_PATTERN_COUNT]; 2028 static { 2029 LEAP_MONTH_PATTERNS_PATHS[DT_LEAP_MONTH_PATTERN_FORMAT_WIDE] = "monthPatterns/format/wide"; 2030 LEAP_MONTH_PATTERNS_PATHS[DT_LEAP_MONTH_PATTERN_FORMAT_ABBREV] = "monthPatterns/format/abbreviated"; 2031 LEAP_MONTH_PATTERNS_PATHS[DT_LEAP_MONTH_PATTERN_FORMAT_NARROW] = "monthPatterns/format/narrow"; 2032 LEAP_MONTH_PATTERNS_PATHS[DT_LEAP_MONTH_PATTERN_STANDALONE_WIDE] = "monthPatterns/stand-alone/wide"; 2033 LEAP_MONTH_PATTERNS_PATHS[DT_LEAP_MONTH_PATTERN_STANDALONE_ABBREV] = "monthPatterns/stand-alone/abbreviated"; 2034 LEAP_MONTH_PATTERNS_PATHS[DT_LEAP_MONTH_PATTERN_STANDALONE_NARROW] = "monthPatterns/stand-alone/narrow"; 2035 LEAP_MONTH_PATTERNS_PATHS[DT_LEAP_MONTH_PATTERN_NUMERIC] = "monthPatterns/numeric/all"; 2036 } 2037 2038 private static final boolean arrayOfArrayEquals(Object[][] aa1, Object[][]aa2) { 2039 if (aa1 == aa2) { // both are null 2040 return true; 2041 } 2042 if (aa1 == null || aa2 == null) { // one is null and the other is not 2043 return false; 2044 } 2045 if (aa1.length != aa2.length) { 2046 return false; 2047 } 2048 boolean equal = true; 2049 for (int i = 0; i < aa1.length; i++) { 2050 equal = Utility.arrayEquals(aa1[i], aa2[i]); 2051 if (!equal) { 2052 break; 2053 } 2054 } 2055 return equal; 2056 } 2057 2058 /** 2059 * Keys for dayPeriods 2060 */ 2061 private static final String[] DAY_PERIOD_KEYS = {"midnight", "noon", 2062 "morning1", "afternoon1", "evening1", "night1", 2063 "morning2", "afternoon2", "evening2", "night2"}; 2064 2065 /** 2066 * Loads localized names for day periods in the requested format. 2067 * @param resourceMap Contains the dayPeriod resource to load 2068 */ 2069 private String[] loadDayPeriodStrings(Map<String, String> resourceMap) { 2070 String strings[] = new String[DAY_PERIOD_KEYS.length]; 2071 if (resourceMap != null) { 2072 for (int i = 0; i < DAY_PERIOD_KEYS.length; ++i) { 2073 strings[i] = resourceMap.get(DAY_PERIOD_KEYS[i]); // Null if string doesn't exist. 2074 } 2075 } 2076 return strings; 2077 } 2078 2079 /* 2080 * save the input locale 2081 */ 2082 private ULocale requestedLocale; 2083 2084 /* 2085 * Clones an array of Strings. 2086 * @param srcArray the source array to be cloned. 2087 * @return a cloned array. 2088 */ 2089 private final String[] duplicate(String[] srcArray) 2090 { 2091 return srcArray.clone(); 2092 } 2093 2094 private final String[][] duplicate(String[][] srcArray) 2095 { 2096 String[][] aCopy = new String[srcArray.length][]; 2097 for (int i = 0; i < srcArray.length; ++i) 2098 aCopy[i] = duplicate(srcArray[i]); 2099 return aCopy; 2100 } 2101 2102 /* 2103 * Compares the equality of the two arrays of String. 2104 * @param current this String array. 2105 * @param other that String array. 2106 private final boolean equals(String[] current, String[] other) 2107 { 2108 int count = current.length; 2109 2110 for (int i = 0; i < count; ++i) 2111 if (!current[i].equals(other[i])) 2112 return false; 2113 return true; 2114 } 2115 */ 2116 2117 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2118 2119 /** 2120 * Returns the {@link DateFormatSymbols} object that should be used to format a 2121 * calendar system's dates in the given locale. 2122 * <p> 2123 * <b>Subclassing:</b><br> 2124 * When creating a new Calendar subclass, you must create the 2125 * {@link ResourceBundle ResourceBundle} 2126 * containing its {@link DateFormatSymbols DateFormatSymbols} in a specific place. 2127 * The resource bundle name is based on the calendar's fully-specified 2128 * class name, with ".resources" inserted at the end of the package name 2129 * (just before the class name) and "Symbols" appended to the end. 2130 * For example, the bundle corresponding to "android.icu.util.HebrewCalendar" 2131 * is "android.icu.impl.data.HebrewCalendarSymbols". 2132 * <p> 2133 * Within the ResourceBundle, this method searches for five keys: 2134 * <ul> 2135 * <li><b>DayNames</b> - 2136 * An array of strings corresponding to each possible 2137 * value of the <code>DAY_OF_WEEK</code> field. Even though 2138 * <code>DAY_OF_WEEK</code> starts with <code>SUNDAY</code> = 1, 2139 * This array is 0-based; the name for Sunday goes in the 2140 * first position, at index 0. If this key is not found 2141 * in the bundle, the day names are inherited from the 2142 * default <code>DateFormatSymbols</code> for the requested locale. 2143 * 2144 * <li><b>DayAbbreviations</b> - 2145 * An array of abbreviated day names corresponding 2146 * to the values in the "DayNames" array. If this key 2147 * is not found in the resource bundle, the "DayNames" 2148 * values are used instead. If neither key is found, 2149 * the day abbreviations are inherited from the default 2150 * <code>DateFormatSymbols</code> for the locale. 2151 * 2152 * <li><b>MonthNames</b> - 2153 * An array of strings corresponding to each possible 2154 * value of the <code>MONTH</code> field. If this key is not found 2155 * in the bundle, the month names are inherited from the 2156 * default <code>DateFormatSymbols</code> for the requested locale. 2157 * 2158 * <li><b>MonthAbbreviations</b> - 2159 * An array of abbreviated day names corresponding 2160 * to the values in the "MonthNames" array. If this key 2161 * is not found in the resource bundle, the "MonthNames" 2162 * values are used instead. If neither key is found, 2163 * the day abbreviations are inherited from the default 2164 * <code>DateFormatSymbols</code> for the locale. 2165 * 2166 * <li><b>Eras</b> - 2167 * An array of strings corresponding to each possible 2168 * value of the <code>ERA</code> field. If this key is not found 2169 * in the bundle, the era names are inherited from the 2170 * default <code>DateFormatSymbols</code> for the requested locale. 2171 * </ul> 2172 * <p> 2173 * @param cal The calendar system whose date format symbols are desired. 2174 * @param locale The locale whose symbols are desired. 2175 * 2176 * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale) 2177 */ 2178 public DateFormatSymbols(Calendar cal, Locale locale) { 2179 initializeData(ULocale.forLocale(locale), cal.getType()); 2180 } 2181 2182 /** 2183 * Returns the {@link DateFormatSymbols} object that should be used to format a 2184 * calendar system's dates in the given locale. 2185 * <p> 2186 * <b>Subclassing:</b><br> 2187 * When creating a new Calendar subclass, you must create the 2188 * {@link ResourceBundle ResourceBundle} 2189 * containing its {@link DateFormatSymbols DateFormatSymbols} in a specific place. 2190 * The resource bundle name is based on the calendar's fully-specified 2191 * class name, with ".resources" inserted at the end of the package name 2192 * (just before the class name) and "Symbols" appended to the end. 2193 * For example, the bundle corresponding to "android.icu.util.HebrewCalendar" 2194 * is "android.icu.impl.data.HebrewCalendarSymbols". 2195 * <p> 2196 * Within the ResourceBundle, this method searches for five keys: 2197 * <ul> 2198 * <li><b>DayNames</b> - 2199 * An array of strings corresponding to each possible 2200 * value of the <code>DAY_OF_WEEK</code> field. Even though 2201 * <code>DAY_OF_WEEK</code> starts with <code>SUNDAY</code> = 1, 2202 * This array is 0-based; the name for Sunday goes in the 2203 * first position, at index 0. If this key is not found 2204 * in the bundle, the day names are inherited from the 2205 * default <code>DateFormatSymbols</code> for the requested locale. 2206 * 2207 * <li><b>DayAbbreviations</b> - 2208 * An array of abbreviated day names corresponding 2209 * to the values in the "DayNames" array. If this key 2210 * is not found in the resource bundle, the "DayNames" 2211 * values are used instead. If neither key is found, 2212 * the day abbreviations are inherited from the default 2213 * <code>DateFormatSymbols</code> for the locale. 2214 * 2215 * <li><b>MonthNames</b> - 2216 * An array of strings corresponding to each possible 2217 * value of the <code>MONTH</code> field. If this key is not found 2218 * in the bundle, the month names are inherited from the 2219 * default <code>DateFormatSymbols</code> for the requested locale. 2220 * 2221 * <li><b>MonthAbbreviations</b> - 2222 * An array of abbreviated day names corresponding 2223 * to the values in the "MonthNames" array. If this key 2224 * is not found in the resource bundle, the "MonthNames" 2225 * values are used instead. If neither key is found, 2226 * the day abbreviations are inherited from the default 2227 * <code>DateFormatSymbols</code> for the locale. 2228 * 2229 * <li><b>Eras</b> - 2230 * An array of strings corresponding to each possible 2231 * value of the <code>ERA</code> field. If this key is not found 2232 * in the bundle, the era names are inherited from the 2233 * default <code>DateFormatSymbols</code> for the requested locale. 2234 * </ul> 2235 * <p> 2236 * @param cal The calendar system whose date format symbols are desired. 2237 * @param locale The ulocale whose symbols are desired. 2238 * 2239 * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale) 2240 */ 2241 public DateFormatSymbols(Calendar cal, ULocale locale) { 2242 initializeData(locale, cal.getType()); 2243 } 2244 2245 /** 2246 * Variant of DateFormatSymbols(Calendar, Locale) that takes the Calendar class 2247 * instead of a Calendar instance. 2248 * @see #DateFormatSymbols(Calendar, Locale) 2249 */ 2250 public DateFormatSymbols(Class<? extends Calendar> calendarClass, Locale locale) { 2251 this(calendarClass, ULocale.forLocale(locale)); 2252 } 2253 2254 /** 2255 * Variant of DateFormatSymbols(Calendar, ULocale) that takes the Calendar class 2256 * instead of a Calendar instance. 2257 * @see #DateFormatSymbols(Calendar, Locale) 2258 */ 2259 public DateFormatSymbols(Class<? extends Calendar> calendarClass, ULocale locale) { 2260 String fullName = calendarClass.getName(); 2261 int lastDot = fullName.lastIndexOf('.'); 2262 String className = fullName.substring(lastDot+1); 2263 String calType = null; 2264 for (String[] calClassInfo : CALENDAR_CLASSES) { 2265 if (calClassInfo[0].equals(className)) { 2266 calType = calClassInfo[1]; 2267 break; 2268 } 2269 } 2270 if (calType == null) { 2271 calType = className.replaceAll("Calendar", "").toLowerCase(Locale.ENGLISH); 2272 } 2273 2274 initializeData(locale, calType); 2275 } 2276 2277 // Android patch (http://b/30464240) start: Add constructor taking a calendar type. 2278 /** 2279 * Variant of DateFormatSymbols(Calendar, ULocale) that takes the calendar type 2280 * instead of a Calendar instance. 2281 * @see #DateFormatSymbols(Calendar, Locale) 2282 * @deprecated This API is ICU internal only. 2283 * @hide draft / provisional / internal are hidden on Android 2284 */ 2285 @Deprecated 2286 public DateFormatSymbols(ULocale locale, String calType) { 2287 initializeData(locale, calType); 2288 } 2289 // Android patch end. 2290 2291 /** 2292 * Fetches a custom calendar's DateFormatSymbols out of the given resource 2293 * bundle. Symbols that are not overridden are inherited from the 2294 * default DateFormatSymbols for the locale. 2295 * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale) 2296 */ 2297 public DateFormatSymbols(ResourceBundle bundle, Locale locale) { 2298 this(bundle, ULocale.forLocale(locale)); 2299 } 2300 2301 /** 2302 * Fetches a custom calendar's DateFormatSymbols out of the given resource 2303 * bundle. Symbols that are not overridden are inherited from the 2304 * default DateFormatSymbols for the locale. 2305 * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale) 2306 */ 2307 public DateFormatSymbols(ResourceBundle bundle, ULocale locale) { 2308 initializeData(locale, (ICUResourceBundle) bundle, CalendarUtil.getCalendarType(locale)); 2309 } 2310 2311 /** 2312 * Finds the ResourceBundle containing the date format information for 2313 * a specified calendar subclass in a given locale. 2314 * <p> 2315 * The resource bundle name is based on the calendar's fully-specified 2316 * class name, with ".resources" inserted at the end of the package name 2317 * (just before the class name) and "Symbols" appended to the end. 2318 * For example, the bundle corresponding to "android.icu.util.HebrewCalendar" 2319 * is "android.icu.impl.data.HebrewCalendarSymbols". 2320 * <p> 2321 * <b>Note:</b>Because of the structural changes in the ICU locale bundle, 2322 * this API no longer works as described. This method always returns null. 2323 * @deprecated ICU 4.0 2324 * @hide original deprecated declaration 2325 */ 2326 @Deprecated 2327 // This API was formerly @stable ICU 2.0 2328 static public ResourceBundle getDateFormatBundle(Class<? extends Calendar> calendarClass, 2329 Locale locale) 2330 throws MissingResourceException { 2331 return null; 2332 } 2333 2334 /** 2335 * Finds the ResourceBundle containing the date format information for 2336 * a specified calendar subclass in a given locale. 2337 * <p> 2338 * The resource bundle name is based on the calendar's fully-specified 2339 * class name, with ".resources" inserted at the end of the package name 2340 * (just before the class name) and "Symbols" appended to the end. 2341 * For example, the bundle corresponding to "android.icu.util.HebrewCalendar" 2342 * is "android.icu.impl.data.HebrewCalendarSymbols". 2343 * <p> 2344 * <b>Note:</b>Because of the structural changes in the ICU locale bundle, 2345 * this API no longer works as described. This method always returns null. 2346 * @deprecated ICU 4.0 2347 * @hide original deprecated declaration 2348 */ 2349 @Deprecated 2350 // This API was formerly @stable ICU 3.2 2351 static public ResourceBundle getDateFormatBundle(Class<? extends Calendar> calendarClass, 2352 ULocale locale) 2353 throws MissingResourceException { 2354 return null; 2355 } 2356 2357 /** 2358 * Variant of getDateFormatBundle(java.lang.Class, java.util.Locale) that takes 2359 * a Calendar instance instead of a Calendar class. 2360 * <p> 2361 * <b>Note:</b>Because of the structural changes in the ICU locale bundle, 2362 * this API no longer works as described. This method always returns null. 2363 * @see #getDateFormatBundle(java.lang.Class, java.util.Locale) 2364 * @deprecated ICU 4.0 2365 * @hide original deprecated declaration 2366 */ 2367 @Deprecated 2368 // This API was formerly @stable ICU 2.2 2369 public static ResourceBundle getDateFormatBundle(Calendar cal, Locale locale) 2370 throws MissingResourceException { 2371 return null; 2372 } 2373 2374 /** 2375 * Variant of getDateFormatBundle(java.lang.Class, java.util.Locale) that takes 2376 * a Calendar instance instead of a Calendar class. 2377 * <p> 2378 * <b>Note:</b>Because of the structural changes in the ICU locale bundle, 2379 * this API no longer works as described. This method always returns null. 2380 * @see #getDateFormatBundle(java.lang.Class, java.util.Locale) 2381 * @deprecated ICU 4.0 2382 * @hide original deprecated declaration 2383 */ 2384 @Deprecated 2385 // This API was formerly @stable ICU 3.2 2386 public static ResourceBundle getDateFormatBundle(Calendar cal, ULocale locale) 2387 throws MissingResourceException { 2388 return null; 2389 } 2390 2391 // -------- BEGIN ULocale boilerplate -------- 2392 2393 /** 2394 * Returns the locale that was used to create this object, or null. 2395 * This may may differ from the locale requested at the time of 2396 * this object's creation. For example, if an object is created 2397 * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be 2398 * drawn from <tt>en</tt> (the <i>actual</i> locale), and 2399 * <tt>en_US</tt> may be the most specific locale that exists (the 2400 * <i>valid</i> locale). 2401 * 2402 * <p>Note: This method will be implemented in ICU 3.0; ICU 2.8 2403 * contains a partial preview implementation. The * <i>actual</i> 2404 * locale is returned correctly, but the <i>valid</i> locale is 2405 * not, in most cases. 2406 * @param type type of information requested, either {@link 2407 * android.icu.util.ULocale#VALID_LOCALE} or {@link 2408 * android.icu.util.ULocale#ACTUAL_LOCALE}. 2409 * @return the information specified by <i>type</i>, or null if 2410 * this object was not constructed from locale data. 2411 * @see android.icu.util.ULocale 2412 * @see android.icu.util.ULocale#VALID_LOCALE 2413 * @see android.icu.util.ULocale#ACTUAL_LOCALE 2414 * @hide draft / provisional / internal are hidden on Android 2415 */ 2416 public final ULocale getLocale(ULocale.Type type) { 2417 return type == ULocale.ACTUAL_LOCALE ? 2418 this.actualLocale : this.validLocale; 2419 } 2420 2421 /** 2422 * Sets information about the locales that were used to create this 2423 * object. If the object was not constructed from locale data, 2424 * both arguments should be set to null. Otherwise, neither 2425 * should be null. The actual locale must be at the same level or 2426 * less specific than the valid locale. This method is intended 2427 * for use by factories or other entities that create objects of 2428 * this class. 2429 * @param valid the most specific locale containing any resource 2430 * data, or null 2431 * @param actual the locale containing data used to construct this 2432 * object, or null 2433 * @see android.icu.util.ULocale 2434 * @see android.icu.util.ULocale#VALID_LOCALE 2435 * @see android.icu.util.ULocale#ACTUAL_LOCALE 2436 */ 2437 final void setLocale(ULocale valid, ULocale actual) { 2438 // Change the following to an assertion later 2439 if ((valid == null) != (actual == null)) { 2440 ///CLOVER:OFF 2441 throw new IllegalArgumentException(); 2442 ///CLOVER:ON 2443 } 2444 // Another check we could do is that the actual locale is at 2445 // the same level or less specific than the valid locale. 2446 this.validLocale = valid; 2447 this.actualLocale = actual; 2448 } 2449 2450 /** 2451 * The most specific locale containing any resource data, or null. 2452 * @see android.icu.util.ULocale 2453 */ 2454 private ULocale validLocale; 2455 2456 /** 2457 * The locale containing data used to construct this object, or 2458 * null. 2459 * @see android.icu.util.ULocale 2460 */ 2461 private ULocale actualLocale; 2462 2463 // -------- END ULocale boilerplate -------- 2464 2465 /** 2466 * 3.8 or older version did not have localized GMT format 2467 * patterns. 2468 */ 2469 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 2470 stream.defaultReadObject(); 2471 } 2472} 2473