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