12d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// © 2016 and later: Unicode, Inc. and others. 22d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License 37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/* 487255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert* Copyright (C) 2008-2016, International Business Machines 57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* Corporation and others. All Rights Reserved. 67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*/ 77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.text; 97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.IOException; 117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.ObjectInputStream; 127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.FieldPosition; 137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.ParsePosition; 147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Collections; 157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.HashMap; 167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Locale; 177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Map; 187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUCache; 202d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubertimport com.ibm.icu.impl.ICUData; 212d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubertimport com.ibm.icu.impl.ICUResourceBundle; 227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.SimpleCache; 2387255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubertimport com.ibm.icu.impl.SimpleFormatterImpl; 247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.DateIntervalInfo.PatternInfo; 257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.Calendar; 267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.DateInterval; 277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.Output; 287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.TimeZone; 297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale; 307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale.Category; 312d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubertimport com.ibm.icu.util.UResourceBundle; 327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/** 357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateIntervalFormat is a class for formatting and parsing date 367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * intervals in a language-independent manner. 377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Only formatting is supported. Parsing is not supported. 387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Date interval means from one date to another date, 417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for example, from "Jan 11, 2008" to "Jan 18, 2008". 427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * We introduced class DateInterval to represent it. 437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateInterval is a pair of UDate, which is 447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the standard milliseconds since 24:00 GMT, Jan 1, 1970. 457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateIntervalFormat formats a DateInterval into 487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * text as compactly as possible. 497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, the date interval format from "Jan 11, 2008" to "Jan 18,. 2008" 507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is "Jan 11-18, 2008" for English. 517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * And it parses text into DateInterval, 527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * although initially, parsing is not supported. 537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * There is no structural information in date time patterns. 567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For any punctuations and string literals inside a date time pattern, 577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * we do not know whether it is just a separator, or a prefix, or a suffix. 587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Without such information, so, it is difficult to generate a sub-pattern 597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (or super-pattern) by algorithm. 607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * So, formatting a DateInterval is pattern-driven. It is very 617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * similar to formatting in SimpleDateFormat. 627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * We introduce class DateIntervalInfo to save date interval 637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * patterns, similar to date time pattern in SimpleDateFormat. 647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Logically, the interval patterns are mappings 677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * from (skeleton, the_largest_different_calendar_field) 687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to (date_interval_pattern). 697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * A skeleton 727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ol> 737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li> 747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * only keeps the field pattern letter and ignores all other parts 757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in a pattern, such as space, punctuations, and string literals. 767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li> 777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * hides the order of fields. 787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li> 797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * might hide a field's pattern letter length. 807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For those non-digit calendar fields, the pattern letter length is 827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * important, such as MMM, MMMM, and MMMMM; EEE and EEEE, 837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and the field's pattern letter length is honored. 847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For the digit calendar fields, such as M or MM, d or dd, yy or yyyy, 867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the field pattern length is ignored and the best match, which is defined 877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in date time patterns, will be returned without honor the field pattern 887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * letter length in skeleton. 897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ol> 907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The calendar fields we support for interval formatting are: 93bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * year, month, date, day-of-week, am-pm, hour, hour-of-day, minute, and 94bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * second (though we do not currently have specific intervalFormat data for 95bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * skeletons with seconds). 967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Those calendar fields can be defined in the following order: 979e281ba4837cba4a1cf9523d6f8b0621b150063dScott Russell * year > month > date > hour (in day) > minute > second 987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The largest different calendar fields between 2 calendars is the 1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * first different calendar field in above order. 1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example: the largest different calendar fields between "Jan 10, 2007" 1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and "Feb 20, 2008" is year. 1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For other calendar fields, the compact interval formatting is not 1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * supported. And the interval format will be fall back to fall-back 1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * patterns, which is mostly "{date0} - {date1}". 1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * There is a set of pre-defined static skeleton strings in DateFormat, 1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * There are pre-defined interval patterns for those pre-defined skeletons 1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in locales' resource files. 1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, for a skeleton YEAR_ABBR_MONTH_DAY, which is "yMMMd", 1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in en_US, if the largest different calendar field between date1 and date2 1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is "year", the date interval pattern is "MMM d, yyyy - MMM d, yyyy", 1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * such as "Jan 10, 2007 - Jan 10, 2008". 1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If the largest different calendar field between date1 and date2 is "month", 1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the date interval pattern is "MMM d - MMM d, yyyy", 1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * such as "Jan 10 - Feb 10, 2007". 1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If the largest different calendar field between date1 and date2 is "day", 1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the date interval pattern is ""MMM d-d, yyyy", such as "Jan 10-20, 2007". 1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For date skeleton, the interval patterns when year, or month, or date is 1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * different are defined in resource files. 1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For time skeleton, the interval patterns when am/pm, or hour, or minute is 1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * different are defined in resource files. 1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If a skeleton is not found in a locale's DateIntervalInfo, which means 1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the interval patterns for the skeleton is not defined in resource file, 1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the interval pattern will falls back to the interval "fallback" pattern 1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * defined in resource file. 1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If the interval "fallback" pattern is not defined, the default fall-back 1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is "{date0} - {data1}". 1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For the combination of date and time, 1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The rule to genearte interval patterns are: 1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ol> 1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li> 1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * when the year, month, or day differs, falls back to fall-back 1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * interval pattern, which mostly is the concatenate the two original 1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * expressions with a separator between, 1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, interval pattern from "Jan 10, 2007 10:10 am" 1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to "Jan 11, 2007 10:10am" is 1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "Jan 10, 2007 10:10 am - Jan 11, 2007 10:10am" 1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li> 1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * otherwise, present the date followed by the range expression 1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for the time. 1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, interval pattern from "Jan 10, 2007 10:10 am" 1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to "Jan 10, 2007 11:10am" is "Jan 10, 2007 10:10 am - 11:10am" 1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ol> 1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If two dates are the same, the interval pattern is the single date pattern. 1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, interval pattern from "Jan 10, 2007" to "Jan 10, 2007" is 1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "Jan 10, 2007". 1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Or if the presenting fields between 2 dates have the exact same values, 1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the interval pattern is the single date pattern. 1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, if user only requests year and month, 1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the interval pattern from "Jan 10, 2007" to "Jan 20, 2007" is "Jan 2007". 1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateIntervalFormat needs the following information for correct 1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * formatting: time zone, calendar type, pattern, date format symbols, 1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and date interval patterns. 1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It can be instantiated in several ways: 1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ol> 1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li> 1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * create an instance using default or given locale plus given skeleton. 1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Users are encouraged to created date interval formatter this way and 1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to use the pre-defined skeleton macros, such as 1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * YEAR_NUM_MONTH, which consists the calendar fields and 1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the format style. 1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </li> 1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li> 1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * create an instance using default or given locale plus given skeleton 1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * plus a given DateIntervalInfo. 1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This factory method is for powerful users who want to provide their own 1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * interval patterns. 1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Locale provides the timezone, calendar, and format symbols information. 1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Local plus skeleton provides full pattern information. 1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateIntervalInfo provides the date interval patterns. 1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </li> 1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ol> 1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For the calendar field pattern letter, such as G, y, M, d, a, h, H, m, s etc. 1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateIntervalFormat uses the same syntax as that of 1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateTime format. 1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Code Sample: general usage 1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <pre> 1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * // the date interval object which the DateIntervalFormat formats on 2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * // and parses into 2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateInterval dtInterval = new DateInterval(1000*3600*24L, 1000*3600*24*2L); 2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateIntervalFormat dtIntervalFmt = DateIntervalFormat.getInstance( 2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * YEAR_MONTH_DAY, Locale("en", "GB", "")); 2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * StringBuffer str = new StringBuffer(""); 2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * FieldPosition pos = new FieldPosition(0); 2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * // formatting 2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dtIntervalFmt.format(dtInterval, dateIntervalString, pos); 2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </pre> 2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Code Sample: for powerful users who wants to use their own interval pattern 2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <pre> 2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * import com.ibm.icu.text.DateIntervalInfo; 2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * import com.ibm.icu.text.DateIntervalFormat; 2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * .................... 2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * // Get DateIntervalFormat instance using default locale 2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateIntervalFormat dtitvfmt = DateIntervalFormat.getInstance(YEAR_MONTH_DAY); 2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * // Create an empty DateIntervalInfo object, which does not have any interval patterns inside. 2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dtitvinf = new DateIntervalInfo(); 2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * // a series of set interval patterns. 226bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * // Only ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, DAY_OF_WEEK, AM_PM, HOUR, HOUR_OF_DAY, 227bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * MINUTE and SECOND are supported. 2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dtitvinf.setIntervalPattern("yMMMd", Calendar.YEAR, "'y ~ y'"); 2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dtitvinf.setIntervalPattern("yMMMd", Calendar.MONTH, "yyyy 'diff' MMM d - MMM d"); 2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dtitvinf.setIntervalPattern("yMMMd", Calendar.DATE, "yyyy MMM d ~ d"); 2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dtitvinf.setIntervalPattern("yMMMd", Calendar.HOUR_OF_DAY, "yyyy MMM d HH:mm ~ HH:mm"); 2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * // Set fallback interval pattern. Fallback pattern is used when interval pattern is not found. 2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * // If the fall-back pattern is not set, falls back to {date0} - {date1} if interval pattern is not found. 2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dtitvinf.setFallbackIntervalPattern("{0} - {1}"); 2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * // Set above DateIntervalInfo object as the interval patterns of date interval formatter 2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dtitvfmt.setDateIntervalInfo(dtitvinf); 2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * // Prepare to format 2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pos = new FieldPosition(0); 2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * str = new StringBuffer(""); 2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * // The 2 calendars should be equivalent, otherwise, IllegalArgumentException will be thrown by format() 2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Calendar fromCalendar = (Calendar) dtfmt.getCalendar().clone(); 2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Calendar toCalendar = (Calendar) dtfmt.getCalendar().clone(); 2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * fromCalendar.setTimeInMillis(....); 2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * toCalendar.setTimeInMillis(...); 2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * //Formatting given 2 calendars 2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dtitvfmt.format(fromCalendar, toCalendar, str, pos); 2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </pre> 25587255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert * <h3>Synchronization</h3> 25687255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert * 25787255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert * The format methods of DateIntervalFormat may be used concurrently from multiple threads. 25887255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert * Functions that alter the state of a DateIntervalFormat object (setters) 25987255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert * may not be used concurrently with any other functions. 26087255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert * 2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class DateIntervalFormat extends UFormat { 2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final long serialVersionUID = 1; 2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Used to save the information for a skeleton's best match skeleton. 2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It is package accessible since it is used in DateIntervalInfo too. 2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final class BestMatchInfo { 2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the best match skeleton 2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert final String bestMatchSkeleton; 2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 0 means the best matched skeleton is the same as input skeleton 2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 1 means the fields are the same, but field width are different 2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 2 means the only difference between fields are v/z, 2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // -1 means there are other fields difference 2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert final int bestMatchDistanceInfo; 2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert BestMatchInfo(String bestSkeleton, int difference) { 2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestMatchSkeleton = bestSkeleton; 2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestMatchDistanceInfo = difference; 2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Used to save the information on a skeleton and its best match. 2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final class SkeletonAndItsBestMatch { 2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert final String skeleton; 2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert final String bestMatchSkeleton; 2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert SkeletonAndItsBestMatch(String skeleton, String bestMatch) { 2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.skeleton = skeleton; 2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestMatchSkeleton = bestMatch; 2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Cache for the locale interval pattern 3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static ICUCache<String, Map<String, PatternInfo>> LOCAL_PATTERN_CACHE = 3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert new SimpleCache<String, Map<String, PatternInfo>>(); 3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The interval patterns for this locale. 3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private DateIntervalInfo fInfo; 3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 31087255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert * The DateFormat object used to format single pattern. 31187255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert * Because fDateFormat is modified during format operations, all 31287255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert * access to it from logically const, thread safe functions must be synchronized. 3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private SimpleDateFormat fDateFormat; 3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The 2 calendars with the from and to date. 3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * could re-use the calendar in fDateFormat, 3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * but keeping 2 calendars make it clear and clean. 32087255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert * Because these Calendars are modified during format operations, all 32187255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert * access to them from logically const, thread safe functions must be synchronized. 3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Calendar fFromCalendar; 3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Calendar fToCalendar; 3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Following are transient interval information 328bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * relevant (locale) to this formatter. 3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String fSkeleton = null; 3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Needed for efficient deserialization. If set, it means we can use the 3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * cache to initialize fIntervalPatterns. 3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean isDateIntervalInfoDefault; 3377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Interval patterns for this instance's locale. 3407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient Map<String, PatternInfo> fIntervalPatterns = null; 342bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 343bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert /* 344bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Patterns for fallback formatting. 345bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert */ 346bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private String fDatePattern = null; 347bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private String fTimePattern = null; 348bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private String fDateTimeFormat = null; 3497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * default constructor; private because we don't want anyone to use 3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @SuppressWarnings("unused") 3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private DateIntervalFormat() { 3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Construct a DateIntervalFormat from DateFormat, 3607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * a DateIntervalInfo, and skeleton. 3617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateFormat provides the timezone, calendar, 3627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * full pattern, and date format symbols information. 3637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It should be a SimpleDateFormat object which 3647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * has a pattern in it. 3657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the DateIntervalInfo provides the interval patterns. 3667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param skeleton the skeleton of the date formatter 3687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dtItvInfo the DateIntervalInfo object to be adopted. 3697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param simpleDateFormat will be used for formatting 3707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 3727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 3737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 3757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public DateIntervalFormat(String skeleton, DateIntervalInfo dtItvInfo, 3767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert SimpleDateFormat simpleDateFormat) 3777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 3787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fDateFormat = simpleDateFormat; 3797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // freeze date interval info 3807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dtItvInfo.freeze(); 3817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fSkeleton = skeleton; 3827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fInfo = dtItvInfo; 3837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert isDateIntervalInfoDefault = false; 3847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fFromCalendar = (Calendar) fDateFormat.getCalendar().clone(); 3857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fToCalendar = (Calendar) fDateFormat.getCalendar().clone(); 3867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initializePattern(null); 3877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private DateIntervalFormat(String skeleton, ULocale locale, 3907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert SimpleDateFormat simpleDateFormat) 3917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 3927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fDateFormat = simpleDateFormat; 3937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fSkeleton = skeleton; 3947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fInfo = new DateIntervalInfo(locale).freeze(); 3957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert isDateIntervalInfoDefault = true; 3967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fFromCalendar = (Calendar) fDateFormat.getCalendar().clone(); 3977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fToCalendar = (Calendar) fDateFormat.getCalendar().clone(); 3987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initializePattern(LOCAL_PATTERN_CACHE); 3997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert} 4007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 4037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Construct a DateIntervalFormat from skeleton and the default <code>FORMAT</code> locale. 4047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This is a convenient override of 4067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * getInstance(String skeleton, ULocale locale) 4077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * with the value of locale as default <code>FORMAT</code> locale. 4087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param skeleton the skeleton on which interval format based. 4107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return a date time interval formatter. 4117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see Category#FORMAT 4127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 4137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final DateIntervalFormat 4157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert getInstance(String skeleton) 4167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 4187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return getInstance(skeleton, ULocale.getDefault(Category.FORMAT)); 4197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 4237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Construct a DateIntervalFormat from skeleton and a given locale. 4247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This is a convenient override of 4267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * getInstance(String skeleton, ULocale locale) 4277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Example code:{@.jcite com.ibm.icu.samples.text.dateintervalformat.DateIntervalFormatSample:---dtitvfmtPreDefinedExample} 4297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param skeleton the skeleton on which interval format based. 4307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param locale the given locale 4317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return a date time interval formatter. 4327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 4337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final DateIntervalFormat 4357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert getInstance(String skeleton, Locale locale) 4367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 4377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return getInstance(skeleton, ULocale.forLocale(locale)); 4387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 4427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Construct a DateIntervalFormat from skeleton and a given locale. 4437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 4447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * In this factory method, 4457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the date interval pattern information is load from resource files. 4467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Users are encouraged to created date interval formatter this way and 4477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to use the pre-defined skeleton macros. 4487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 4507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * There are pre-defined skeletons in DateFormat, 4517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * such as MONTH_DAY, YEAR_MONTH_WEEKDAY_DAY etc. 4527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Those skeletons have pre-defined interval patterns in resource files. 4547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Users are encouraged to use them. 4557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example: 4567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateIntervalFormat.getInstance(DateFormat.MONTH_DAY, false, loc); 4577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The given Locale provides the interval patterns. 4597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, for en_GB, if skeleton is YEAR_ABBR_MONTH_WEEKDAY_DAY, 4607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * which is "yMMMEEEd", 4617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the interval patterns defined in resource file to above skeleton are: 4627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "EEE, d MMM, yyyy - EEE, d MMM, yyyy" for year differs, 4637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "EEE, d MMM - EEE, d MMM, yyyy" for month differs, 4647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "EEE, d - EEE, d MMM, yyyy" for day differs, 4657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param skeleton the skeleton on which interval format based. 4667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param locale the given locale 4677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return a date time interval formatter. 4687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 4697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final DateIntervalFormat 4717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert getInstance(String skeleton, ULocale locale) 4727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 4737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateTimePatternGenerator generator = DateTimePatternGenerator.getInstance(locale); 4747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new DateIntervalFormat(skeleton, locale, new SimpleDateFormat(generator.getBestPattern(skeleton), locale)); 4757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 4807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Construct a DateIntervalFormat from skeleton 4817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateIntervalInfo, and the default <code>FORMAT</code> locale. 4827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This is a convenient override of 4847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * getInstance(String skeleton, ULocale locale, DateIntervalInfo dtitvinf) 4857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * with the locale value as default <code>FORMAT</code> locale. 4867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param skeleton the skeleton on which interval format based. 4887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dtitvinf the DateIntervalInfo object to be adopted. 4897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return a date time interval formatter. 4907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see Category#FORMAT 4917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 4927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final DateIntervalFormat getInstance(String skeleton, 4947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalInfo dtitvinf) 4957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 4967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return getInstance(skeleton, ULocale.getDefault(Category.FORMAT), dtitvinf); 4977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Construct a DateIntervalFormat from skeleton 5037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * a DateIntervalInfo, and the given locale. 5047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This is a convenient override of 5067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * getInstance(String skeleton, ULocale locale, DateIntervalInfo dtitvinf) 5077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Example code:{@.jcite com.ibm.icu.samples.text.dateintervalformat.DateIntervalFormatSample:---dtitvfmtCustomizedExample} 5097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param skeleton the skeleton on which interval format based. 5107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param locale the given locale 5117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dtitvinf the DateIntervalInfo object to be adopted. 5127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return a date time interval formatter. 5137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 5147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final DateIntervalFormat getInstance(String skeleton, 5167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Locale locale, 5177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalInfo dtitvinf) 5187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 5197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return getInstance(skeleton, ULocale.forLocale(locale), dtitvinf); 5207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Construct a DateIntervalFormat from skeleton 5267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * a DateIntervalInfo, and the given locale. 5277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 5297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * In this factory method, user provides its own date interval pattern 5307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * information, instead of using those pre-defined data in resource file. 5317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This factory method is for powerful users who want to provide their own 5327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * interval patterns. 5337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 5357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * There are pre-defined skeleton in DateFormat, 5367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * such as MONTH_DAY, YEAR_MONTH_WEEKDAY_DAY etc. 5377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Those skeletons have pre-defined interval patterns in resource files. 5397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Users are encouraged to use them. 5407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example: 5417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateIntervalFormat.getInstance(DateFormat.MONTH_DAY, false, loc,itvinf); 5427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the DateIntervalInfo provides the interval patterns. 5447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * User are encouraged to set default interval pattern in DateIntervalInfo 5467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * as well, if they want to set other interval patterns ( instead of 5477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * reading the interval patterns from resource files). 5487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * When the corresponding interval pattern for a largest calendar different 5497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * field is not found ( if user not set it ), interval format fallback to 5507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the default interval pattern. 5517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If user does not provide default interval pattern, it fallback to 5527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "{date0} - {date1}" 5537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param skeleton the skeleton on which interval format based. 5557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param locale the given locale 5567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dtitvinf the DateIntervalInfo object to be adopted. 5577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return a date time interval formatter. 5587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 5597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final DateIntervalFormat getInstance(String skeleton, 5617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ULocale locale, 5627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalInfo dtitvinf) 5637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 5647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // clone. If it is frozen, clone returns itself, otherwise, clone 5657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // returns a copy. 5667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dtitvinf = (DateIntervalInfo)dtitvinf.clone(); 5677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateTimePatternGenerator generator = DateTimePatternGenerator.getInstance(locale); 5687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new DateIntervalFormat(skeleton, dtitvinf, new SimpleDateFormat(generator.getBestPattern(skeleton), locale)); 5697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Clone this Format object polymorphically. 5747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return A copy of the object. 5757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 5767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 57787255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert public synchronized Object clone() 5787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 5797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalFormat other = (DateIntervalFormat) super.clone(); 5807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert other.fDateFormat = (SimpleDateFormat) fDateFormat.clone(); 5817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert other.fInfo = (DateIntervalInfo) fInfo.clone(); 5827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert other.fFromCalendar = (Calendar) fFromCalendar.clone(); 5837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert other.fToCalendar = (Calendar) fToCalendar.clone(); 584bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert other.fDatePattern = fDatePattern; 585bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert other.fTimePattern = fTimePattern; 586bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert other.fDateTimeFormat = fDateTimeFormat; 5877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return other; 5887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Format an object to produce a string. This method handles Formattable 5937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * objects with a DateInterval type. 5947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If a the Formattable object type is not a DateInterval, 5957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * IllegalArgumentException is thrown. 5967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param obj The object to format. 5987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Must be a DateInterval. 5997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param appendTo Output parameter to receive result. 6007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Result is appended to existing contents. 6017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param fieldPosition On input: an alignment field, if desired. 6027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * On output: the offsets of the alignment field. 603bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * There may be multiple instances of a given field type 604bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * in an interval format; in this case the fieldPosition 605bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * offsets refer to the first instance. 6067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return Reference to 'appendTo' parameter. 6077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if the formatted object is not 6087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateInterval object 6097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 6107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public final StringBuffer 6127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert format(Object obj, StringBuffer appendTo, FieldPosition fieldPosition) 6137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 6147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( obj instanceof DateInterval ) { 6157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return format( (DateInterval)obj, appendTo, fieldPosition); 6167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert else { 6187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Cannot format given Object (" + obj.getClass().getName() + ") as a DateInterval"); 6197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 6237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Format a DateInterval to produce a string. 6247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dtInterval DateInterval to be formatted. 6267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param appendTo Output parameter to receive result. 6277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Result is appended to existing contents. 6287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param fieldPosition On input: an alignment field, if desired. 6297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * On output: the offsets of the alignment field. 630bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * There may be multiple instances of a given field type 631bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * in an interval format; in this case the fieldPosition 632bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * offsets refer to the first instance. 6337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return Reference to 'appendTo' parameter. 6347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 6357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 63687255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert public final synchronized StringBuffer format(DateInterval dtInterval, 6377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuffer appendTo, 6387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition fieldPosition) 6397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 6407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fFromCalendar.setTimeInMillis(dtInterval.getFromDate()); 6417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fToCalendar.setTimeInMillis(dtInterval.getToDate()); 6427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return format(fFromCalendar, fToCalendar, appendTo, fieldPosition); 6437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 6467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 6477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 6487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 6507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String getPatterns(Calendar fromCalendar, 6517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar toCalendar, 6527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Output<String> part2) { 6537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // First, find the largest different calendar field. 6547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int field; 6557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( fromCalendar.get(Calendar.ERA) != toCalendar.get(Calendar.ERA) ) { 6567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert field = Calendar.ERA; 6577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( fromCalendar.get(Calendar.YEAR) != 6587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert toCalendar.get(Calendar.YEAR) ) { 6597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert field = Calendar.YEAR; 6607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( fromCalendar.get(Calendar.MONTH) != 6617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert toCalendar.get(Calendar.MONTH) ) { 6627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert field = Calendar.MONTH; 6637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( fromCalendar.get(Calendar.DATE) != 6647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert toCalendar.get(Calendar.DATE) ) { 6657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert field = Calendar.DATE; 6667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( fromCalendar.get(Calendar.AM_PM) != 6677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert toCalendar.get(Calendar.AM_PM) ) { 6687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert field = Calendar.AM_PM; 6697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( fromCalendar.get(Calendar.HOUR) != 6707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert toCalendar.get(Calendar.HOUR) ) { 6717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert field = Calendar.HOUR; 6727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( fromCalendar.get(Calendar.MINUTE) != 6737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert toCalendar.get(Calendar.MINUTE) ) { 6747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert field = Calendar.MINUTE; 675bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if ( fromCalendar.get(Calendar.SECOND) != 676bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert toCalendar.get(Calendar.SECOND) ) { 677bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert field = Calendar.SECOND; 6787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 6797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 6807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternInfo intervalPattern = fIntervalPatterns.get( 6827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalInfo.CALENDAR_FIELD_TO_PATTERN_LETTER[field]); 6837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert part2.value = intervalPattern.getSecondPart(); 6847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return intervalPattern.getFirstPart(); 6857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 6877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Format 2 Calendars to produce a string. 6887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param fromCalendar calendar set to the from date in date interval 6907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to be formatted into date interval string 6917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param toCalendar calendar set to the to date in date interval 6927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to be formatted into date interval string 6937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param appendTo Output parameter to receive result. 6947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Result is appended to existing contents. 6957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pos On input: an alignment field, if desired. 6967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * On output: the offsets of the alignment field. 697bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * There may be multiple instances of a given field type 698bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * in an interval format; in this case the fieldPosition 699bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * offsets refer to the first instance. 7007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return Reference to 'appendTo' parameter. 7017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if the two calendars are not equivalent. 7027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 7037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 70487255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert public final synchronized StringBuffer format(Calendar fromCalendar, 7057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar toCalendar, 7067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuffer appendTo, 7077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition pos) 7087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 7097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // not support different calendar types and time zones 7107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( !fromCalendar.isEquivalentTo(toCalendar) ) { 7117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("can not format on two different calendars"); 7127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // First, find the largest different calendar field. 7157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int field = -1; //init with an invalid value. 7167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( fromCalendar.get(Calendar.ERA) != toCalendar.get(Calendar.ERA) ) { 7187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert field = Calendar.ERA; 7197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( fromCalendar.get(Calendar.YEAR) != 7207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert toCalendar.get(Calendar.YEAR) ) { 7217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert field = Calendar.YEAR; 7227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( fromCalendar.get(Calendar.MONTH) != 7237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert toCalendar.get(Calendar.MONTH) ) { 7247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert field = Calendar.MONTH; 7257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( fromCalendar.get(Calendar.DATE) != 7267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert toCalendar.get(Calendar.DATE) ) { 7277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert field = Calendar.DATE; 7287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( fromCalendar.get(Calendar.AM_PM) != 7297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert toCalendar.get(Calendar.AM_PM) ) { 7307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert field = Calendar.AM_PM; 7317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( fromCalendar.get(Calendar.HOUR) != 7327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert toCalendar.get(Calendar.HOUR) ) { 7337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert field = Calendar.HOUR; 7347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( fromCalendar.get(Calendar.MINUTE) != 7357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert toCalendar.get(Calendar.MINUTE) ) { 7367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert field = Calendar.MINUTE; 737bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if ( fromCalendar.get(Calendar.SECOND) != 738bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert toCalendar.get(Calendar.SECOND) ) { 739bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert field = Calendar.SECOND; 740bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else { 741bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert /* ignore the millisecond etc. small fields' difference. 7427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * use single date when all the above are the same. 7437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 7447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return fDateFormat.format(fromCalendar, appendTo, pos); 7457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 746bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert boolean fromToOnSameDay = (field==Calendar.AM_PM || field==Calendar.HOUR || field==Calendar.MINUTE || field==Calendar.SECOND); 7477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // get interval pattern 7497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternInfo intervalPattern = fIntervalPatterns.get( 7507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalInfo.CALENDAR_FIELD_TO_PATTERN_LETTER[field]); 7517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( intervalPattern == null ) { 7537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( fDateFormat.isFieldUnitIgnored(field) ) { 7547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* the largest different calendar field is small than 7557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the smallest calendar field in pattern, 7567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * return single date format. 7577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 7587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return fDateFormat.format(fromCalendar, appendTo, pos); 7597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 761bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return fallbackFormat(fromCalendar, toCalendar, fromToOnSameDay, appendTo, pos); 7627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If the first part in interval pattern is empty, 7657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the 2nd part of it saves the full-pattern used in fall-back. 7667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // For a 'real' interval pattern, the first part will never be empty. 7677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( intervalPattern.getFirstPart() == null ) { 7687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // fall back 769bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return fallbackFormat(fromCalendar, toCalendar, fromToOnSameDay, appendTo, pos, 7707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPattern.getSecondPart()); 7717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar firstCal; 7737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar secondCal; 7747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( intervalPattern.firstDateInPtnIsLaterDate() ) { 7757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert firstCal = toCalendar; 7767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert secondCal = fromCalendar; 7777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 7787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert firstCal = fromCalendar; 7797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert secondCal = toCalendar; 7807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // break the interval pattern into 2 parts 7827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // first part should not be empty, 7837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String originalPattern = fDateFormat.toPattern(); 7847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fDateFormat.applyPattern(intervalPattern.getFirstPart()); 7857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fDateFormat.format(firstCal, appendTo, pos); 7867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( intervalPattern.getSecondPart() != null ) { 7877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fDateFormat.applyPattern(intervalPattern.getSecondPart()); 788bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert FieldPosition otherPos = new FieldPosition(pos.getField()); 789bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert fDateFormat.format(secondCal, appendTo, otherPos); 790bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (pos.getEndIndex() == 0 && otherPos.getEndIndex() > 0) { 7912d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert pos.setBeginIndex(otherPos.getBeginIndex()); 7922d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert pos.setEndIndex(otherPos.getEndIndex()); 793bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 7947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fDateFormat.applyPattern(originalPattern); 7967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return appendTo; 7977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 799bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private void adjustPosition(String combiningPattern, // has {0} and {1} in it 800bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String pat0, FieldPosition pos0, // pattern and pos corresponding to {0} 801bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String pat1, FieldPosition pos1, // pattern and pos corresponding to {1} 802bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert FieldPosition posResult) { 803bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int index0 = combiningPattern.indexOf("{0}"); 804bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int index1 = combiningPattern.indexOf("{1}"); 805bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (index0 < 0 || index1 < 0) { 806bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return; 807bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 808bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int placeholderLen = 3; // length of "{0}" or "{1}" 809bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (index0 < index1) { 810bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (pos0.getEndIndex() > 0) { 811bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert posResult.setBeginIndex(pos0.getBeginIndex() + index0); 812bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert posResult.setEndIndex(pos0.getEndIndex() + index0); 813bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (pos1.getEndIndex() > 0) { 814bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // here index1 >= 3 815bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert index1 += pat0.length() - placeholderLen; // adjust for pat0 replacing {0} 816bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert posResult.setBeginIndex(pos1.getBeginIndex() + index1); 817bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert posResult.setEndIndex(pos1.getEndIndex() + index1); 818bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 819bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else { 820bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (pos1.getEndIndex() > 0) { 821bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert posResult.setBeginIndex(pos1.getBeginIndex() + index1); 822bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert posResult.setEndIndex(pos1.getEndIndex() + index1); 823bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (pos0.getEndIndex() > 0) { 824bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // here index0 >= 3 825bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert index0 += pat1.length() - placeholderLen; // adjust for pat1 replacing {1} 826bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert posResult.setBeginIndex(pos0.getBeginIndex() + index0); 827bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert posResult.setEndIndex(pos0.getEndIndex() + index0); 828bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 829bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 830bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 8317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 8337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Format 2 Calendars to using fall-back interval pattern 8347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 8357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The full pattern used in this fall-back format is the 8367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * full pattern of the date formatter. 8377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 8387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param fromCalendar calendar set to the from date in date interval 8397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to be formatted into date interval string 8407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param toCalendar calendar set to the to date in date interval 8417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to be formatted into date interval string 8427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param appendTo Output parameter to receive result. 8437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Result is appended to existing contents. 8447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pos On input: an alignment field, if desired. 8457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * On output: the offsets of the alignment field. 8467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return Reference to 'appendTo' parameter. 8477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private final StringBuffer fallbackFormat(Calendar fromCalendar, 8497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar toCalendar, 850bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert boolean fromToOnSameDay, 8517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuffer appendTo, 8527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition pos) { 853bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String fullPattern = null; // for saving the pattern in fDateFormat 854bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert boolean formatDatePlusTimeRange = (fromToOnSameDay && fDatePattern != null && fTimePattern != null); 8557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the fall back 856bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (formatDatePlusTimeRange) { 857bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert fullPattern = fDateFormat.toPattern(); // save current pattern, restore later 858bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert fDateFormat.applyPattern(fTimePattern); 859bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 860bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert FieldPosition otherPos = new FieldPosition(pos.getField()); 8617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuffer earlierDate = new StringBuffer(64); 8627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert earlierDate = fDateFormat.format(fromCalendar, earlierDate, pos); 8637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuffer laterDate = new StringBuffer(64); 864bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert laterDate = fDateFormat.format(toCalendar, laterDate, otherPos); 8657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String fallbackPattern = fInfo.getFallbackIntervalPattern(); 866bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert adjustPosition(fallbackPattern, earlierDate.toString(), pos, laterDate.toString(), otherPos, pos); 86787255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert String fallbackRange = SimpleFormatterImpl.formatRawPattern( 86887255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert fallbackPattern, 2, 2, earlierDate, laterDate); 869bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (formatDatePlusTimeRange) { 870bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // fallbackRange has just the time range, need to format the date part and combine that 871bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert fDateFormat.applyPattern(fDatePattern); 872bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert StringBuffer datePortion = new StringBuffer(64); 873bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert otherPos.setBeginIndex(0); 874bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert otherPos.setEndIndex(0); 875bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert datePortion = fDateFormat.format(fromCalendar, datePortion, otherPos); 876bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert adjustPosition(fDateTimeFormat, fallbackRange, pos, datePortion.toString(), otherPos, pos); 877a76563514e312656c9833550299569b1964a7448Felipe BalbontÃn // Android patch (CLDR ticket #10321) begin. 878a76563514e312656c9833550299569b1964a7448Felipe BalbontÃn MessageFormat msgFmt = new MessageFormat(""); 879a76563514e312656c9833550299569b1964a7448Felipe BalbontÃn msgFmt.applyPattern(fDateTimeFormat, MessagePattern.ApostropheMode.DOUBLE_REQUIRED); 880a76563514e312656c9833550299569b1964a7448Felipe BalbontÃn StringBuffer fallbackRangeBuffer = new StringBuffer(128); 881a76563514e312656c9833550299569b1964a7448Felipe BalbontÃn fallbackRange = msgFmt.format(new Object[] { fallbackRange, datePortion }, 882a76563514e312656c9833550299569b1964a7448Felipe BalbontÃn fallbackRangeBuffer, new FieldPosition(0)).toString(); 883a76563514e312656c9833550299569b1964a7448Felipe BalbontÃn // Android patch (CLDR ticket #10321) end. 884bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 885bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert appendTo.append(fallbackRange); 886bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (formatDatePlusTimeRange) { 887bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // restore full pattern 888bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert fDateFormat.applyPattern(fullPattern); 889bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 8907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return appendTo; 8917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 8957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Format 2 Calendars to using fall-back interval pattern 8967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 8977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This fall-back pattern is generated on a given full pattern, 8987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * not the full pattern of the date formatter. 8997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 9007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param fromCalendar calendar set to the from date in date interval 9017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to be formatted into date interval string 9027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param toCalendar calendar set to the to date in date interval 9037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to be formatted into date interval string 9047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param appendTo Output parameter to receive result. 9057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Result is appended to existing contents. 9067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pos On input: an alignment field, if desired. 9077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * On output: the offsets of the alignment field. 9087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param fullPattern the full pattern need to apply to date formatter 9097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return Reference to 'appendTo' parameter. 9107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private final StringBuffer fallbackFormat(Calendar fromCalendar, 9127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar toCalendar, 913bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert boolean fromToOnSameDay, 9147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuffer appendTo, 9157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition pos, 9167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String fullPattern) { 9177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String originalPattern = fDateFormat.toPattern(); 9187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fDateFormat.applyPattern(fullPattern); 919bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert fallbackFormat(fromCalendar, toCalendar, fromToOnSameDay, appendTo, pos); 9207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fDateFormat.applyPattern(originalPattern); 9217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return appendTo; 9227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Date interval parsing is not supported. 9277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 9287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This method should handle parsing of 9297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * date time interval strings into Formattable objects with 9307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateInterval type, which is a pair of UDate. 9317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 9327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Before calling, set parse_pos.index to the offset you want to start 9337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * parsing at in the source. After calling, parse_pos.index is the end of 9347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the text you parsed. If error occurs, index is unchanged. 9357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 9367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * When parsing, leading whitespace is discarded (with a successful parse), 9377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * while trailing whitespace is left as is. 9387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <P> 9397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * See Format.parseObject() for more. 9407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 9417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param source The string to be parsed into an object. 9427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param parse_pos The position to start parsing at. Since no parsing 9437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is supported, upon return this param is unchanged. 9447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return A newly created Formattable* object, or NULL 9457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * on failure. 9467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 9477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 9487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 9507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Object parseObject(String source, ParsePosition parse_pos) 9517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 9527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new UnsupportedOperationException("parsing is not supported"); 9537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Gets the date time interval patterns. 9587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return a copy of the date time interval patterns associated with 9597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * this date interval formatter. 9607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 9617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public DateIntervalInfo getDateIntervalInfo() 9637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 9647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (DateIntervalInfo)fInfo.clone(); 9657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Set the date time interval patterns. 9707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param newItvPattern the given interval patterns to copy. 9717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 9727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setDateIntervalInfo(DateIntervalInfo newItvPattern) 9747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 9757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // clone it. If it is frozen, the clone returns itself. 9767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Otherwise, clone returns a copy 9777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fInfo = (DateIntervalInfo)newItvPattern.clone(); 9787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.isDateIntervalInfoDefault = false; 9797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fInfo.freeze(); // freeze it 9807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( fDateFormat != null ) { 9817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initializePattern(null); 9827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Get the TimeZone 9877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return A copy of the TimeZone associated with this date interval formatter. 988f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * @stable ICU 53 9897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public TimeZone getTimeZone() 9917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 9927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( fDateFormat != null ) { 9937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Here we clone, like other getters here, but unlike 9947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // DateFormat.getTimeZone() and Calendar.getTimeZone() 9957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // which return the TimeZone from the Calendar's zone variable 9967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (TimeZone)(fDateFormat.getTimeZone().clone()); 9977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If fDateFormat is null (unexpected), return default timezone. 9997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return TimeZone.getDefault(); 10007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 10047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Set the TimeZone for the calendar used by this DateIntervalFormat object. 10057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param zone The new TimeZone, will be cloned for use by this DateIntervalFormat. 1006f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * @stable ICU 53 10077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 10087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setTimeZone(TimeZone zone) 10097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 10107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // zone is cloned once for all three usages below: 10117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert TimeZone zoneToSet = (TimeZone)zone.clone(); 10127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fDateFormat != null) { 10137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fDateFormat.setTimeZone(zoneToSet); 10147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // fDateFormat has the master calendar for the DateIntervalFormat; 10167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // fFromCalendar and fToCalendar are internal work clones of that calendar. 10177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fFromCalendar != null) { 10187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fFromCalendar.setTimeZone(zoneToSet); 10197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fToCalendar != null) { 10217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fToCalendar.setTimeZone(zoneToSet); 10227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 10267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Gets the date formatter 10277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return a copy of the date formatter associated with 10287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * this date interval formatter. 10297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 10307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 103187255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert public synchronized DateFormat getDateFormat() 10327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 10337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (DateFormat)fDateFormat.clone(); 10347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 10387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Below are for generating interval patterns locale to the formatter 10397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 10407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 10427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Initialize interval patterns locale to this formatter. 10437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 10447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void initializePattern(ICUCache<String, Map<String, PatternInfo>> cache) { 10457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String fullPattern = fDateFormat.toPattern(); 10467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ULocale locale = fDateFormat.getLocale(); 10477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String key = null; 10487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Map<String, PatternInfo> patterns = null; 10497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (cache != null) { 10507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( fSkeleton != null ) { 10517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert key = locale.toString() + "+" + fullPattern + "+" + fSkeleton; 10527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 10537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert key = locale.toString() + "+" + fullPattern; 10547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patterns = cache.get(key); 10567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (patterns == null) { 10587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Map<String, PatternInfo> intervalPatterns = initializeIntervalPattern(fullPattern, locale); 10597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patterns = Collections.unmodifiableMap(intervalPatterns); 10607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (cache != null) { 10617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cache.put(key, patterns); 10627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fIntervalPatterns = patterns; 10657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 10707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Initialize interval patterns locale to this formatter 10717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 10727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This code is a bit complicated since 10737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1. the interval patterns saved in resource bundle files are interval 10747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * patterns based on date or time only. 10757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It does not have interval patterns based on both date and time. 10767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Interval patterns on both date and time are algorithm generated. 10777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 10787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, it has interval patterns on skeleton "dMy" and "hm", 10797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * but it does not have interval patterns on skeleton "dMyhm". 10807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 10817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The rule to generate interval patterns for both date and time skeleton are 10827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1) when the year, month, or day differs, concatenate the two original 10837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * expressions with a separator between, 10847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, interval pattern from "Jan 10, 2007 10:10 am" 10857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to "Jan 11, 2007 10:10am" is 10867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "Jan 10, 2007 10:10 am - Jan 11, 2007 10:10am" 10877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 10887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2) otherwise, present the date followed by the range expression 10897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for the time. 10907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, interval pattern from "Jan 10, 2007 10:10 am" 10917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to "Jan 10, 2007 11:10am" is 10927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "Jan 10, 2007 10:10 am - 11:10am" 10937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 10947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2. even a pattern does not request a certain calendar field, 10957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the interval pattern needs to include such field if such fields are 10967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * different between 2 dates. 10977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, a pattern/skeleton is "hm", but the interval pattern 10987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * includes year, month, and date when year, month, and date differs. 10997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 11007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 11017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param fullPattern formatter's full pattern 11027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param locale the given locale. 11037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return interval patterns' hash map 11047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 11057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Map<String, PatternInfo> initializeIntervalPattern(String fullPattern, ULocale locale) { 11067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateTimePatternGenerator dtpng = DateTimePatternGenerator.getInstance(locale); 11077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( fSkeleton == null ) { 11087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // fSkeleton is already set by getDateIntervalInstance() 11097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // or by getInstance(String skeleton, .... ) 11107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fSkeleton = dtpng.getSkeleton(fullPattern); 11117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String skeleton = fSkeleton; 11137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert HashMap<String, PatternInfo> intervalPatterns = new HashMap<String, PatternInfo>(); 11157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* Check whether the skeleton is a combination of date and time. 11177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For the complication reason 1 explained above. 11187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 11197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder date = new StringBuilder(skeleton.length()); 11207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder normalizedDate = new StringBuilder(skeleton.length()); 11217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder time = new StringBuilder(skeleton.length()); 11227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder normalizedTime = new StringBuilder(skeleton.length()); 11237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* the difference between time skeleton and normalizedTimeSkeleton are: 11257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1. (Formerly, normalized time skeleton folded 'H' to 'h'; no longer true) 11267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2. 'a' is omitted in normalized time skeleton. 11277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3. there is only one appearance for 'h', 'm','v', 'z' in normalized 11287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * time skeleton 11297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 11307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The difference between date skeleton and normalizedDateSkeleton are: 11317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1. both 'y' and 'd' appear only once in normalizeDateSkeleton 11327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2. 'E' and 'EE' are normalized into 'EEE' 11337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3. 'MM' is normalized into 'M' 11347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 11357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert getDateTimeSkeleton(skeleton, date, normalizedDate, 11367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert time, normalizedTime); 11377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String dateSkeleton = date.toString(); 11397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String timeSkeleton = time.toString(); 11407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String normalizedDateSkeleton = normalizedDate.toString(); 11417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String normalizedTimeSkeleton = normalizedTime.toString(); 11427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1143bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // move this up here since we need it for fallbacks 1144bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (time.length() != 0 && date.length() != 0) { 11452d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert // Need the Date/Time pattern for concatenating the date with 1146bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // the time interval. 1147bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // The date/time pattern ( such as {0} {1} ) is saved in 1148bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // calendar, that is why need to get the CalendarData here. 11492d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert fDateTimeFormat = getConcatenationPattern(locale); 1150bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 1151bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 11527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean found = genSeparateDateTimePtn(normalizedDateSkeleton, 11537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert normalizedTimeSkeleton, 1154bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert intervalPatterns, dtpng); 11557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1156bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // for skeletons with seconds, found is false and we enter this block 11577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( found == false ) { 11587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // use fallback 11597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // TODO: if user asks "m", but "d" differ 11607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //StringBuffer skeleton = new StringBuffer(skeleton); 11617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( time.length() != 0 ) { 11627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //genFallbackForNotFound(Calendar.MINUTE, skeleton); 11637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //genFallbackForNotFound(Calendar.HOUR, skeleton); 11647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //genFallbackForNotFound(Calendar.AM_PM, skeleton); 11657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( date.length() == 0 ) { 11667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // prefix with yMd 11677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeSkeleton = DateFormat.YEAR_NUM_MONTH_DAY + timeSkeleton; 11687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String pattern =dtpng.getBestPattern(timeSkeleton); 11697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // for fall back interval patterns, 11707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the first part of the pattern is empty, 11717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the second part of the pattern is the full-pattern 11727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // should be used in fall-back. 11737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternInfo ptn = new PatternInfo(null, pattern, 11747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fInfo.getDefaultOrder()); 11757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPatterns.put(DateIntervalInfo. 11767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.DATE], ptn); 11777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // share interval pattern 11787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPatterns.put(DateIntervalInfo. 11797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.MONTH], ptn); 11807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // share interval pattern 11817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPatterns.put(DateIntervalInfo. 11827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.YEAR], ptn); 11837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 11847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //genFallbackForNotFound(Calendar.DATE, skeleton); 11857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //genFallbackForNotFound(Calendar.MONTH, skeleton); 11867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //genFallbackForNotFound(Calendar.YEAR, skeleton); 11877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 11897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //genFallbackForNotFound(Calendar.DATE, skeleton); 11907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //genFallbackForNotFound(Calendar.MONTH, skeleton); 11917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //genFallbackForNotFound(Calendar.YEAR, skeleton); 11927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return intervalPatterns; 11947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } // end of skeleton not found 11957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // interval patterns for skeleton are found in resource 11967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( time.length() == 0 ) { 11977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // done 11987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( date.length() == 0 ) { 11997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // need to set up patterns for y/M/d differ 12007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* result from following looks confusing. 12017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for example: 10 10:10 - 11 10:10, it is not 12027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * clear that the first 10 is the 10th day 12037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert time.insert(0, 'd'); 12047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert genFallbackPattern(Calendar.DATE, time); 12057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert time.insert(0, 'M'); 12067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert genFallbackPattern(Calendar.MONTH, time); 12077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert time.insert(0, 'y'); 12087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert genFallbackPattern(Calendar.YEAR, time); 12097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 12107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // prefix with yMd 12117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeSkeleton = DateFormat.YEAR_NUM_MONTH_DAY + timeSkeleton; 12127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String pattern =dtpng.getBestPattern(timeSkeleton); 12137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // for fall back interval patterns, 12147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the first part of the pattern is empty, 12157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the second part of the pattern is the full-pattern 12167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // should be used in fall-back. 12177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternInfo ptn = new PatternInfo( 12187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert null, pattern, fInfo.getDefaultOrder()); 12197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPatterns.put(DateIntervalInfo. 12207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.DATE], ptn); 12217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPatterns.put(DateIntervalInfo. 12227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.MONTH], ptn); 12237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPatterns.put(DateIntervalInfo. 12247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.YEAR], ptn); 12257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 12267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* if both present, 12277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1) when the year, month, or day differs, 12287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * concatenate the two original expressions with a separator between, 12297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2) otherwise, present the date followed by the 12307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * range expression for the time. 12317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 12327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 12337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1) when the year, month, or day differs, 12347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * concatenate the two original expressions with a separator between, 12357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 12367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // if field exists, use fall back 12377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( !fieldExistsInSkeleton(Calendar.DATE, dateSkeleton) ) { 12387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // prefix skeleton with 'd' 12397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert skeleton = DateIntervalInfo. 12407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.DATE] + skeleton; 12417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert genFallbackPattern(Calendar.DATE, skeleton, intervalPatterns, dtpng); 12427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( !fieldExistsInSkeleton(Calendar.MONTH, dateSkeleton) ) { 12447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // then prefix skeleton with 'M' 12457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert skeleton = DateIntervalInfo. 12467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.MONTH] + skeleton; 12477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert genFallbackPattern(Calendar.MONTH, skeleton, intervalPatterns, dtpng); 12487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( !fieldExistsInSkeleton(Calendar.YEAR, dateSkeleton) ) { 12507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // then prefix skeleton with 'y' 12517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert skeleton = DateIntervalInfo. 12527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.YEAR] + skeleton; 12537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert genFallbackPattern(Calendar.YEAR, skeleton, intervalPatterns, dtpng); 12547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 12577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2) otherwise, present the date followed by the 12587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * range expression for the time. 12597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1260bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (fDateTimeFormat == null) { 1261bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert fDateTimeFormat = "{1} {0}"; 1262bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 12637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String datePattern =dtpng.getBestPattern(dateSkeleton); 1264bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert concatSingleDate2TimeInterval(fDateTimeFormat, datePattern, Calendar.AM_PM, intervalPatterns); 1265bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert concatSingleDate2TimeInterval(fDateTimeFormat, datePattern, Calendar.HOUR, intervalPatterns); 1266bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert concatSingleDate2TimeInterval(fDateTimeFormat, datePattern, Calendar.MINUTE, intervalPatterns); 12677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return intervalPatterns; 12707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12722d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert /** 12732d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert * Retrieves the concatenation DateTime pattern from the resource bundle. 12742d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert * @param locale Locale to retrieve. 12752d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert * @return Concatenation DateTime pattern. 12762d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert */ 12772d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert private String getConcatenationPattern(ULocale locale) { 12782d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, locale); 12792d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert ICUResourceBundle dtPatternsRb = rb.getWithFallback("calendar/gregorian/DateTimePatterns"); 12802d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert ICUResourceBundle concatenationPatternRb = (ICUResourceBundle) dtPatternsRb.get(8); 12812d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert if (concatenationPatternRb.getType() == UResourceBundle.STRING) { 12822d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert return concatenationPatternRb.getString(); 12832d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert } else { 12842d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert return concatenationPatternRb.getString(0); 12852d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert } 12862d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert } 12877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 12897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Generate fall back interval pattern given a calendar field, 12907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * a skeleton, and a date time pattern generator 12917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param field the largest different calendar field 12927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param skeleton a skeleton 12937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dtpng date time pattern generator 12947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param intervalPatterns interval patterns 12957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 12967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void genFallbackPattern(int field, String skeleton, 12977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Map<String, PatternInfo> intervalPatterns, 12987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateTimePatternGenerator dtpng) { 12997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String pattern = dtpng.getBestPattern(skeleton); 13007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // for fall back interval patterns, 13017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the first part of the pattern is empty, 13027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the second part of the pattern is the full-pattern 13037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // should be used in fall-back. 13047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternInfo ptn = new PatternInfo( 13057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert null, pattern, fInfo.getDefaultOrder()); 13067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPatterns.put( 13077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalInfo.CALENDAR_FIELD_TO_PATTERN_LETTER[field], ptn); 13087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 13137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void genFallbackForNotFound(String field, StringBuffer skeleton) { 13147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( SimpleDateFormat.isFieldUnitIgnored(skeleton.toString(), field) ) { 13157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // single date 13167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalInfo.PatternInfo ptnInfo = 13177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert new DateIntervalInfo.PatternInfo(null, fDateFormat.toPattern(), 13187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fInfo.getDefaultOrder()); 13197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fIntervalPatterns.put(field, ptnInfo); 13207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return; 13217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( skeleton.indexOf(field) == -1 ) { 13227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert skeleton.insert(0,field); 13237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert genFallbackPattern(field, skeleton, dtpng); 13247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 13277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 13297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * get separated date and time skeleton from a combined skeleton. 13307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 13317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The difference between date skeleton and normalizedDateSkeleton are: 13327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1. both 'y' and 'd' are appeared only once in normalizeDateSkeleton 13337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2. 'E' and 'EE' are normalized into 'EEE' 13347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3. 'MM' is normalized into 'M' 13357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 13367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ** the difference between time skeleton and normalizedTimeSkeleton are: 13377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1. both 'H' and 'h' are normalized as 'h' in normalized time skeleton, 13387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2. 'a' is omitted in normalized time skeleton. 13397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3. there is only one appearance for 'h', 'm','v', 'z' in normalized time 13407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * skeleton 13417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 13427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 13437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param skeleton given combined skeleton. 13447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param date Output parameter for date only skeleton. 13457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param normalizedDate Output parameter for normalized date only 13467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 13477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param time Output parameter for time only skeleton. 13487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param normalizedTime Output parameter for normalized time only 13497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * skeleton. 13507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 13517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static void getDateTimeSkeleton(String skeleton, 13527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder dateSkeleton, 13537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder normalizedDateSkeleton, 13547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder timeSkeleton, 13557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder normalizedTimeSkeleton) 13567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 13577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // dateSkeleton follows the sequence of y*M*E*d* 13587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // timeSkeleton follows the sequence of hm*[v|z]? 13597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int i; 13607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int ECount = 0; 13617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int dCount = 0; 13627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int MCount = 0; 13637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int yCount = 0; 13647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int hCount = 0; 13657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int HCount = 0; 13667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int mCount = 0; 13677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int vCount = 0; 13687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int zCount = 0; 13697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (i = 0; i < skeleton.length(); ++i) { 13717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char ch = skeleton.charAt(i); 13727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert switch ( ch ) { 13737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'E': 13747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dateSkeleton.append(ch); 13757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++ECount; 13767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 13777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'd': 13787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dateSkeleton.append(ch); 13797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++dCount; 13807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 13817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'M': 13827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dateSkeleton.append(ch); 13837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++MCount; 13847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 13857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'y': 13867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dateSkeleton.append(ch); 13877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++yCount; 13887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 13897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'G': 13907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'Y': 13917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'u': 13927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'Q': 13937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'q': 13947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'L': 13957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'l': 13967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'W': 13977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'w': 13987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'D': 13997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'F': 14007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'g': 14017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'e': 14027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'c': 1403f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert case 'U': 1404f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert case 'r': 14057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert normalizedDateSkeleton.append(ch); 14067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dateSkeleton.append(ch); 14077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 14087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'a': 14097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 'a' is implicitly handled 14107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeSkeleton.append(ch); 14117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 14127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'h': 14137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeSkeleton.append(ch); 14147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++hCount; 14157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 14167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'H': 14177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeSkeleton.append(ch); 14187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++HCount; 14197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 14207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'm': 14217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeSkeleton.append(ch); 14227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++mCount; 14237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 14247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'z': 14257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++zCount; 14267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeSkeleton.append(ch); 14277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 14287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'v': 14297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++vCount; 14307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeSkeleton.append(ch); 14317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 14327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'V': 14337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'Z': 14347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'k': 14357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'K': 14367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'j': 14377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 's': 14387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'S': 14397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 'A': 14407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeSkeleton.append(ch); 14417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert normalizedTimeSkeleton.append(ch); 14427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 14437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* generate normalized form for date*/ 14477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( yCount != 0 ) { 14487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (i = 0; i < yCount; i++) { 14497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert normalizedDateSkeleton.append('y'); 14507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( MCount != 0 ) { 14537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( MCount < 3 ) { 14547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert normalizedDateSkeleton.append('M'); 14557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 14567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( i = 0; i < MCount && i < 5; ++i ) { 14577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert normalizedDateSkeleton.append('M'); 14587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( ECount != 0 ) { 14627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( ECount <= 3 ) { 14637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert normalizedDateSkeleton.append('E'); 14647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 14657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( i = 0; i < ECount && i < 5; ++i ) { 14667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert normalizedDateSkeleton.append('E'); 14677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( dCount != 0 ) { 14717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert normalizedDateSkeleton.append('d'); 14727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* generate normalized form for time */ 14757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( HCount != 0 ) { 14767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert normalizedTimeSkeleton.append('H'); 14777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert else if ( hCount != 0 ) { 14797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert normalizedTimeSkeleton.append('h'); 14807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( mCount != 0 ) { 14827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert normalizedTimeSkeleton.append('m'); 14837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( zCount != 0 ) { 14857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert normalizedTimeSkeleton.append('z'); 14867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( vCount != 0 ) { 14887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert normalizedTimeSkeleton.append('v'); 14897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 14957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Generate date or time interval pattern from resource. 14967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 14977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It needs to handle the following: 14987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1. need to adjust field width. 14997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, the interval patterns saved in DateIntervalInfo 15007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * includes "dMMMy", but not "dMMMMy". 15017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Need to get interval patterns for dMMMMy from dMMMy. 15027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Another example, the interval patterns saved in DateIntervalInfo 15037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * includes "hmv", but not "hmz". 15047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Need to get interval patterns for "hmz' from 'hmv' 15057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 15067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2. there might be no pattern for 'y' differ for skeleton "Md", 15077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in order to get interval patterns for 'y' differ, 15087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * need to look for it from skeleton 'yMd' 15097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 15107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dateSkeleton normalized date skeleton 15117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param timeSkeleton normalized time skeleton 15127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param intervalPatterns interval patterns 15137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return whether there is interval patterns for the skeleton. 15147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * true if there is, false otherwise 15157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 15167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean genSeparateDateTimePtn(String dateSkeleton, 15177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String timeSkeleton, 1518bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert Map<String, PatternInfo> intervalPatterns, 1519bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert DateTimePatternGenerator dtpng) 15207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 15217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String skeleton; 15227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // if both date and time skeleton present, 15237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the final interval pattern might include time interval patterns 1524bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // ( when, am_pm, hour, minute, second differ ), 15257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // but not date interval patterns ( when year, month, day differ ). 15267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // For year/month/day differ, it falls back to fall-back pattern. 15277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( timeSkeleton.length() != 0 ) { 15287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert skeleton = timeSkeleton; 15297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 15307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert skeleton = dateSkeleton; 15317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* interval patterns for skeleton "dMMMy" (but not "dMMMMy") 15347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * are defined in resource, 15357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * interval patterns for skeleton "dMMMMy" are calculated by 15367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1. get the best match skeleton for "dMMMMy", which is "dMMMy" 15377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2. get the interval patterns for "dMMMy", 15387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3. extend "MMM" to "MMMM" in above interval patterns for "dMMMMy" 15397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * getBestSkeleton() is step 1. 15407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 15417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // best skeleton, and the difference information 15427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert BestMatchInfo retValue = fInfo.getBestSkeleton(skeleton); 15437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String bestSkeleton = retValue.bestMatchSkeleton; 15447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int differenceInfo = retValue.bestMatchDistanceInfo; 15457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1546bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // Set patterns for fallback use, need to do this 1547bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // before returning if differenceInfo == -1 1548bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (dateSkeleton.length() != 0 ) { 1549bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert fDatePattern = dtpng.getBestPattern(dateSkeleton); 1550bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 1551bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (timeSkeleton.length() != 0 ) { 1552bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert fTimePattern = dtpng.getBestPattern(timeSkeleton); 1553bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 1554bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 15557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // difference: 15567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 0 means the best matched skeleton is the same as input skeleton 15577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 1 means the fields are the same, but field width are different 15587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 2 means the only difference between fields are v/z, 15597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // -1 means there are other fields difference 1560bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // (this will happen, for instance, if the supplied skeleton has seconds, 1561bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // but no skeletons in the intervalFormats data do) 15627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( differenceInfo == -1 ) { 15637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // skeleton has different fields, not only v/z difference 15647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 15657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( timeSkeleton.length() == 0 ) { 15687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // only has date skeleton 15697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert genIntervalPattern(Calendar.DATE, skeleton, bestSkeleton, differenceInfo, intervalPatterns); 15707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert SkeletonAndItsBestMatch skeletons = genIntervalPattern( 15717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar.MONTH, skeleton, 15727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestSkeleton, differenceInfo, 15737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPatterns); 15747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( skeletons != null ) { 15757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestSkeleton = skeletons.skeleton; 15767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert skeleton = skeletons.bestMatchSkeleton; 15777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert genIntervalPattern(Calendar.YEAR, skeleton, bestSkeleton, differenceInfo, intervalPatterns); 15797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 15807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert genIntervalPattern(Calendar.MINUTE, skeleton, bestSkeleton, differenceInfo, intervalPatterns); 15817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert genIntervalPattern(Calendar.HOUR, skeleton, bestSkeleton, differenceInfo, intervalPatterns); 15827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert genIntervalPattern(Calendar.AM_PM, skeleton, bestSkeleton, differenceInfo, intervalPatterns); 15837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 15857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 15917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Generate interval pattern from existing resource 15927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 15937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It not only save the interval patterns, 15947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * but also return the skeleton and its best match skeleton. 15957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 15967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param field largest different calendar field 15977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param skeleton skeleton 15987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param bestSkeleton the best match skeleton which has interval pattern 15997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * defined in resource 16007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param differenceInfo the difference between skeleton and best skeleton 16017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 0 means the best matched skeleton is the same as input skeleton 16027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1 means the fields are the same, but field width are different 16037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2 means the only difference between fields are v/z, 16047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * -1 means there are other fields difference 16057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 16067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param intervalPatterns interval patterns 16077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 16087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return an extended skeleton or extended best skeleton if applicable. 16097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * null otherwise. 16107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 16117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private SkeletonAndItsBestMatch genIntervalPattern( 16127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int field, String skeleton, String bestSkeleton, 16137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int differenceInfo, Map<String, PatternInfo> intervalPatterns) { 16147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert SkeletonAndItsBestMatch retValue = null; 16157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternInfo pattern = fInfo.getIntervalPattern( 16167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestSkeleton, field); 16177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( pattern == null ) { 16187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // single date 16197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( SimpleDateFormat.isFieldUnitIgnored(bestSkeleton, field) ) { 16207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternInfo ptnInfo = 16217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert new PatternInfo(fDateFormat.toPattern(), 16227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert null, 16237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fInfo.getDefaultOrder()); 16247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPatterns.put(DateIntervalInfo. 16257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CALENDAR_FIELD_TO_PATTERN_LETTER[field], ptnInfo); 16267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 16277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 16297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // for 24 hour system, interval patterns in resource file 16307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // might not include pattern when am_pm differ, 16317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // which should be the same as hour differ. 16327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // add it here for simplicity 16337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( field == Calendar.AM_PM ) { 16347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pattern = fInfo.getIntervalPattern(bestSkeleton, 16357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar.HOUR); 16367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( pattern != null ) { 16377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // share 16387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPatterns.put(DateIntervalInfo. 16397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CALENDAR_FIELD_TO_PATTERN_LETTER[field], 16407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pattern); 16417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 16437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // else, looking for pattern when 'y' differ for 'dMMMM' skeleton, 16457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // first, get best match pattern "MMMd", 16467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // since there is no pattern for 'y' differs for skeleton 'MMMd', 16477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // need to look for it from skeleton 'yMMMd', 16487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // if found, adjust field width in interval pattern from 16497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "MMM" to "MMMM". 16507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String fieldLetter = 16517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalInfo.CALENDAR_FIELD_TO_PATTERN_LETTER[field]; 16527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestSkeleton = fieldLetter + bestSkeleton; 16537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert skeleton = fieldLetter + skeleton; 16547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // for example, looking for patterns when 'y' differ for 16557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // skeleton "MMMM". 16567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pattern = fInfo.getIntervalPattern(bestSkeleton, field); 16577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( pattern == null && differenceInfo == 0 ) { 16587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // if there is no skeleton "yMMMM" defined, 16597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // look for the best match skeleton, for example: "yMMM" 16607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert BestMatchInfo tmpRetValue = fInfo.getBestSkeleton(skeleton); 16617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String tmpBestSkeleton = tmpRetValue.bestMatchSkeleton; 16627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert differenceInfo = tmpRetValue.bestMatchDistanceInfo; 16637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( tmpBestSkeleton.length() != 0 && differenceInfo != -1 ) { 16647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pattern = fInfo.getIntervalPattern(tmpBestSkeleton, field); 16657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestSkeleton = tmpBestSkeleton; 16667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( pattern != null ) { 16697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert retValue = new SkeletonAndItsBestMatch(skeleton, bestSkeleton); 16707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( pattern != null ) { 16737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( differenceInfo != 0 ) { 16747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String part1 = adjustFieldWidth(skeleton, bestSkeleton, 16757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pattern.getFirstPart(), differenceInfo); 16767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String part2 = adjustFieldWidth(skeleton, bestSkeleton, 16777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pattern.getSecondPart(), differenceInfo); 16787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pattern = new PatternInfo(part1, part2, 16797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pattern.firstDateInPtnIsLaterDate()); 16807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 16817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // pattern is immutable, no need to clone; 16827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // pattern = (PatternInfo)pattern.clone(); 16837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPatterns.put( 16857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalInfo.CALENDAR_FIELD_TO_PATTERN_LETTER[field], pattern); 16867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return retValue; 16887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 16907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 16917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Adjust field width in best match interval pattern to match 16927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the field width in input skeleton. 16937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 16947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * TODO (xji) make a general solution 16957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The adjusting rule can be: 16967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1. always adjust 16977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2. never adjust 16987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3. default adjust, which means adjust according to the following rules 16997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3.1 always adjust string, such as MMM and MMMM 17007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3.2 never adjust between string and numeric, such as MM and MMM 17017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3.3 always adjust year 17027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3.4 do not adjust 'd', 'h', or 'm' if h presents 17037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3.5 do not adjust 'M' if it is numeric(?) 17047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 17057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Since date interval format is well-formed format, 17067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * date and time skeletons are normalized previously, 17077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * till this stage, the adjust here is only "adjust strings, such as MMM 17087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and MMMM, EEE and EEEE. 17097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 17107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param inputSkeleton the input skeleton 17117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param bestMatchSkeleton the best match skeleton 17127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param bestMatchIntervalpattern the best match interval pattern 17137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param differenceInfo the difference between 2 skeletons 17147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1 means only field width differs 17157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2 means v/z exchange 17167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the adjusted interval pattern 17177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 17187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static String adjustFieldWidth(String inputSkeleton, 17197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String bestMatchSkeleton, 17207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String bestMatchIntervalPattern, 17217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int differenceInfo ) { 17227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 17237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( bestMatchIntervalPattern == null ) { 17247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; // the 2nd part could be null 17257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int[] inputSkeletonFieldWidth = new int[58]; 17277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int[] bestMatchSkeletonFieldWidth = new int[58]; 17287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 17297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* initialize as following 17307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 17317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // A B C D E F G H I J K L M N O 17327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // P Q R S T U V W X Y Z 17347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // a b c d e f g h i j k l m n o 17367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // p q r s t u v w x y z 17387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }; 17407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 17417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 17427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 17437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalInfo.parseSkeleton(inputSkeleton, inputSkeletonFieldWidth); 17447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalInfo.parseSkeleton(bestMatchSkeleton, bestMatchSkeletonFieldWidth); 17457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( differenceInfo == 2 ) { 17467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestMatchIntervalPattern = bestMatchIntervalPattern.replace('v', 'z'); 17477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 17497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder adjustedPtn = new StringBuilder(bestMatchIntervalPattern); 17507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 17517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean inQuote = false; 17527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char prevCh = 0; 17537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int count = 0; 17547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 17557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int PATTERN_CHAR_BASE = 0x41; 17567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 17577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // loop through the pattern string character by character 17587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int adjustedPtnLength = adjustedPtn.length(); 17597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < adjustedPtnLength; ++i) { 17607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char ch = adjustedPtn.charAt(i); 17617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch != prevCh && count > 0) { 17627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // check the repeativeness of pattern letter 17637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char skeletonChar = prevCh; 17647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( skeletonChar == 'L' ) { 17657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // for skeleton "M+", the pattern is "...L..." 17667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert skeletonChar = 'M'; 17677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int fieldCount = bestMatchSkeletonFieldWidth[skeletonChar - PATTERN_CHAR_BASE]; 17697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int inputFieldCount = inputSkeletonFieldWidth[skeletonChar - PATTERN_CHAR_BASE]; 17707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( fieldCount == count && inputFieldCount > fieldCount ) { 17717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = inputFieldCount - fieldCount; 17727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( int j = 0; j < count; ++j ) { 17737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert adjustedPtn.insert(i, prevCh); 17747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i += count; 17767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert adjustedPtnLength += count; 17777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = 0; 17797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch == '\'') { 17817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Consecutive single quotes are a single quote literal, 17827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // either outside of quotes or between quotes 17837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((i+1) < adjustedPtn.length() && adjustedPtn.charAt(i+1) == '\'') { 17847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++i; 17857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 17867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert inQuote = ! inQuote; 17877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert else if ( ! inQuote && ((ch >= 0x0061 /*'a'*/ && ch <= 0x007A /*'z'*/) 17907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || (ch >= 0x0041 /*'A'*/ && ch <= 0x005A /*'Z'*/))) { 17917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ch is a date-time pattern character 17927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert prevCh = ch; 17937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++count; 17947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( count > 0 ) { 17977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // last item 17987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // check the repeativeness of pattern letter 17997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char skeletonChar = prevCh; 18007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( skeletonChar == 'L' ) { 18017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // for skeleton "M+", the pattern is "...L..." 18027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert skeletonChar = 'M'; 18037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int fieldCount = bestMatchSkeletonFieldWidth[skeletonChar - PATTERN_CHAR_BASE]; 18057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int inputFieldCount = inputSkeletonFieldWidth[skeletonChar - PATTERN_CHAR_BASE]; 18067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( fieldCount == count && inputFieldCount > fieldCount ) { 18077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = inputFieldCount - fieldCount; 18087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( int j = 0; j < count; ++j ) { 18097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert adjustedPtn.append(prevCh); 18107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return adjustedPtn.toString(); 18147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 18167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 18177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 18187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Concat a single date pattern with a time interval pattern, 18197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * set it into the intervalPatterns, while field is time field. 18207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This is used to handle time interval patterns on skeleton with 18217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * both time and date. Present the date followed by 18227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the range expression for the time. 18237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dtfmt date and time format 18247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param datePattern date pattern 18257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param field time calendar field: AM_PM, HOUR, MINUTE 18267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param intervalPatterns interval patterns 18277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 18287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void concatSingleDate2TimeInterval(String dtfmt, 18297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String datePattern, 18307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int field, 18317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Map<String, PatternInfo> intervalPatterns) 18327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 18337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 18347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternInfo timeItvPtnInfo = 18357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPatterns.get(DateIntervalInfo.CALENDAR_FIELD_TO_PATTERN_LETTER[field]); 18367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( timeItvPtnInfo != null ) { 18377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String timeIntervalPattern = timeItvPtnInfo.getFirstPart() + 18387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeItvPtnInfo.getSecondPart(); 183987255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert String pattern = SimpleFormatterImpl.formatRawPattern( 184087255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert dtfmt, 2, 2, timeIntervalPattern, datePattern); 18417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeItvPtnInfo = DateIntervalInfo.genPatternInfo(pattern, 18427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeItvPtnInfo.firstDateInPtnIsLaterDate()); 18437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intervalPatterns.put( 18447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateIntervalInfo.CALENDAR_FIELD_TO_PATTERN_LETTER[field], timeItvPtnInfo); 18457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // else: fall back 18477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // it should not happen if the interval format defined is valid 18487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 18507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 18517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 18527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * check whether a calendar field present in a skeleton. 18537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param field calendar field need to check 18547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param skeleton given skeleton on which to check the calendar field 18557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true if field present in a skeleton. 18567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 18577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static boolean fieldExistsInSkeleton(int field, String skeleton) 18587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 18597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String fieldChar = DateIntervalInfo.CALENDAR_FIELD_TO_PATTERN_LETTER[field]; 18607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ( (skeleton.indexOf(fieldChar) == -1) ? false : true ) ; 18617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 18637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 18647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 18657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * readObject. 18667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 18677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void readObject(ObjectInputStream stream) 18687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throws IOException, ClassNotFoundException { 18697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stream.defaultReadObject(); 18707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initializePattern(isDateIntervalInfoDefault ? LOCAL_PATTERN_CACHE : null); 18717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1872f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 1873f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /** 1874f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * Get the internal patterns for the skeleton 1875f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * @internal CLDR 1876f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * @deprecated This API is ICU internal only. 1877f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert */ 1878f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert @Deprecated 1879f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert public Map<String, PatternInfo> getRawPatterns() { 1880f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // this is unmodifiable, so ok to return directly 1881f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert return fIntervalPatterns; 1882f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 18837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert} 1884