17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/* 27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 3f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * Copyright (C) 2008-2015, International Business Machines Corporation and * 47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved. * 57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.text; 97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.Serializable; 117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.HashMap; 127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.HashSet; 137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.LinkedHashMap; 147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.LinkedHashSet; 157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Locale; 167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Map; 177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Map.Entry; 187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.MissingResourceException; 197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Set; 207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUCache; 227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUResourceBundle; 237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.SimpleCache; 247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.Utility; 257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.Calendar; 267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.Freezable; 277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ICUCloneNotSupportedException; 287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale; 297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.UResourceBundle; 307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/** 327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateIntervalInfo is a public class for encapsulating localizable 337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * date time interval patterns. It is used by DateIntervalFormat. 347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For most users, ordinary use of DateIntervalFormat does not need to create 377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateIntervalInfo object directly. 387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateIntervalFormat will take care of it when creating a date interval 397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * formatter when user pass in skeleton and locale. 407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For power users, who want to create their own date interval patterns, 437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * or want to re-set date interval patterns, they could do so by 447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * directly creating DateIntervalInfo and manupulating it. 457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Logically, the interval patterns are mappings 487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * from (skeleton, the_largest_different_calendar_field) 497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to (date_interval_pattern). 507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * A skeleton 537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ol> 547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li> 557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * only keeps the field pattern letter and ignores all other parts 567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in a pattern, such as space, punctuations, and string literals. 577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li> 587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * hides the order of fields. 597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li> 607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * might hide a field's pattern letter length. 617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For those non-digit calendar fields, the pattern letter length is 637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * important, such as MMM, MMMM, and MMMMM; EEE and EEEE, 647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and the field's pattern letter length is honored. 657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For the digit calendar fields, such as M or MM, d or dd, yy or yyyy, 677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the field pattern length is ignored and the best match, which is defined 687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in date time patterns, will be returned without honor the field pattern 697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * letter length in skeleton. 707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ol> 717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The calendar fields we support for interval formatting are: 747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * year, month, date, day-of-week, am-pm, hour, hour-of-day, and minute. 757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Those calendar fields can be defined in the following order: 767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * year > month > date > am-pm > hour > minute 777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The largest different calendar fields between 2 calendars is the 797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * first different calendar field in above order. 807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example: the largest different calendar fields between "Jan 10, 2007" 827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and "Feb 20, 2008" is year. 837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * There is a set of pre-defined static skeleton strings. 867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * There are pre-defined interval patterns for those pre-defined skeletons 877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in locales' resource files. 887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, for a skeleton YEAR_ABBR_MONTH_DAY, which is "yMMMd", 897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in en_US, if the largest different calendar field between date1 and date2 907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is "year", the date interval pattern is "MMM d, yyyy - MMM d, yyyy", 917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * such as "Jan 10, 2007 - Jan 10, 2008". 927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If the largest different calendar field between date1 and date2 is "month", 937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the date interval pattern is "MMM d - MMM d, yyyy", 947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * such as "Jan 10 - Feb 10, 2007". 957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If the largest different calendar field between date1 and date2 is "day", 967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the date interval pattern is ""MMM d-d, yyyy", such as "Jan 10-20, 2007". 977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For date skeleton, the interval patterns when year, or month, or date is 997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * different are defined in resource files. 1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For time skeleton, the interval patterns when am/pm, or hour, or minute is 1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * different are defined in resource files. 1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * There are 2 dates in interval pattern. For most locales, the first date 1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in an interval pattern is the earlier date. There might be a locale in which 1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the first date in an interval pattern is the later date. 1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * We use fallback format for the default order for the locale. 1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, if the fallback format is "{0} - {1}", it means 1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the first date in the interval pattern for this locale is earlier date. 1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If the fallback format is "{1} - {0}", it means the first date is the 1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * later date. 1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For a particular interval pattern, the default order can be overriden 1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * by prefixing "latestFirst:" or "earliestFirst:" to the interval pattern. 1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, if the fallback format is "{0}-{1}", 1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * but for skeleton "yMMMd", the interval pattern when day is different is 1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "latestFirst:d-d MMM yy", it means by default, the first date in interval 1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern is the earlier date. But for skeleton "yMMMd", when day is different, 1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the first date in "d-d MMM yy" is the later date. 1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The recommended way to create a DateIntervalFormat object is to pass in 1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the locale. 1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * By using a Locale parameter, the DateIntervalFormat object is 1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * initialized with the pre-defined interval patterns for a given or 1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * default locale. 1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Users can also create DateIntervalFormat object 1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * by supplying their own interval patterns. 1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It provides flexibility for power usage. 1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * After a DateIntervalInfo object is created, clients may modify 1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the interval patterns using setIntervalPattern function as so desired. 1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Currently, users can only set interval patterns when the following 1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * calendar fields are different: ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, 1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DAY_OF_WEEK, AM_PM, HOUR, HOUR_OF_DAY, and MINUTE. 1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Interval patterns when other calendar fields are different is not supported. 1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateIntervalInfo objects are cloneable. 1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * When clients obtain a DateIntervalInfo object, 1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * they can feel free to modify it as necessary. 1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateIntervalInfo are not expected to be subclassed. 1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Data for a calendar is loaded out of resource bundles. 1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Through ICU 4.4, date interval patterns are only supported in the Gregoria 1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * calendar; non-Gregorian calendars are supported from ICU 4.4.1. 1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class DateIntervalInfo implements Cloneable, Freezable<DateIntervalInfo>, Serializable { 153f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 154f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /** 155f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * Set to pattern for debugging, otherwise make null to strip dead code 156f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert */ 157f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert private static final String DEBUG_SKELETON = null; // "yMMM"; 158f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* Save the interval pattern information. 1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Interval pattern consists of 2 single date patterns and the separator. 1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, interval pattern "MMM d - MMM d, yyyy" consists 1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * a single date pattern "MMM d", another single date pattern "MMM d, yyyy", 1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and a separator "-". 1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Also, the first date appears in an interval pattern could be 1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the earlier date or the later date. 1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * And such information is saved in the interval pattern as well. 1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final int currentSerialVersion = 1; 1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * PatternInfo class saves the first and second part of interval pattern, 1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and whether the interval pattern is earlier date first. 1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final class PatternInfo implements Cloneable, Serializable { 1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final int currentSerialVersion = 1; 1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final long serialVersionUID = 1; 1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private final String fIntervalPatternFirstPart; 1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private final String fIntervalPatternSecondPart; 1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Whether the first date in interval pattern is later date or not. 1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Fallback format set the default ordering. 1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * And for a particular interval pattern, the order can be 1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * overriden by prefixing the interval pattern with "latestFirst:" or 1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "earliestFirst:" 1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, given 2 date, Jan 10, 2007 to Feb 10, 2007. 1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * if the fallback format is "{0} - {1}", 1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and the pattern is "d MMM - d MMM yyyy", the interval format is 1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "10 Jan - 10 Feb, 2007". 1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If the pattern is "latestFirst:d MMM - d MMM yyyy", 1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the interval format is "10 Feb - 10 Jan, 2007" 1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private final boolean fFirstDateInPtnIsLaterDate; 1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * constructor 1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PatternInfo(String firstPart, String secondPart, 2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean firstDateInPtnIsLaterDate) { 2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fIntervalPatternFirstPart = firstPart; 2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fIntervalPatternSecondPart = secondPart; 2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fFirstDateInPtnIsLaterDate = firstDateInPtnIsLaterDate; 2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * accessor 2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String getFirstPart() { 2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return fIntervalPatternFirstPart; 2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * accessor 2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String getSecondPart() { 2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return fIntervalPatternSecondPart; 2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * accessor 2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean firstDateInPtnIsLaterDate() { 2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return fFirstDateInPtnIsLaterDate; 2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Override equals 2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean equals(Object a) { 2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( a instanceof PatternInfo ) { 2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternInfo patternInfo = (PatternInfo)a; 2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return Utility.objectEquals(fIntervalPatternFirstPart, patternInfo.fIntervalPatternFirstPart) && 2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Utility.objectEquals(fIntervalPatternSecondPart, fIntervalPatternSecondPart) && 2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fFirstDateInPtnIsLaterDate == patternInfo.fFirstDateInPtnIsLaterDate; 2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Override hashcode 2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int hashCode() { 2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int hash = fIntervalPatternFirstPart != null ? fIntervalPatternFirstPart.hashCode() : 0; 2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fIntervalPatternSecondPart != null) { 2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert hash ^= fIntervalPatternSecondPart.hashCode(); 2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fFirstDateInPtnIsLaterDate) { 2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert hash ^= -1; 2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return hash; 2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 258f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 259f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /** 260f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * {@inheritDoc} 261f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * @internal 262f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * @deprecated This API is ICU internal only. 263f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert */ 264f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert @Deprecated 265f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert @Override 266f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert public String toString() { 267f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert return "{first=«" + fIntervalPatternFirstPart + "», second=«" + fIntervalPatternSecondPart + "», reversed:" + fFirstDateInPtnIsLaterDate + "}"; 268f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Following is package protected since 2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // it is shared with DateIntervalFormat. 2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final String[] CALENDAR_FIELD_TO_PATTERN_LETTER = 2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "G", "y", "M", 2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "w", "W", "d", 2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "D", "E", "F", 2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "a", "h", "H", 279f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert "m", "s", "S", // MINUTE, SECOND, MILLISECOND 280f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert "z", " ", "Y", // ZONE_OFFSET, DST_OFFSET, YEAR_WOY 281f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert "e", "u", "g", // DOW_LOCAL, EXTENDED_YEAR, JULIAN_DAY 282f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert "A", " ", " ", // MILLISECONDS_IN_DAY, IS_LEAP_MONTH. 2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }; 2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final long serialVersionUID = 1; 2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int MINIMUM_SUPPORTED_CALENDAR_FIELD = 2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar.MINUTE; 2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //private static boolean DEBUG = true; 2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static String FALLBACK_STRING = "fallback"; 2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static String LATEST_FIRST_PREFIX = "latestFirst:"; 2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static String EARLIEST_FIRST_PREFIX = "earliestFirst:"; 2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // DateIntervalInfo cache 2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private final static ICUCache<String, DateIntervalInfo> DIICACHE = new SimpleCache<String, DateIntervalInfo>(); 2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 298f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // default interval pattern on the skeleton, {0} - {1} 3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String fFallbackIntervalPattern; 3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // default order 3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean fFirstDateInPtnIsLaterDate = false; 3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // HashMap( skeleton, HashMap(largest_different_field, pattern) ) 3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Map<String, Map<String, PatternInfo>> fIntervalPatterns = null; 3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient volatile boolean frozen = false; 3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If true, fIntervalPatterns should not be modified in-place because it 3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // is shared with other objects. Unlike frozen which is always true once 3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // set to true, this field can go from true to false as long as frozen is 3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // false. 3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient boolean fIntervalPatternsReadOnly = false; 3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Create empty instance. 3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It does not initialize any interval patterns except 3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * that it initialize default fall-back pattern as "{0} - {1}", 3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * which can be reset by setFallbackIntervalPattern(). 3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It should be followed by setFallbackIntervalPattern() and 3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * setIntervalPattern(), 3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and is recommended to be used only for power users who 3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * wants to create their own interval patterns and use them to create 3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * date interval formatter. 3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public DateIntervalInfo() 3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fIntervalPatterns = new HashMap<String, Map<String, PatternInfo>>(); 3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fFallbackIntervalPattern = "{0} \u2013 {1}"; 3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Construct DateIntervalInfo for the given locale, 3407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param locale the interval patterns are loaded from the appropriate 3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * calendar data (specified calendar or default calendar) 3427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in this locale. 3437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 3447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public DateIntervalInfo(ULocale locale) 3467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 3477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initializeData(locale); 3487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Construct DateIntervalInfo for the given JDK locale, 3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param locale the interval patterns are loaded from the appropriate 3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * calendar data (specified calendar or default calendar) 3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in this locale. 3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @draft ICU 54 3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @provisional This API might change or be removed in a future release. 3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public DateIntervalInfo(Locale locale) 3607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 3617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this(ULocale.forLocale(locale)); 3627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 3657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Initialize the DateIntervalInfo from locale 3667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param locale the given locale. 3677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void initializeData(ULocale locale) 3697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 3707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String key = locale.toString(); 3717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalInfo dii = DIICACHE.get(key); 3727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( dii == null ) { 3737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // initialize data from scratch 3747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setup(locale); 3757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Marking fIntervalPatterns read-only makes cloning cheaper. 3767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fIntervalPatternsReadOnly = true; 3777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We freeze what goes in the cache without freezing this object. 3787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DIICACHE.put(key, ((DateIntervalInfo) clone()).freeze()); 3797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 3807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initializeFromReadOnlyPatterns(dii); 3817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Initialize this object 3887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dii must have read-only fIntervalPatterns. 3897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void initializeFromReadOnlyPatterns(DateIntervalInfo dii) { 3917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fFallbackIntervalPattern = dii.fFallbackIntervalPattern; 3927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fFirstDateInPtnIsLaterDate = dii.fFirstDateInPtnIsLaterDate; 3937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fIntervalPatterns = dii.fIntervalPatterns; 3947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fIntervalPatternsReadOnly = true; 3957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 3997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Initialize DateIntervalInfo from calendar data 4007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param calData calendar data 4017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void setup(ULocale locale) { 4037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int DEFAULT_HASH_SIZE = 19; 4047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fIntervalPatterns = new HashMap<String, Map<String, PatternInfo>>(DEFAULT_HASH_SIZE); 4057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // initialize to guard if there is no interval date format defined in 4067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // resource files 4077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fFallbackIntervalPattern = "{0} \u2013 {1}"; 408f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert HashSet<String> skeletonKeyPairs = new HashSet<String>(); 4097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 4107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // loop through all locales to get all available skeletons' 4117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // interval format 4127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ULocale currentLocale = locale; 4137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Get the correct calendar type 4147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String calendarTypeToUse = locale.getKeywordValue("calendar"); 4157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( calendarTypeToUse == null ) { 4167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String[] preferredCalendarTypes = Calendar.getKeywordValuesForLocale("calendar", locale, true); 4177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendarTypeToUse = preferredCalendarTypes[0]; // the most preferred calendar 4187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( calendarTypeToUse == null ) { 4207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendarTypeToUse = "gregorian"; // fallback 4217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert do { 4237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String name = currentLocale.getName(); 4247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( name.length() == 0 ) { 4257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 4267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,currentLocale); 4297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Note: 4307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ICU4J getWithFallback does not work well when 4317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 1) A nested table is an alias to /LOCALE/... 4327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 2) getWithFallback is called multiple times for going down hierarchical resource path 4337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // #9987 resolved the issue of alias table when full path is specified in getWithFallback, 4347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // but there is no easy solution when the equivalent operation is done by multiple operations. 4357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // This issue is addressed in #9964. 4367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// ICUResourceBundle calBundle = rb.getWithFallback("calendar"); 4377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// ICUResourceBundle calTypeBundle = calBundle.getWithFallback(calendarTypeToUse); 4387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ICUResourceBundle itvDtPtnResource =rb.getWithFallback("calendar/" + calendarTypeToUse + "/intervalFormats"); 4397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // look for fallback first, since it establishes the default order 4407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String fallback = itvDtPtnResource.getStringWithFallback(FALLBACK_STRING); 4417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setFallbackIntervalPattern(fallback); 4427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int size = itvDtPtnResource.getSize(); 4437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( int index = 0; index < size; ++index ) { 4447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String skeleton = itvDtPtnResource.get(index).getKey(); 4457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( skeleton.compareTo(FALLBACK_STRING) == 0 ) { 4467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 4477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ICUResourceBundle intervalPatterns = (ICUResourceBundle)itvDtPtnResource.get(skeleton); 4497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int ptnNum = intervalPatterns.getSize(); 4507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( int ptnIndex = 0; ptnIndex < ptnNum; ++ptnIndex) { 4517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String key = intervalPatterns.get(ptnIndex).getKey(); 452f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 453f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // hack because Relation isn't available, and it will probably port more easily than Pair<String,String> 454f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert String skeletonKeyPair = skeleton + "\u0001" + key; 455f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if (skeletonKeyPairs.contains(skeletonKeyPair)) { 456f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert continue; 457f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 458f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert skeletonKeyPairs.add(skeletonKeyPair); 459f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 4607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String pattern = intervalPatterns.get(ptnIndex).getString(); 4617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int calendarField = -1; // initialize with an invalid value. 4636598e9f0af29bfb1f2e0c97cce1a2b4432f9cd62Travis Keep if ( key.equals(CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.YEAR])) { 4647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendarField = Calendar.YEAR; 4656598e9f0af29bfb1f2e0c97cce1a2b4432f9cd62Travis Keep } else if ( key.equals(CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.MONTH])) { 4667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendarField = Calendar.MONTH; 4676598e9f0af29bfb1f2e0c97cce1a2b4432f9cd62Travis Keep } else if ( key.equals(CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.DATE])) { 4687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendarField = Calendar.DATE; 4696598e9f0af29bfb1f2e0c97cce1a2b4432f9cd62Travis Keep } else if ( key.equals(CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.AM_PM]) ) { 4707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendarField = Calendar.AM_PM; 4716598e9f0af29bfb1f2e0c97cce1a2b4432f9cd62Travis Keep } else if ( key.equals(CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.HOUR]) ) { 4726598e9f0af29bfb1f2e0c97cce1a2b4432f9cd62Travis Keep calendarField = Calendar.HOUR; 4736598e9f0af29bfb1f2e0c97cce1a2b4432f9cd62Travis Keep key = CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.HOUR]; 4746598e9f0af29bfb1f2e0c97cce1a2b4432f9cd62Travis Keep } else if ( key.equals(CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.HOUR_OF_DAY]) ) { 4756598e9f0af29bfb1f2e0c97cce1a2b4432f9cd62Travis Keep // HOUR_OF_DAY is 'H' for 24 hour clock; HOUR is 'h' for 12 hour clock. We use HOUR 4766598e9f0af29bfb1f2e0c97cce1a2b4432f9cd62Travis Keep // here instead of HOUR_OF_DAY because setIntervalPatternInternally understand HOUR. 4776598e9f0af29bfb1f2e0c97cce1a2b4432f9cd62Travis Keep calendarField = Calendar.HOUR; 4786598e9f0af29bfb1f2e0c97cce1a2b4432f9cd62Travis Keep key = CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.HOUR]; 4796598e9f0af29bfb1f2e0c97cce1a2b4432f9cd62Travis Keep } else if ( key.equals(CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.MINUTE]) ) { 4807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendarField = Calendar.MINUTE; 4817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( calendarField != -1 ) { 484f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if (DEBUG_SKELETON != null && DEBUG_SKELETON.equals(skeleton)) { 485f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert Map<String, PatternInfo> oldValue = fIntervalPatterns.get(skeleton); 486f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert setIntervalPatternInternally(skeleton, key, pattern); 487f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert Map<String, PatternInfo> newValue = fIntervalPatterns.get(skeleton); 488f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if (!Utility.objectEquals(oldValue, newValue)) { 489f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert System.out.println("\n" + currentLocale + ", skeleton: " + skeleton + ", oldValue: " + oldValue + ", newValue: " + newValue); 490f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 491f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } else { 492f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert setIntervalPatternInternally(skeleton, key, pattern); 493f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 4947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 4987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UResourceBundle parentNameBundle = rb.get("%%Parent"); 4997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currentLocale = new ULocale(parentNameBundle.getString()); 5007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch (MissingResourceException e) { 5017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currentLocale = currentLocale.getFallback(); 5027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } while (currentLocale != null && !currentLocale.getBaseName().equals("root")); 5047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch ( MissingResourceException e) { 5057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ok, will fallback to {data0} - {date1} 5067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 5117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Split interval patterns into 2 part. 5127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param intervalPattern interval pattern 5137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the index in interval pattern which split the pattern into 2 part 5147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static int splitPatternInto2Part(String intervalPattern) { 5167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean inQuote = false; 5177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char prevCh = 0; 5187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int count = 0; 5197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* repeatedPattern used to record whether a pattern has already seen. 5217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert It is a pattern applies to first calendar if it is first time seen, 5227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert otherwise, it is a pattern applies to the second calendar 5237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int[] patternRepeated = new int[58]; 5257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int PATTERN_CHAR_BASE = 0x41; 5277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* loop through the pattern string character by character looking for 5297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the first repeated pattern letter, which breaks the interval pattern 5307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * into 2 parts. 5317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int i; 5337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean foundRepetition = false; 5347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (i = 0; i < intervalPattern.length(); ++i) { 5357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char ch = intervalPattern.charAt(i); 5367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch != prevCh && count > 0) { 5387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // check the repeativeness of pattern letter 5397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int repeated = patternRepeated[prevCh - PATTERN_CHAR_BASE]; 5407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( repeated == 0 ) { 5417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternRepeated[prevCh - PATTERN_CHAR_BASE] = 1; 5427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 5437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert foundRepetition = true; 5447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 5457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = 0; 5477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch == '\'') { 5497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Consecutive single quotes are a single quote literal, 5507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // either outside of quotes or between quotes 5517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((i+1) < intervalPattern.length() && 5527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPattern.charAt(i+1) == '\'') { 5537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++i; 5547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 5557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert inQuote = ! inQuote; 5567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert else if (!inQuote && ((ch >= 0x0061 /*'a'*/ && ch <= 0x007A /*'z'*/) 5597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || (ch >= 0x0041 /*'A'*/ && ch <= 0x005A /*'Z'*/))) { 5607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ch is a date-time pattern character 5617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert prevCh = ch; 5627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++count; 5637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // check last pattern char, distinguish 5667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "dd MM" ( no repetition ), 5677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "d-d"(last char repeated ), and 5687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "d-d MM" ( repetition found ) 5697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( count > 0 && foundRepetition == false ) { 5707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( patternRepeated[prevCh - PATTERN_CHAR_BASE] == 0 ) { 5717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = 0; 5727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (i - count); 5757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Provides a way for client to build interval patterns. 5807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * User could construct DateIntervalInfo by providing 5817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * a list of skeletons and their patterns. 5827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 5837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example: 5847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <pre> 5857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateIntervalInfo dIntervalInfo = new DateIntervalInfo(); 5867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dIntervalInfo.setIntervalPattern("yMd", Calendar.YEAR, "'from' yyyy-M-d 'to' yyyy-M-d"); 5877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dIntervalInfo.setIntervalPattern("yMMMd", Calendar.MONTH, "'from' yyyy MMM d 'to' MMM d"); 5887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dIntervalInfo.setIntervalPattern("yMMMd", Calendar.DAY, "yyyy MMM d-d"); 5897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dIntervalInfo.setFallbackIntervalPattern("{0} ~ {1}"); 5907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </pre> 5917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Restriction: 5937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Currently, users can only set interval patterns when the following 5947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * calendar fields are different: ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, 5957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DAY_OF_WEEK, AM_PM, HOUR, HOUR_OF_DAY, and MINUTE. 5967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Interval patterns when other calendar fields are different are 5977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * not supported. 5987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param skeleton the skeleton on which interval pattern based 6007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param lrgDiffCalUnit the largest different calendar unit. 6017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param intervalPattern the interval pattern on the largest different 6027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * calendar unit. 6037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, if lrgDiffCalUnit is 6047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "year", the interval pattern for en_US when year 6057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is different could be "'from' yyyy 'to' yyyy". 6067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if setting interval pattern on 6077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * a calendar field that is smaller 6087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * than the MINIMUM_SUPPORTED_CALENDAR_FIELD 6097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws UnsupportedOperationException if the object is frozen 6107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 6117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setIntervalPattern(String skeleton, 6137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int lrgDiffCalUnit, 6147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String intervalPattern) 6157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 6167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( frozen ) { 6177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new UnsupportedOperationException("no modification is allowed after DII is frozen"); 6187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( lrgDiffCalUnit > MINIMUM_SUPPORTED_CALENDAR_FIELD ) { 6207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("calendar field is larger than MINIMUM_SUPPORTED_CALENDAR_FIELD"); 6217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fIntervalPatternsReadOnly) { 6237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fIntervalPatterns = cloneIntervalPatterns(fIntervalPatterns); 6247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fIntervalPatternsReadOnly = false; 6257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternInfo ptnInfo = setIntervalPatternInternally(skeleton, 6277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CALENDAR_FIELD_TO_PATTERN_LETTER[lrgDiffCalUnit], 6287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPattern); 6297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( lrgDiffCalUnit == Calendar.HOUR_OF_DAY ) { 6307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setIntervalPattern(skeleton, 6317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.AM_PM], 6327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ptnInfo); 6337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setIntervalPattern(skeleton, 6347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.HOUR], 6357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ptnInfo); 6367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( lrgDiffCalUnit == Calendar.DAY_OF_MONTH || 6377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert lrgDiffCalUnit == Calendar.DAY_OF_WEEK ) { 6387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setIntervalPattern(skeleton, 6397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.DATE], 6407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ptnInfo); 6417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* Set Interval pattern. 6467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It generates the interval pattern info, 6487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * afer which, not only sets the interval pattern info into the hash map, 6497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * but also returns the interval pattern info to the caller 6507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * so that caller can re-use it. 6517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param skeleton skeleton on which the interval pattern based 6537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param lrgDiffCalUnit the largest different calendar unit. 6547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param intervalPattern the interval pattern on the largest different 6557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * calendar unit. 6567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the interval pattern pattern information 6577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private PatternInfo setIntervalPatternInternally(String skeleton, 6597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String lrgDiffCalUnit, 6607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String intervalPattern) { 6617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Map<String, PatternInfo> patternsOfOneSkeleton = fIntervalPatterns.get(skeleton); 6627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean emptyHash = false; 6637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (patternsOfOneSkeleton == null) { 6647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternsOfOneSkeleton = new HashMap<String, PatternInfo>(); 6657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert emptyHash = true; 6667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean order = fFirstDateInPtnIsLaterDate; 6687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // check for "latestFirst:" or "earliestFirst:" prefix 6697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( intervalPattern.startsWith(LATEST_FIRST_PREFIX) ) { 6707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert order = true; 6717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int prefixLength = LATEST_FIRST_PREFIX.length(); 6727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPattern = intervalPattern.substring(prefixLength, intervalPattern.length()); 6737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( intervalPattern.startsWith(EARLIEST_FIRST_PREFIX) ) { 6747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert order = false; 6757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int earliestFirstLength = EARLIEST_FIRST_PREFIX.length(); 6767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPattern = intervalPattern.substring(earliestFirstLength, intervalPattern.length()); 6777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternInfo itvPtnInfo = genPatternInfo(intervalPattern, order); 6797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternsOfOneSkeleton.put(lrgDiffCalUnit, itvPtnInfo); 6817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( emptyHash == true ) { 6827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fIntervalPatterns.put(skeleton, patternsOfOneSkeleton); 6837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return itvPtnInfo; 6867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* Set Interval pattern. 6907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param skeleton skeleton on which the interval pattern based 6927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param lrgDiffCalUnit the largest different calendar unit. 6937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ptnInfo interval pattern infomration 6947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void setIntervalPattern(String skeleton, 6967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String lrgDiffCalUnit, 6977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternInfo ptnInfo) { 6987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Map<String, PatternInfo> patternsOfOneSkeleton = fIntervalPatterns.get(skeleton); 6997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternsOfOneSkeleton.put(lrgDiffCalUnit, ptnInfo); 7007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 7047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Break interval patterns as 2 part and save them into pattern info. 7057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param intervalPattern interval pattern 7067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param laterDateFirst whether the first date in intervalPattern 7077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is earlier date or later date 7087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return pattern info object 709f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * @internal 710f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * @deprecated This API is ICU internal only. 7117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 712f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert @Deprecated 713f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert public static PatternInfo genPatternInfo(String intervalPattern, 7147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean laterDateFirst) { 7157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int splitPoint = splitPatternInto2Part(intervalPattern); 7167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String firstPart = intervalPattern.substring(0, splitPoint); 7187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String secondPart = null; 7197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( splitPoint < intervalPattern.length() ) { 7207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert secondPart = intervalPattern.substring(splitPoint, intervalPattern.length()); 7217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new PatternInfo(firstPart, secondPart, laterDateFirst); 7247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 7287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Get the interval pattern given the largest different calendar field. 7297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param skeleton the skeleton 7307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param field the largest different calendar field 7317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return interval pattern return null if interval pattern is not found. 7327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if getting interval pattern on 7337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * a calendar field that is smaller 7347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * than the MINIMUM_SUPPORTED_CALENDAR_FIELD 7357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 7367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 7377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PatternInfo getIntervalPattern(String skeleton, int field) 7387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 7397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( field > MINIMUM_SUPPORTED_CALENDAR_FIELD ) { 7407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("no support for field less than MINUTE"); 7417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Map<String, PatternInfo> patternsOfOneSkeleton = fIntervalPatterns.get(skeleton); 7437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( patternsOfOneSkeleton != null ) { 7447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternInfo intervalPattern = patternsOfOneSkeleton. 7457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert get(CALENDAR_FIELD_TO_PATTERN_LETTER[field]); 7467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( intervalPattern != null ) { 7477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return intervalPattern; 7487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 7517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 7567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Get the fallback interval pattern. 7577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return fallback interval pattern 7587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 7597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 7607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String getFallbackIntervalPattern() 7617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 7627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return fFallbackIntervalPattern; 7637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 7677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Re-set the fallback interval pattern. 7687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 7697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * In construction, default fallback pattern is set as "{0} - {1}". 7707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * And constructor taking locale as parameter will set the 7717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * fallback pattern as what defined in the locale resource file. 7727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 7737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This method provides a way for user to replace the fallback pattern. 7747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 7757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param fallbackPattern fall-back interval pattern. 7767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws UnsupportedOperationException if the object is frozen 7777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if there is no pattern {0} or 7787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern {1} in fallbakckPattern 7797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 7807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 7817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 7827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setFallbackIntervalPattern(String fallbackPattern) 7837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 7847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( frozen ) { 7857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new UnsupportedOperationException("no modification is allowed after DII is frozen"); 7867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int firstPatternIndex = fallbackPattern.indexOf("{0}"); 7887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int secondPatternIndex = fallbackPattern.indexOf("{1}"); 7897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( firstPatternIndex == -1 || secondPatternIndex == -1 ) { 7907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("no pattern {0} or pattern {1} in fallbackPattern"); 7917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( firstPatternIndex > secondPatternIndex ) { 7937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fFirstDateInPtnIsLaterDate = true; 7947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fFallbackIntervalPattern = fallbackPattern; 7967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Get default order -- whether the first date in pattern is later date 8017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * or not. 8027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 8037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * return default date ordering in interval pattern. TRUE if the first date 8047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in pattern is later date, FALSE otherwise. 8057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 8067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean getDefaultOrder() 8087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 8097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return fFirstDateInPtnIsLaterDate; 8107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Boilerplate. Clone this object. 8157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return a copy of the object 8167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU4.0 8177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Object clone() 8197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 8207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( frozen ) { 8217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return this; 8227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return cloneUnfrozenDII(); 8247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 8287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Clone an unfrozen DateIntervalInfo object. 8297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return a copy of the object 8307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Object cloneUnfrozenDII() //throws IllegalStateException 8327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 8337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 8347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalInfo other = (DateIntervalInfo) super.clone(); 8357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert other.fFallbackIntervalPattern=fFallbackIntervalPattern; 8367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert other.fFirstDateInPtnIsLaterDate = fFirstDateInPtnIsLaterDate; 8377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fIntervalPatternsReadOnly) { 8387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert other.fIntervalPatterns = fIntervalPatterns; 8397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert other.fIntervalPatternsReadOnly = true; 8407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 8417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert other.fIntervalPatterns = cloneIntervalPatterns(fIntervalPatterns); 8427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert other.fIntervalPatternsReadOnly = false; 8437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert other.frozen = false; 8457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return other; 8467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch ( CloneNotSupportedException e ) { 8477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ///CLOVER:OFF 8487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new ICUCloneNotSupportedException("clone is not supported", e); 8497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ///CLOVER:ON 8507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static Map<String, Map<String, PatternInfo>> cloneIntervalPatterns( 8547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Map<String, Map<String, PatternInfo>> patterns) { 8557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Map<String, Map<String, PatternInfo>> result = new HashMap<String, Map<String, PatternInfo>>(); 8567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (Entry<String, Map<String, PatternInfo>> skeletonEntry : patterns.entrySet()) { 8577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String skeleton = skeletonEntry.getKey(); 8587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Map<String, PatternInfo> patternsOfOneSkeleton = skeletonEntry.getValue(); 8597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Map<String, PatternInfo> oneSetPtn = new HashMap<String, PatternInfo>(); 8607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (Entry<String, PatternInfo> calEntry : patternsOfOneSkeleton.entrySet()) { 8617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String calField = calEntry.getKey(); 8627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternInfo value = calEntry.getValue(); 8637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert oneSetPtn.put(calField, value); 8647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.put(skeleton, oneSetPtn); 8667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return result; 8687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Boilerplate for Freezable 8747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 8757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean isFrozen() { 8777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return frozen; 8787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Boilerplate for Freezable 8827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.4 8837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public DateIntervalInfo freeze() { 8857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fIntervalPatternsReadOnly = true; 8867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert frozen = true; 8877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return this; 8887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Boilerplate for Freezable 8927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.4 8937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public DateIntervalInfo cloneAsThawed() { 8957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalInfo result = (DateIntervalInfo) (this.cloneUnfrozenDII()); 8967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return result; 8977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Parse skeleton, save each field's width. 9027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It is used for looking for best match skeleton, 9037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and adjust pattern field width. 9047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param skeleton skeleton to be parsed 9057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param skeletonFieldWidth parsed skeleton field width 9067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static void parseSkeleton(String skeleton, int[] skeletonFieldWidth) { 9087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int PATTERN_CHAR_BASE = 0x41; 9097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( int i = 0; i < skeleton.length(); ++i ) { 9107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++skeletonFieldWidth[skeleton.charAt(i) - PATTERN_CHAR_BASE]; 9117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 9177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Check whether one field width is numeric while the other is string. 9187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 9197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * TODO (xji): make it general 9207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 9217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param fieldWidth one field width 9227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param anotherFieldWidth another field width 9237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param patternLetter pattern letter char 9247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true if one field width is numeric and the other is string, 9257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * false otherwise. 9267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static boolean stringNumeric(int fieldWidth, 9287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int anotherFieldWidth, 9297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char patternLetter) { 9307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( patternLetter == 'M' ) { 9317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( fieldWidth <= 2 && anotherFieldWidth > 2 || 9327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldWidth > 2 && anotherFieldWidth <= 2 ) { 9337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 9347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 9377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 9417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * given an input skeleton, get the best match skeleton 9427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * which has pre-defined interval pattern in resource file. 9437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 9447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * TODO (xji): set field weight or 9457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * isolate the funtionality in DateTimePatternGenerator 9467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param inputSkeleton input skeleton 9477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return 0, if there is exact match for input skeleton 9487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1, if there is only field width difference between 9497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the best match and the input skeleton 9507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2, the only field difference is 'v' and 'z' 9517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * -1, if there is calendar field difference between 9527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the best match and the input skeleton 9537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalFormat.BestMatchInfo getBestSkeleton(String inputSkeleton) { 9557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String bestSkeleton = inputSkeleton; 9567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int[] inputSkeletonFieldWidth = new int[58]; 9577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int[] skeletonFieldWidth = new int[58]; 9587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert final int DIFFERENT_FIELD = 0x1000; 9607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert final int STRING_NUMERIC_DIFFERENCE = 0x100; 9617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert final int BASE = 0x41; 9627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // TODO: this is a hack for 'v' and 'z' 9647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // resource bundle only have time skeletons ending with 'v', 9657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // but not for time skeletons ending with 'z'. 9667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean replaceZWithV = false; 9677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( inputSkeleton.indexOf('z') != -1 ) { 9687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert inputSkeleton = inputSkeleton.replace('z', 'v'); 9697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert replaceZWithV = true; 9707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parseSkeleton(inputSkeleton, inputSkeletonFieldWidth); 9737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int bestDistance = Integer.MAX_VALUE; 9747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 0 means exact the same skeletons; 9757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 1 means having the same field, but with different length, 9767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 2 means only z/v differs 9777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // -1 means having different field. 9787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int bestFieldDifference = 0; 9797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (String skeleton : fIntervalPatterns.keySet()) { 9807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // clear skeleton field width 9817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( int i = 0; i < skeletonFieldWidth.length; ++i ) { 9827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert skeletonFieldWidth[i] = 0; 9837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parseSkeleton(skeleton, skeletonFieldWidth); 9857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // calculate distance 9867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int distance = 0; 9877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int fieldDifference = 1; 9887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( int i = 0; i < inputSkeletonFieldWidth.length; ++i ) { 9897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int inputFieldWidth = inputSkeletonFieldWidth[i]; 9907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int fieldWidth = skeletonFieldWidth[i]; 9917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( inputFieldWidth == fieldWidth ) { 9927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 9937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( inputFieldWidth == 0 ) { 9957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldDifference = -1; 9967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert distance += DIFFERENT_FIELD; 9977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( fieldWidth == 0 ) { 9987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldDifference = -1; 9997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert distance += DIFFERENT_FIELD; 10007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (stringNumeric(inputFieldWidth, fieldWidth, 10017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (char)(i+BASE) ) ) { 10027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert distance += STRING_NUMERIC_DIFFERENCE; 10037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 10047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert distance += Math.abs(inputFieldWidth - fieldWidth); 10057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( distance < bestDistance ) { 10087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestSkeleton = skeleton; 10097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestDistance = distance; 10107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestFieldDifference = fieldDifference; 10117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( distance == 0 ) { 10137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestFieldDifference = 0; 10147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 10157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( replaceZWithV && bestFieldDifference != -1 ) { 10187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestFieldDifference = 2; 10197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new DateIntervalFormat.BestMatchInfo(bestSkeleton, bestFieldDifference); 10217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 10247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Override equals 10257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 10267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 10277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean equals(Object a) { 10287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( a instanceof DateIntervalInfo ) { 10297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalInfo dtInfo = (DateIntervalInfo)a; 10307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return fIntervalPatterns.equals(dtInfo.fIntervalPatterns); 10317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 10337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 10367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Override hashcode 10377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 10387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 10397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int hashCode() { 10407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return fIntervalPatterns.hashCode(); 10417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 10447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal CLDR 10457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 10467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 10477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 10487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Map<String,Set<String>> getPatterns() { 10497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert LinkedHashMap<String,Set<String>> result = new LinkedHashMap<String,Set<String>>(); 10507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (Entry<String, Map<String, PatternInfo>> entry : fIntervalPatterns.entrySet()) { 10517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.put(entry.getKey(), new LinkedHashSet<String>(entry.getValue().keySet())); 10527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return result; 10547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1055f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 1056f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /** 1057f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * Get the internal patterns, with a deep clone for safety. 1058f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * @internal CLDR 1059f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * @deprecated This API is ICU internal only. 1060f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert */ 1061f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert @Deprecated 1062f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert public Map<String, Map<String, PatternInfo>> getRawPatterns() { 1063f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert LinkedHashMap<String, Map<String, PatternInfo>> result = new LinkedHashMap<String, Map<String, PatternInfo>>(); 1064f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert for (Entry<String, Map<String, PatternInfo>> entry : fIntervalPatterns.entrySet()) { 1065f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert result.put(entry.getKey(), new LinkedHashMap<String, PatternInfo>(entry.getValue())); 1066f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 1067f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert return result; 1068f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 10697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}// end class DateIntervalInfo 1070