17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/* 27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 3f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * Copyright (C) 1996-2015, International Business Machines Corporation and 4f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * others. All Rights Reserved. 57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 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.io.ObjectOutputStream; 137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.AttributedCharacterIterator; 147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.AttributedString; 157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.FieldPosition; 167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.Format; 177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.ParsePosition; 187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.ArrayList; 197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Date; 207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.HashMap; 217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.List; 227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Locale; 237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.MissingResourceException; 247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.UUID; 257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.CalendarData; 277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.DateNumberFormat; 287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUCache; 297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.PatternProps; 307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.SimpleCache; 317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.lang.UCharacter; 327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.TimeZoneFormat.Style; 337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.TimeZoneFormat.TimeType; 347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.BasicTimeZone; 357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.Calendar; 367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.HebrewCalendar; 377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.Output; 387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.TimeZone; 397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.TimeZoneTransition; 407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale; 417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale.Category; 427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/** 457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icuenhanced java.text.SimpleDateFormat}.{@icu _usage_} 467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p><code>SimpleDateFormat</code> is a concrete class for formatting and 487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * parsing dates in a locale-sensitive manner. It allows for formatting 49bee65486a185907111f3be60992433e133ec0e32Scott Russell * (date -> text), parsing (text -> date), and normalization. 507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p> 527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>SimpleDateFormat</code> allows you to start by choosing 537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * any user-defined patterns for date-time formatting. However, you 547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * are encouraged to create a date-time formatter with either 557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>getTimeInstance</code>, <code>getDateInstance</code>, or 567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>getDateTimeInstance</code> in <code>DateFormat</code>. Each 577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of these class methods can return a date/time formatter initialized 587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * with a default format pattern. You may modify the format pattern 597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * using the <code>applyPattern</code> methods as desired. 607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For more information on using these methods, see 617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@link DateFormat}. 627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p><strong>Date and Time Patterns:</strong></p> 647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Date and time formats are specified by <em>date and time pattern</em> strings. 667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Within date and time pattern strings, all unquoted ASCII letters [A-Za-z] are reserved 677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * as pattern letters representing calendar fields. <code>SimpleDateFormat</code> supports 687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the date and time formatting algorithm and pattern letters defined by <a href="http://www.unicode.org/reports/tr35/">UTS#35 697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Unicode Locale Data Markup Language (LDML)</a>. The following pattern letters are 707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * currently available (note that the actual values depend on CLDR and may change from the 717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * examples shown here):</p> 727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <blockquote> 737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <table border="1"> 747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th>Field</th> 767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th style="text-align: center">Sym.</th> 777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th style="text-align: center">No.</th> 787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th>Example</th> 797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th>Description</th> 807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th rowspan="3">era</th> 837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center" rowspan="3">G</td> 847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..3</td> 857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>AD</td> 867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="3">Era - Replaced with the Era string for the current date. One to three letters for the 877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * abbreviated form, four letters for the long (wide) form, five for the narrow form.</td> 887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">4</td> 917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Anno Domini</td> 927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">5</td> 957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>A</td> 967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th rowspan="6">year</th> 997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">y</td> 1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..n</td> 1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>1996</td> 1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Year. Normally the length specifies the padding, but for two letters it also specifies the maximum 103bee65486a185907111f3be60992433e133ec0e32Scott Russell * length. Example:<div style="text-align: center"> 1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <center> 1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <table border="1" cellpadding="2" cellspacing="0"> 1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th>Year</th> 1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th style="text-align: right">y</th> 1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th style="text-align: right">yy</th> 1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th style="text-align: right">yyy</th> 1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th style="text-align: right">yyyy</th> 1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th style="text-align: right">yyyyy</th> 1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>AD 1</td> 1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">1</td> 1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">01</td> 1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">001</td> 1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">0001</td> 1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">00001</td> 1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>AD 12</td> 1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">12</td> 1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">12</td> 1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">012</td> 1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">0012</td> 1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">00012</td> 1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>AD 123</td> 1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">123</td> 1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">23</td> 1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">123</td> 1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">0123</td> 1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">00123</td> 1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>AD 1234</td> 1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">1234</td> 1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">34</td> 1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">1234</td> 1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">1234</td> 1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">01234</td> 1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>AD 12345</td> 1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">12345</td> 1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">45</td> 1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">12345</td> 1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">12345</td> 1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: right">12345</td> 1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </table> 1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </center></div> 1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </td> 1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">Y</td> 1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..n</td> 1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>1997</td> 1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Year (in "Week of Year" based calendars). Normally the length specifies the padding, 1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * but for two letters it also specifies the maximum length. This year designation is used in ISO 1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * year-week calendar as defined by ISO 8601, but can be used in non-Gregorian based calendar systems 1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * where week date processing is desired. May not always be the same value as calendar year.</td> 1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">u</td> 1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..n</td> 1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>4601</td> 1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Extended year. This is a single number designating the year of this calendar system, encompassing 1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * all supra-year fields. For example, for the Julian calendar system, year numbers are positive, with an 1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * era of BCE or CE. An extended year value for the Julian calendar system assigns positive values to CE 1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * years and negative values to BCE years, with 1 BCE being year 0.</td> 1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center" rowspan="3">U</td> 1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..3</td> 1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>甲子</td> 1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="3">Cyclic year name. Calendars such as the Chinese lunar calendar (and related calendars) 1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and the Hindu calendars use 60-year cycles of year names. Use one through three letters for the abbreviated 1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * name, four for the full (wide) name, or five for the narrow name (currently the data only provides abbreviated names, 1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * which will be used for all requested name widths). If the calendar does not provide cyclic year name data, 1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * or if the year value to be formatted is out of the range of years for which cyclic name data is provided, 1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * then numeric formatting is used (behaves like 'y').</td> 1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">4</td> 1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>(currently also 甲子)</td> 1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">5</td> 1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>(currently also 甲子)</td> 1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th rowspan="6">quarter</th> 1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="3" style="text-align: center">Q</td> 1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..2</td> 1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>02</td> 2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="3">Quarter - Use one or two for the numerical quarter, three for the abbreviation, or four 2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for the full (wide) name (five for the narrow name is not yet supported).</td> 2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">3</td> 2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Q2</td> 2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">4</td> 2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>2nd quarter</td> 2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="3" style="text-align: center">q</td> 2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..2</td> 2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>02</td> 2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="3"><b>Stand-Alone</b> Quarter - Use one or two for the numerical quarter, three for the abbreviation, 2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * or four for the full name (five for the narrow name is not yet supported).</td> 2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">3</td> 2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Q2</td> 2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">4</td> 2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>2nd quarter</td> 2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th rowspan="8">month</th> 2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="4" style="text-align: center">M</td> 2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..2</td> 2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>09</td> 2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="4">Month - Use one or two for the numerical month, three for the abbreviation, four for 2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the full (wide) name, or five for the narrow name. With two ("MM"), the month number is zero-padded 2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * if necessary (e.g. "08").</td> 2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">3</td> 2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Sep</td> 2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">4</td> 2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>September</td> 2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">5</td> 2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>S</td> 2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="4" style="text-align: center">L</td> 2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..2</td> 2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>09</td> 2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="4"><b>Stand-Alone</b> Month - Use one or two for the numerical month, three for the abbreviation, 2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * four for the full (wide) name, or 5 for the narrow name. With two ("LL"), the month number is zero-padded if 2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * necessary (e.g. "08").</td> 2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">3</td> 2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Sep</td> 2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">4</td> 2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>September</td> 2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">5</td> 2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>S</td> 2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th rowspan="2">week</th> 2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">w</td> 2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..2</td> 2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>27</td> 2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Week of Year. Use "w" to show the minimum number of digits, or "ww" to always show two digits 2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (zero-padding if necessary, e.g. "08").</td> 2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">W</td> 2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1</td> 2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>3</td> 2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Week of Month</td> 2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th rowspan="4">day</th> 2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">d</td> 2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..2</td> 2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>1</td> 2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Date - Day of the month. Use "d" to show the minimum number of digits, or "dd" to always show 2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * two digits (zero-padding if necessary, e.g. "08").</td> 2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">D</td> 2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..3</td> 2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>345</td> 2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Day of year</td> 2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">F</td> 2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1</td> 2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>2</td> 2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Day of Week in Month. The example is for the 2nd Wed in July</td> 3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">g</td> 3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..n</td> 3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>2451334</td> 3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Modified Julian day. This is different from the conventional Julian day number in two regards. 3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * First, it demarcates days at local zone midnight, rather than noon GMT. Second, it is a local number; 3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * that is, it depends on the local time zone. It can be thought of as a single number that encompasses 3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * all the date-related fields.</td> 3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th rowspan="14">week<br> 3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * day</th> 3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="4" style="text-align: center">E</td> 3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..3</td> 3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Tue</td> 3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="4">Day of week - Use one through three letters for the short day, four for the full (wide) name, 3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * five for the narrow name, or six for the short name.</td> 3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">4</td> 3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Tuesday</td> 3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">5</td> 3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>T</td> 3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">6</td> 3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Tu</td> 3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="5" style="text-align: center">e</td> 3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..2</td> 3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>2</td> 3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="5">Local day of week. Same as E except adds a numeric value that will depend on the local 3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * starting day of the week, using one or two letters. For this example, Monday is the first day of the week.</td> 3377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">3</td> 3407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Tue</td> 3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">4</td> 3447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Tuesday</td> 3457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">5</td> 3487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>T</td> 3497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">6</td> 3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Tu</td> 3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="5" style="text-align: center">c</td> 3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1</td> 3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>2</td> 3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="5"><b>Stand-Alone</b> local day of week - Use one letter for the local numeric value (same 3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * as 'e'), three for the short day, four for the full (wide) name, five for the narrow name, or six for 3607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the short name.</td> 3617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">3</td> 3647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Tue</td> 3657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">4</td> 3687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Tuesday</td> 3697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">5</td> 3727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>T</td> 3737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">6</td> 3767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Tu</td> 3777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th>period</th> 3807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">a</td> 3817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1</td> 3827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>AM</td> 3837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>AM or PM</td> 3847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th rowspan="4">hour</th> 3877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">h</td> 3887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..2</td> 3897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>11</td> 3907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Hour [1-12]. When used in skeleton data or in a skeleton passed in an API for flexible data pattern 3917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * generation, it should match the 12-hour-cycle format preferred by the locale (h or K); it should not match 3927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * a 24-hour-cycle format (H or k). Use hh for zero padding.</td> 3937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 3947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 3957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">H</td> 3967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..2</td> 3977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>13</td> 3987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Hour [0-23]. When used in skeleton data or in a skeleton passed in an API for flexible data pattern 3997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * generation, it should match the 24-hour-cycle format preferred by the locale (H or k); it should not match a 4007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 12-hour-cycle format (h or K). Use HH for zero padding.</td> 4017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 4027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 4037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">K</td> 4047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..2</td> 4057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>0</td> 4067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Hour [0-11]. When used in a skeleton, only matches K or h, see above. Use KK for zero padding.</td> 4077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 4087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 4097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">k</td> 4107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..2</td> 4117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>24</td> 4127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Hour [1-24]. When used in a skeleton, only matches k or H, see above. Use kk for zero padding.</td> 4137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 4147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 4157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th>minute</th> 4167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">m</td> 4177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..2</td> 4187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>59</td> 4197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Minute. Use "m" to show the minimum number of digits, or "mm" to always show two digits 4207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (zero-padding if necessary, e.g. "08")..</td> 4217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 4227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 4237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th rowspan="3">second</th> 4247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">s</td> 4257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..2</td> 4267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>12</td> 4277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Second. Use "s" to show the minimum number of digits, or "ss" to always show two digits 4287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (zero-padding if necessary, e.g. "08").</td> 4297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 4307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 4317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">S</td> 4327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..n</td> 4337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>3450</td> 4347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Fractional Second - truncates (like other time fields) to the count of letters when formatting. Appends zeros if more than 3 letters specified. Truncates at three significant digits when parsing. 4357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (example shows display using pattern SSSS for seconds value 12.34567)</td> 4367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 4377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 4387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">A</td> 4397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..n</td> 4407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>69540000</td> 4417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Milliseconds in day. This field behaves <i>exactly</i> like a composite of all time-related fields, 4427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * not including the zone fields. As such, it also reflects discontinuities of those fields on DST transition 4437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * days. On a day of DST onset, it will jump forward. On a day of DST cessation, it will jump backward. This 4447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * reflects the fact that is must be combined with the offset field to obtain a unique local time value.</td> 4457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 4467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 4477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th rowspan="23">zone</th> 4487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="2" style="text-align: center">z</td> 4497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..3</td> 4507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>PDT</td> 4517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>short specific non-location format</i>. 4527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Where that is unavailable, falls back to the <i>short localized GMT format</i> ("O").</td> 4537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 4547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 4557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">4</td> 4567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Pacific Daylight Time</td> 4577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>long specific non-location format</i>. 4587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Where that is unavailable, falls back to the <i>long localized GMT format</i> ("OOOO").</td> 4597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 4607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 4617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="3" style="text-align: center">Z</td> 4627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1..3</td> 4637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>-0800</td> 4647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>ISO8601 basic format</i> with hours, minutes and optional seconds fields. 4657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The format is equivalent to RFC 822 zone format (when optional seconds field is absent). 4667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This is equivalent to the "xxxx" specifier.</td> 4677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 4687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 4697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">4</td> 4707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>GMT-8:00</td> 4717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>long localized GMT format</i>. 4727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This is equivalent to the "OOOO" specifier.</td> 4737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 4747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 4757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">5</td> 4767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>-08:00<br> 4777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * -07:52:58</td> 4787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>ISO8601 extended format</i> with hours, minutes and optional seconds fields. 4797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The ISO8601 UTC indicator "Z" is used when local time offset is 0. 4807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This is equivalent to the "XXXXX" specifier.</td> 4817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 4827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 4837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="2" style="text-align: center">O</td> 4847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1</td> 4857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>GMT-8</td> 4867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>short localized GMT format</i>.</td> 4877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 4887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 4897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">4</td> 4907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>GMT-08:00</td> 4917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>long localized GMT format</i>.</td> 4927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 4937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 4947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="2" style="text-align: center">v</td> 4957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1</td> 4967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>PT</td> 4977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>short generic non-location format</i>. 4987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Where that is unavailable, falls back to the <i>generic location format</i> ("VVVV"), 4997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * then the <i>short localized GMT format</i> as the final fallback.</td> 5007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 5017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 5027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">4</td> 5037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Pacific Time</td> 5047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>long generic non-location format</i>. 5057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Where that is unavailable, falls back to <i>generic location format</i> ("VVVV"). 5067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 5077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 5087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="4" style="text-align: center">V</td> 5097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1</td> 5107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>uslax</td> 5117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The short time zone ID. 5127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Where that is unavailable, the special short time zone ID <i>unk</i> (Unknown Zone) is used.<br> 5137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <i><b>Note</b>: This specifier was originally used for a variant of the short specific non-location format, 5147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * but it was deprecated in the later version of the LDML specification. In CLDR 23/ICU 51, the definition of 5157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the specifier was changed to designate a short time zone ID.</i></td> 5167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 5177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 5187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">2</td> 5197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>America/Los_Angeles</td> 5207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The long time zone ID.</td> 5217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 5227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 5237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">3</td> 5247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Los Angeles</td> 5257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The exemplar city (location) for the time zone. 5267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Where that is unavailable, the localized exemplar city name for the special zone <i>Etc/Unknown</i> is used 5277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * as the fallback (for example, "Unknown City"). </td> 5287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 5297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 5307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">4</td> 5317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Los Angeles Time</td> 5327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>generic location format</i>. 5337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Where that is unavailable, falls back to the <i>long localized GMT format</i> ("OOOO"; 5347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Note: Fallback is only necessary with a GMT-style Time Zone ID, like Etc/GMT-830.)<br> 5357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This is especially useful when presenting possible timezone choices for user selection, 5367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * since the naming is more uniform than the "v" format.</td> 5377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 5387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 5397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="5" style="text-align: center">X</td> 5407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1</td> 5417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>-08<br> 5427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * +0530<br> 5437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Z</td> 5447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>ISO8601 basic format</i> with hours field and optional minutes field. 5457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The ISO8601 UTC indicator "Z" is used when local time offset is 0.</td> 5467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 5477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 5487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">2</td> 5497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>-0800<br> 5507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Z</td> 5517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>ISO8601 basic format</i> with hours and minutes fields. 5527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The ISO8601 UTC indicator "Z" is used when local time offset is 0.</td> 5537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 5547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 5557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">3</td> 5567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>-08:00<br> 5577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Z</td> 5587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>ISO8601 extended format</i> with hours and minutes fields. 5597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The ISO8601 UTC indicator "Z" is used when local time offset is 0.</td> 5607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 5617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 5627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">4</td> 5637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>-0800<br> 5647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * -075258<br> 5657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Z</td> 5667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>ISO8601 basic format</i> with hours, minutes and optional seconds fields. 5677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (Note: The seconds field is not supported by the ISO8601 specification.) 5687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The ISO8601 UTC indicator "Z" is used when local time offset is 0.</td> 5697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 5707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 5717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">5</td> 5727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>-08:00<br> 5737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * -07:52:58<br> 5747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Z</td> 5757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>ISO8601 extended format</i> with hours, minutes and optional seconds fields. 5767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (Note: The seconds field is not supported by the ISO8601 specification.) 5777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The ISO8601 UTC indicator "Z" is used when local time offset is 0.</td> 5787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 5797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 5807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td rowspan="5" style="text-align: center">x</td> 5817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">1</td> 5827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>-08<br> 5837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * +0530</td> 5847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>ISO8601 basic format</i> with hours field and optional minutes field.</td> 5857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 5867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 5877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">2</td> 5887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>-0800</td> 5897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>ISO8601 basic format</i> with hours and minutes fields.</td> 5907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 5917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 5927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">3</td> 5937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>-08:00</td> 5947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>ISO8601 extended format</i> with hours and minutes fields.</td> 5957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 5967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 5977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">4</td> 5987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>-0800<br> 5997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * -075258</td> 6007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>ISO8601 basic format</i> with hours, minutes and optional seconds fields. 6017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (Note: The seconds field is not supported by the ISO8601 specification.)</td> 6027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 6037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr> 6047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td style="text-align: center">5</td> 6057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>-08:00<br> 6067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * -07:52:58</td> 6077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>The <i>ISO8601 extended format</i> with hours, minutes and optional seconds fields. 6087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (Note: The seconds field is not supported by the ISO8601 specification.)</td> 6097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </tr> 6107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </table> 6117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </blockquote> 6137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p> 6147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Any characters in the pattern that are not in the ranges of ['a'..'z'] 6157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and ['A'..'Z'] will be treated as quoted text. For instance, characters 6167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * like ':', '.', ' ', '#' and '@' will appear in the resulting time text 6177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * even they are not embraced within single quotes. 6187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p> 6197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * A pattern containing any invalid pattern letter will result in a thrown 6207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * exception during formatting or parsing. 6217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p> 6237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <strong>Examples Using the US Locale:</strong> 6247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <blockquote> 6257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <pre> 6267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Format Pattern Result 6277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * -------------- ------- 628bee65486a185907111f3be60992433e133ec0e32Scott Russell * "yyyy.MM.dd G 'at' HH:mm:ss vvvv" ->> 1996.07.10 AD at 15:08:56 Pacific Time 629bee65486a185907111f3be60992433e133ec0e32Scott Russell * "EEE, MMM d, ''yy" ->> Wed, July 10, '96 630bee65486a185907111f3be60992433e133ec0e32Scott Russell * "h:mm a" ->> 12:08 PM 631bee65486a185907111f3be60992433e133ec0e32Scott Russell * "hh 'o''clock' a, zzzz" ->> 12 o'clock PM, Pacific Daylight Time 632bee65486a185907111f3be60992433e133ec0e32Scott Russell * "K:mm a, vvv" ->> 0:00 PM, PT 633bee65486a185907111f3be60992433e133ec0e32Scott Russell * "yyyyy.MMMMM.dd GGG hh:mm aaa" ->> 01996.July.10 AD 12:08 PM 6347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </pre> 6357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </blockquote> 6367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <strong>Code Sample:</strong> 6377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <blockquote> 6387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <pre> 6397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, "PST"); 6407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2*60*60*1000); 6417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*60*60*1000); 6427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <br> 6437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * // Format the current time. 6447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * SimpleDateFormat formatter 6457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * = new SimpleDateFormat ("yyyy.MM.dd G 'at' hh:mm:ss a zzz"); 6467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Date currentTime_1 = new Date(); 6477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * String dateString = formatter.format(currentTime_1); 6487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <br> 6497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * // Parse the previous string back into a Date. 6507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * ParsePosition pos = new ParsePosition(0); 6517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Date currentTime_2 = formatter.parse(dateString, pos); 6527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </pre> 6537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </blockquote> 6547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * In the example, the time value <code>currentTime_2</code> obtained from 6557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * parsing will be equal to <code>currentTime_1</code>. However, they may not be 6567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * equal if the am/pm marker 'a' is left out from the format pattern while 6577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the "hour in am/pm" pattern symbol is used. This information loss can 6587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * happen when formatting the time in PM. 6597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>When parsing a date string using the abbreviated year pattern ("yy"), 6617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * SimpleDateFormat must interpret the abbreviated year 6627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * relative to some century. It does this by adjusting dates to be 6637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * within 80 years before and 20 years after the time the SimpleDateFormat 6647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * instance is created. For example, using a pattern of "MM/dd/yy" and a 6657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * SimpleDateFormat instance created on Jan 1, 1997, the string 6667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "01/11/12" would be interpreted as Jan 11, 2012 while the string "05/04/64" 6677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * would be interpreted as May 4, 1964. 6687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * During parsing, only strings consisting of exactly two digits, as defined by 6697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@link com.ibm.icu.lang.UCharacter#isDigit(int)}, will be parsed into the default 6707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * century. 6717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Any other numeric string, such as a one digit string, a three or more digit 6727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * string, or a two digit string that isn't all digits (for example, "-1"), is 6737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * interpreted literally. So "01/02/3" or "01/02/003" are parsed, using the 6747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * same pattern, as Jan 2, 3 AD. Likewise, "01/02/-3" is parsed as Jan 2, 4 BC. 6757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>If the year pattern does not have exactly two 'y' characters, the year is 6777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * interpreted literally, regardless of the number of digits. So using the 6787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D. 6797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>When numeric fields abut one another directly, with no intervening delimiter 6817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * characters, they constitute a run of abutting numeric fields. Such runs are 6827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * parsed specially. For example, the format "HHmmss" parses the input text 6837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "123456" to 12:34:56, parses the input text "12345" to 1:23:45, and fails to 6847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * parse "1234". In other words, the leftmost field of the run is flexible, 6857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * while the others keep a fixed width. If the parse fails anywhere in the run, 6867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * then the leftmost field is shortened by one character, and the entire run is 6877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * parsed again. This is repeated until either the parse succeeds or the 6887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * leftmost field is one character in length. If the parse still fails at that 6897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * point, the parse of the run fails. 6907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>For time zones that have no names, use strings GMT+hours:minutes or 6927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * GMT-hours:minutes. 6937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>The calendar defines what is the first day of the week, the first week 6957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of the year, whether hours are zero based or not (0 vs 12 or 24), and the 6967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * time zone. There is one common decimal format to handle all the numbers; 6977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the digit count is handled programmatically according to the pattern. 6987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 699bee65486a185907111f3be60992433e133ec0e32Scott Russell * <h3>Synchronization</h3> 7007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 7017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Date formats are not synchronized. It is recommended to create separate 7027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * format instances for each thread. If multiple threads access a format 7037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * concurrently, it must be synchronized externally. 7047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 7057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see com.ibm.icu.util.Calendar 7067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see com.ibm.icu.util.GregorianCalendar 7077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see com.ibm.icu.util.TimeZone 7087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see DateFormat 7097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see DateFormatSymbols 7107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see DecimalFormat 7117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see TimeZoneFormat 7127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author Mark Davis, Chen-Lieh Huang, Alan Liu 7137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 7147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 7157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class SimpleDateFormat extends DateFormat { 7167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the official serial version ID which says cryptically 7187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // which version we're compatible with 7197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final long serialVersionUID = 4774881970558875024L; 7207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the internal serial version which says which version was written 7227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // - 0 (default) for version up to JDK 1.1.3 7237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // - 1 for version from JDK 1.1.4, which includes a new field 7247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // - 2 we write additional int for capitalizationSetting 7257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final int currentSerialVersion = 2; 7267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static boolean DelayedHebrewMonthCheck = false; 7287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 7307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * From calendar field to its level. 7317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Used to order calendar field. 7327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, calendar fields can be defined in the following order: 7337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * year > month > date > am-pm > hour > minute 7347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * YEAR --> 10, MONTH -->20, DATE --> 30; 7357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * AM_PM -->40, HOUR --> 50, MINUTE -->60 7367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 7377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int[] CALENDAR_FIELD_TO_LEVEL = 7387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 7397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*GyM*/ 0, 10, 20, 7407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*wW*/ 20, 30, 7417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*dDEF*/ 30, 20, 30, 30, 7427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*ahHm*/ 40, 50, 50, 60, 743f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /*sS*/ 70, 80, 7447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*z?Y*/ 0, 0, 10, 7457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*eug*/ 30, 10, 0, 746f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /*A?*/ 40, 0, 0 7477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }; 7487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 7507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * From calendar field letter to its level. 7517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Used to order calendar field. 7527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, calendar fields can be defined in the following order: 7537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * year > month > date > am-pm > hour > minute 7547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 'y' --> 10, 'M' -->20, 'd' --> 30; 'a' -->40, 'h' --> 50, 'm' -->60 7557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 7567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int[] PATTERN_CHAR_TO_LEVEL = 7577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 758f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 759f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // 760f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 761f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // ! " # $ % & ' ( ) * + , - . / 762f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 763f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 764bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 765f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // @ A B C D E F G H I J K L M N O 7667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert -1, 40, -1, -1, 20, 30, 30, 0, 50, -1, -1, 50, 20, 20, -1, 0, 767f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // P Q R S T U V W X Y Z [ \ ] ^ _ 7687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert -1, 20, -1, 80, -1, 10, 0, 30, 0, 10, 0, -1, -1, -1, -1, -1, 769f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // ` a b c d e f g h i j k l m n o 7707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert -1, 40, -1, 30, 30, 30, -1, 0, 50, -1, -1, 50, -1, 60, -1, -1, 771f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // p q r s t u v w x y z { | } ~ 772f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert -1, 20, 10, 70, -1, 10, 0, 20, 0, 10, 0, -1, -1, -1, -1, -1, 773f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert }; 774f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 775f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /** 776f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * Map calendar field letter into calendar field level. 777f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert */ 778f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert private static int getLevelFromChar(char ch) { 779f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert return ch < PATTERN_CHAR_TO_LEVEL.length ? PATTERN_CHAR_TO_LEVEL[ch & 0xff] : -1; 780f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 781f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 782f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert private static final boolean[] PATTERN_CHAR_IS_SYNTAX = 783f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert { 784f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // 785f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert false, false, false, false, false, false, false, false, 786f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // 787f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert false, false, false, false, false, false, false, false, 788f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // 789f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert false, false, false, false, false, false, false, false, 790f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // 791f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert false, false, false, false, false, false, false, false, 792f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // ! " # $ % & ' 793f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert false, false, false, false, false, false, false, false, 794f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // ( ) * + , - . / 795f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert false, false, false, false, false, false, false, false, 796f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // 0 1 2 3 4 5 6 7 797f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert false, false, false, false, false, false, false, false, 798f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // 8 9 : ; < = > ? 799bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert false, false, false, false, false, false, false, false, 800f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // @ A B C D E F G 801f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert false, true, true, true, true, true, true, true, 802f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // H I J K L M N O 803f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert true, true, true, true, true, true, true, true, 804f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // P Q R S T U V W 805f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert true, true, true, true, true, true, true, true, 806f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // X Y Z [ \ ] ^ _ 807f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert true, true, true, false, false, false, false, false, 808f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // ` a b c d e f g 809f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert false, true, true, true, true, true, true, true, 810f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // h i j k l m n o 811f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert true, true, true, true, true, true, true, true, 812f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // p q r s t u v w 813f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert true, true, true, true, true, true, true, true, 814f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // x y z { | } ~ 815f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert true, true, true, false, false, false, false, false, 8167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }; 8177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 818f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /** 819f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * Tell if a character can be used to define a field in a format string. 820f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert */ 821f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert private static boolean isSyntaxChar(char ch) { 822f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert return ch < PATTERN_CHAR_IS_SYNTAX.length ? PATTERN_CHAR_IS_SYNTAX[ch & 0xff] : false; 823f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 824f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 8257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // When calendar uses hebr numbering (i.e. he@calendar=hebrew), 8267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // offset the years within the current millenium down to 1-999 8277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int HEBREW_CAL_CUR_MILLENIUM_START_YEAR = 5000; 8287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int HEBREW_CAL_CUR_MILLENIUM_END_YEAR = 6000; 8297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The version of the serialized data on the stream. Possible values: 8327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ul> 8337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li><b>0</b> or not present on stream: JDK 1.1.3. This version 8347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * has no <code>defaultCenturyStart</code> on stream. 8357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li><b>1</b> JDK 1.1.4 or later. This version adds 8367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>defaultCenturyStart</code>. 8377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li><b>2</b> This version writes an additional int for 8387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>capitalizationSetting</code>. 8397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ul> 8407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * When streaming out this class, the most recent format 8417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and the highest allowable <code>serialVersionOnStream</code> 8427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is written. 8437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 8447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int serialVersionOnStream = currentSerialVersion; 8467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The pattern string of this formatter. This is always a non-localized 8497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern. May not be null. See class documentation for details. 8507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 8517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String pattern; 8537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The override string of this formatter. Used to override the 8567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * numbering system for one or more fields. 8577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 8587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String override; 8607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The hash map used for number format overrides. 8637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 8647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private HashMap<String, NumberFormat> numberFormatters; 8667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The hash map used for number format overrides. 8697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 8707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private HashMap<Character, String> overrideMap; 8727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The symbols used by this formatter for week names, month names, 8757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * etc. May not be null. 8767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 8777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see DateFormatSymbols 8787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private DateFormatSymbols formatData; 8807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient ULocale locale; 8827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * We map dates with two-digit years into the century starting at 8857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>defaultCenturyStart</code>, which may be any date. May 8867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * not be null. 8877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 8887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @since JDK1.1.4 8897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Date defaultCenturyStart; 8917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient int defaultCenturyStartYear; 8937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // defaultCenturyBase is set when an instance is created 8957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // and may be used for calculating defaultCenturyStart when needed. 8967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient long defaultCenturyBase; 8977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int millisPerHour = 60 * 60 * 1000; 8997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // When possessing ISO format, the ERA may be ommitted is the 9017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // year specifier is a negative number. 9027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int ISOSpecialEra = -32000; 9037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // This prefix is designed to NEVER MATCH real text, in order to 9057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // suppress the parsing of negative numbers. Adjust as needed (if 9067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // this becomes valid Unicode). 9077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final String SUPPRESS_NEGATIVE_PREFIX = "\uAB00"; 9087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If true, this object supports fast formatting using the 9117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * subFormat variant that takes a StringBuffer. 9127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient boolean useFastFormat; 9147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 9167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The time zone sub-formatter, introduced in ICU 4.8 9177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private volatile TimeZoneFormat tzFormat; 9197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * BreakIterator to use for capitalization 9227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient BreakIterator capitalizationBrkIter = null; 9247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 9267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Capitalization setting, introduced in ICU 50 9277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Special serialization, see writeObject & readObject below 9287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 9297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Hoisted to DateFormat in ICU 53, get value with 9307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * getContext(DisplayContext.Type.CAPITALIZATION) 9317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // private transient DisplayContext capitalizationSetting; 9337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 9357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Old defaultCapitalizationContext field 9367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * from ICU 49.1: 9377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //private ContextValue defaultCapitalizationContext; 9397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Old ContextValue enum, preserved only to avoid 9417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * deserialization errs from ICU 49.1. 9427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @SuppressWarnings("unused") 9447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private enum ContextValue { 9457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UNKNOWN, 9467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, 9477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, 9487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CAPITALIZATION_FOR_UI_LIST_OR_MENU, 9497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CAPITALIZATION_FOR_STANDALONE 9507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Constructs a SimpleDateFormat using the default pattern for the default <code>FORMAT</code> 9547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * locale. <b>Note:</b> Not all locales support SimpleDateFormat; for full 9557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * generality, use the factory methods in the DateFormat class. 9567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 9577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see DateFormat 9587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see Category#FORMAT 9597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 9607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public SimpleDateFormat() { 9627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this(getDefaultPattern(), null, null, null, null, true, null); 9637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Constructs a SimpleDateFormat using the given pattern in the default <code>FORMAT</code> 9677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * locale. <b>Note:</b> Not all locales support SimpleDateFormat; for full 9687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * generality, use the factory methods in the DateFormat class. 9697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see Category#FORMAT 9707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 9717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public SimpleDateFormat(String pattern) 9737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 9747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this(pattern, null, null, null, null, true, null); 9757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Constructs a SimpleDateFormat using the given pattern and locale. 9797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <b>Note:</b> Not all locales support SimpleDateFormat; for full 9807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * generality, use the factory methods in the DateFormat class. 9817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 9827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public SimpleDateFormat(String pattern, Locale loc) 9847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 9857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this(pattern, null, null, null, ULocale.forLocale(loc), true, null); 9867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Constructs a SimpleDateFormat using the given pattern and locale. 9907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <b>Note:</b> Not all locales support SimpleDateFormat; for full 9917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * generality, use the factory methods in the DateFormat class. 9927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.2 9937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public SimpleDateFormat(String pattern, ULocale loc) 9957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 9967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this(pattern, null, null, null, loc, true, null); 9977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 10007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Constructs a SimpleDateFormat using the given pattern , override and locale. 10017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pattern The pattern to be used 10027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param override The override string. A numbering system override string can take one of the following forms: 10037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1). If just a numbering system name is specified, it applies to all numeric fields in the date format pattern. 10047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2). To specify an alternate numbering system on a field by field basis, use the field letters from the pattern 10057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * followed by an = sign, followed by the numbering system name. For example, to specify that just the year 10067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * be formatted using Hebrew digits, use the override "y=hebr". Multiple overrides can be specified in a single 10077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * string by separating them with a semi-colon. For example, the override string "m=thai;y=deva" would format using 10087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Thai digits for the month and Devanagari digits for the year. 10097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param loc The locale to be used 10107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.2 10117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 10127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public SimpleDateFormat(String pattern, String override, ULocale loc) 10137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 10147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this(pattern, null, null, null, loc, false,override); 10157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 10187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Constructs a SimpleDateFormat using the given pattern and 10197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * locale-specific symbol data. 10207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Warning: uses default <code>FORMAT</code> locale for digits! 10217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 10227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 10237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public SimpleDateFormat(String pattern, DateFormatSymbols formatData) 10247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 10257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this(pattern, (DateFormatSymbols)formatData.clone(), null, null, null, true, null); 10267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 10297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 10307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 10317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 10327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 10337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public SimpleDateFormat(String pattern, DateFormatSymbols formatData, ULocale loc) 10347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 10357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this(pattern, (DateFormatSymbols)formatData.clone(), null, null, loc, true,null); 10367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 10397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Package-private constructor that allows a subclass to specify 10407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * whether it supports fast formatting. 10417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 10427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * TODO make this API public. 10437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 10447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert SimpleDateFormat(String pattern, DateFormatSymbols formatData, Calendar calendar, ULocale locale, 10457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean useFastFormat, String override) { 10467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this(pattern, (DateFormatSymbols)formatData.clone(), (Calendar)calendar.clone(), null, locale, useFastFormat,override); 10477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 10507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The constructor called from all other SimpleDateFormat constructors 10517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 10527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private SimpleDateFormat(String pattern, DateFormatSymbols formatData, Calendar calendar, 10537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert NumberFormat numberFormat, ULocale locale, boolean useFastFormat,String override) { 10547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.pattern = pattern; 10557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.formatData = formatData; 10567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.calendar = calendar; 10577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.numberFormat = numberFormat; 10587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.locale = locale; // time zone formatting 10597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.useFastFormat = useFastFormat; 10607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.override = override; 10617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initialize(); 10627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 10657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates an instance of SimpleDateFormat for the given format configuration 10667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param formatConfig the format configuration 10677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return A SimpleDateFormat instance 10687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 10697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 10707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 10717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 10727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static SimpleDateFormat getInstance(Calendar.FormatConfiguration formatConfig) { 10737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String ostr = formatConfig.getOverrideString(); 10757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean useFast = ( ostr != null && ostr.length() > 0 ); 10767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new SimpleDateFormat(formatConfig.getPatternString(), 10787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert formatConfig.getDateFormatSymbols(), 10797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert formatConfig.getCalendar(), 10807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert null, 10817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert formatConfig.getLocale(), 10827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert useFast, 10837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert formatConfig.getOverrideString()); 10847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 10877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Initialized fields 10887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 10897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void initialize() { 10907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (locale == null) { 10917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert locale = ULocale.getDefault(Category.FORMAT); 10927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (formatData == null) { 10947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert formatData = new DateFormatSymbols(locale); 10957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (calendar == null) { 10977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendar = Calendar.getInstance(locale); 10987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (numberFormat == null) { 11007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert NumberingSystem ns = NumberingSystem.getInstance(locale); 11017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ns.isAlgorithmic()) { 11027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberFormat = NumberFormat.getInstance(locale); 11037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 11047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String digitString = ns.getDescription(); 11057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String nsName = ns.getName(); 11067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Use a NumberFormat optimized for date formatting 11077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberFormat = new DateNumberFormat(locale, digitString, nsName); 11087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Note: deferring calendar calculation until when we really need it. 11117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Instead, we just record time of construction for backward compatibility. 11127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert defaultCenturyBase = System.currentTimeMillis(); 11137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setLocale(calendar.getLocale(ULocale.VALID_LOCALE ), calendar.getLocale(ULocale.ACTUAL_LOCALE)); 11157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initLocalZeroPaddingNumberFormat(); 11167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (override != null) { 11187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initNumberFormatters(locale); 11197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 11237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Private method lazily instantiate the TimeZoneFormat field 11247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param bForceUpdate when true, check if tzFormat is synchronized with 11257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the current numberFormat and update its digits if necessary. When false, 11267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * this check is skipped. 11277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 11287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private synchronized void initializeTimeZoneFormat(boolean bForceUpdate) { 11297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (bForceUpdate || tzFormat == null) { 11307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tzFormat = TimeZoneFormat.getInstance(locale); 11317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String digits = null; 11337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (numberFormat instanceof DecimalFormat) { 11347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DecimalFormatSymbols decsym = ((DecimalFormat) numberFormat).getDecimalFormatSymbols(); 11357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digits = new String(decsym.getDigits()); 11367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (numberFormat instanceof DateNumberFormat) { 11377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digits = new String(((DateNumberFormat)numberFormat).getDigits()); 11387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digits != null) { 11417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!tzFormat.getGMTOffsetDigits().equals(digits)) { 11427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tzFormat.isFrozen()) { 11437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tzFormat = tzFormat.cloneAsThawed(); 11447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tzFormat.setGMTOffsetDigits(digits); 11467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 11527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Private method, returns non-null TimeZoneFormat. 11537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the TimeZoneFormat used by this formatter. 11547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 11557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private TimeZoneFormat tzFormat() { 11567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tzFormat == null) { 11577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initializeTimeZoneFormat(false); 11587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return tzFormat; 11607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // privates for the default pattern 11637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static ULocale cachedDefaultLocale = null; 11647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static String cachedDefaultPattern = null; 11657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final String FALLBACKPATTERN = "yy/MM/dd HH:mm"; 11667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 11687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the default date and time pattern (SHORT) for the default locale. 11697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This method is only used by the default SimpleDateFormat constructor. 11707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 11717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static synchronized String getDefaultPattern() { 11727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ULocale defaultLocale = ULocale.getDefault(Category.FORMAT); 11737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!defaultLocale.equals(cachedDefaultLocale)) { 11747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cachedDefaultLocale = defaultLocale; 11757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar cal = Calendar.getInstance(cachedDefaultLocale); 11767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 11777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CalendarData calData = new CalendarData(cachedDefaultLocale, cal.getType()); 11787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String[] dateTimePatterns = calData.getDateTimePatterns(); 11797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int glueIndex = 8; 11807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (dateTimePatterns.length >= 13) 11817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 11827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert glueIndex += (SHORT + 1); 11837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cachedDefaultPattern = MessageFormat.format(dateTimePatterns[glueIndex], 11857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert new Object[] {dateTimePatterns[SHORT], dateTimePatterns[SHORT + 4]}); 11867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch (MissingResourceException e) { 11877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cachedDefaultPattern = FALLBACKPATTERN; 11887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return cachedDefaultPattern; 11917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* Define one-century window into which to disambiguate dates using 11947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * two-digit years. 11957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 11967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void parseAmbiguousDatesAsAfter(Date startDate) { 11977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert defaultCenturyStart = startDate; 11987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendar.setTime(startDate); 11997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert defaultCenturyStartYear = calendar.get(Calendar.YEAR); 12007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* Initialize defaultCenturyStart and defaultCenturyStartYear by base time. 12037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The default start time is 80 years before the creation time of this object. 12047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 12057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void initializeDefaultCenturyStart(long baseTime) { 12067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert defaultCenturyBase = baseTime; 12077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // clone to avoid messing up date stored in calendar object 12087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // when this method is called while parsing 12097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar tmpCal = (Calendar)calendar.clone(); 12107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tmpCal.setTimeInMillis(baseTime); 12117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tmpCal.add(Calendar.YEAR, -80); 12127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert defaultCenturyStart = tmpCal.getTime(); 12137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert defaultCenturyStartYear = tmpCal.get(Calendar.YEAR); 12147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* Gets the default century start date for this object */ 12177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Date getDefaultCenturyStart() { 12187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (defaultCenturyStart == null) { 12197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // not yet initialized 12207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initializeDefaultCenturyStart(defaultCenturyBase); 12217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return defaultCenturyStart; 12237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* Gets the default century start year for this object */ 12267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int getDefaultCenturyStartYear() { 12277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (defaultCenturyStart == null) { 12287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // not yet initialized 12297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initializeDefaultCenturyStart(defaultCenturyBase); 12307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return defaultCenturyStartYear; 12327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 12357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the 100-year period 2-digit years will be interpreted as being in 12367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to begin on the date the user specifies. 12377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param startDate During parsing, two digit years will be placed in the range 12387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>startDate</code> to <code>startDate + 100 years</code>. 12397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 12407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 12417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void set2DigitYearStart(Date startDate) { 12427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parseAmbiguousDatesAsAfter(startDate); 12437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 12467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the beginning date of the 100-year period 2-digit years are interpreted 12477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * as being within. 12487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the start of the 100-year period into which two digit years are 12497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * parsed 12507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 12517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 12527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Date get2DigitYearStart() { 12537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return getDefaultCenturyStart(); 12547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 12577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Set a particular DisplayContext value in the formatter, 12587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * such as CAPITALIZATION_FOR_STANDALONE. Note: For getContext, see 12597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateFormat. 12607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 12617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param context The DisplayContext value to set. 1262f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * @stable ICU 53 12637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 12647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Here we override the DateFormat implementation in order to lazily initialize relevant items 12657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setContext(DisplayContext context) { 12667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert super.setContext(context); 12677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (capitalizationBrkIter == null && (context==DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE || 12687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert context==DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU || 12697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert context==DisplayContext.CAPITALIZATION_FOR_STANDALONE)) { 12707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capitalizationBrkIter = BreakIterator.getSentenceInstance(locale); 12717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 12757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Formats a date or time, which is the standard millis 12767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * since January 1, 1970, 00:00:00 GMT. 12777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Example: using the US locale: 1278bee65486a185907111f3be60992433e133ec0e32Scott Russell * "yyyy.MM.dd G 'at' HH:mm:ss zzz" ->> 1996.07.10 AD at 15:08:56 PDT 12797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param cal the calendar whose date-time value is to be formatted into a date-time string 12807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param toAppendTo where the new date-time text is to be appended 12817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pos the formatting position. On input: an alignment field, 12827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * if desired. On output: the offsets of the alignment field. 12837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the formatted date-time string. 12847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see DateFormat 12857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 12867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 12877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public StringBuffer format(Calendar cal, StringBuffer toAppendTo, 12887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition pos) { 12897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert TimeZone backupTZ = null; 12907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (cal != calendar && !cal.getType().equals(calendar.getType())) { 12917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Different calendar type 12927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We use the time and time zone from the input calendar, but 12937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // do not use the input calendar for field calculation. 12947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendar.setTimeInMillis(cal.getTimeInMillis()); 12957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert backupTZ = calendar.getTimeZone(); 12967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendar.setTimeZone(cal.getTimeZone()); 12977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal = calendar; 12987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuffer result = format(cal, getContext(DisplayContext.Type.CAPITALIZATION), toAppendTo, pos, null); 13007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (backupTZ != null) { 13017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Restore the original time zone 13027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendar.setTimeZone(backupTZ); 13037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return result; 13057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The actual method to format date. If List attributes is not null, 13087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // then attribute information will be recorded. 13097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private StringBuffer format(Calendar cal, DisplayContext capitalizationContext, 13107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuffer toAppendTo, FieldPosition pos, List<FieldPosition> attributes) { 13117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Initialize 13127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setBeginIndex(0); 13137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setEndIndex(0); 13147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Careful: For best performance, minimize the number of calls 13167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // to StringBuffer.append() by consolidating appends when 13177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // possible. 13187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Object[] items = getPatternItems(); 13207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < items.length; i++) { 13217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (items[i] instanceof String) { 13227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert toAppendTo.append((String)items[i]); 13237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 13247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternItem item = (PatternItem)items[i]; 13257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int start = 0; 13267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (attributes != null) { 13277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Save the current length 13287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert start = toAppendTo.length(); 13297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useFastFormat) { 13317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert subFormat(toAppendTo, item.type, item.length, toAppendTo.length(), 13327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i, capitalizationContext, pos, cal); 13337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 13347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert toAppendTo.append(subFormat(item.type, item.length, toAppendTo.length(), 13357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i, capitalizationContext, pos, cal)); 13367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (attributes != null) { 13387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Check the sub format length 13397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int end = toAppendTo.length(); 13407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (end - start > 0) { 13417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Append the attribute to the list 13427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateFormat.Field attr = patternCharToDateFormatField(item.type); 13437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition fp = new FieldPosition(attr); 13447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fp.setBeginIndex(start); 13457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fp.setEndIndex(end); 13467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert attributes.add(fp); 13477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return toAppendTo; 13527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Map pattern character to index 13567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int[] PATTERN_CHAR_TO_INDEX = 13577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 1358f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1359f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // 1360f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1361f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // ! " # $ % & ' ( ) * + , - . / 1362f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1363f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 1364bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1365f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // @ A B C D E F G H I J K L M N O 13667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert -1, 22, -1, -1, 10, 9, 11, 0, 5, -1, -1, 16, 26, 2, -1, 31, 1367f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // P Q R S T U V W X Y Z [ \ ] ^ _ 13687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert -1, 27, -1, 8, -1, 30, 29, 13, 32, 18, 23, -1, -1, -1, -1, -1, 1369f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // ` a b c d e f g h i j k l m n o 13707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert -1, 14, -1, 25, 3, 19, -1, 21, 15, -1, -1, 4, -1, 6, -1, -1, 1371f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // p q r s t u v w x y z { | } ~ 1372f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert -1, 28, 34, 7, -1, 20, 24, 12, 33, 1, 17, -1, -1, -1, -1, -1, 13737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }; 13747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1375f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert private static int getIndexFromChar(char ch) { 1376f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert return ch < PATTERN_CHAR_TO_INDEX.length ? PATTERN_CHAR_TO_INDEX[ch & 0xff] : -1; 1377f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 1378f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 13797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Map pattern character index to Calendar field number 13807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int[] PATTERN_INDEX_TO_CALENDAR_FIELD = 13817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 13827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*GyM*/ Calendar.ERA, Calendar.YEAR, Calendar.MONTH, 13837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*dkH*/ Calendar.DATE, Calendar.HOUR_OF_DAY, Calendar.HOUR_OF_DAY, 13847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*msS*/ Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND, 13857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*EDF*/ Calendar.DAY_OF_WEEK, Calendar.DAY_OF_YEAR, Calendar.DAY_OF_WEEK_IN_MONTH, 13867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*wWa*/ Calendar.WEEK_OF_YEAR, Calendar.WEEK_OF_MONTH, Calendar.AM_PM, 13877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*hKz*/ Calendar.HOUR, Calendar.HOUR, Calendar.ZONE_OFFSET, 13887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*Yeu*/ Calendar.YEAR_WOY, Calendar.DOW_LOCAL, Calendar.EXTENDED_YEAR, 1389f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /*gAZ*/ Calendar.JULIAN_DAY, Calendar.MILLISECONDS_IN_DAY, Calendar.ZONE_OFFSET /* also DST_OFFSET */, 1390f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /*v*/ Calendar.ZONE_OFFSET /* also DST_OFFSET */, 13917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*c*/ Calendar.DOW_LOCAL, 13927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*L*/ Calendar.MONTH, 13937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*Qq*/ Calendar.MONTH, Calendar.MONTH, 1394f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /*V*/ Calendar.ZONE_OFFSET /* also DST_OFFSET */, 13957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*U*/ Calendar.YEAR, 1396f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /*O*/ Calendar.ZONE_OFFSET /* also DST_OFFSET */, 1397f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /*Xx*/ Calendar.ZONE_OFFSET /* also DST_OFFSET */, Calendar.ZONE_OFFSET /* also DST_OFFSET */, 1398f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /*r*/ Calendar.EXTENDED_YEAR /* not an exact match */, 1399f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /*:*/ -1, /* => no useful mapping to any calendar field, can't use protected Calendar.BASE_FIELD_COUNT */ 14007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }; 14017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Map pattern character index to DateFormat field number 14037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int[] PATTERN_INDEX_TO_DATE_FORMAT_FIELD = { 14047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*GyM*/ DateFormat.ERA_FIELD, DateFormat.YEAR_FIELD, DateFormat.MONTH_FIELD, 14057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*dkH*/ DateFormat.DATE_FIELD, DateFormat.HOUR_OF_DAY1_FIELD, DateFormat.HOUR_OF_DAY0_FIELD, 14067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*msS*/ DateFormat.MINUTE_FIELD, DateFormat.SECOND_FIELD, DateFormat.FRACTIONAL_SECOND_FIELD, 14077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*EDF*/ DateFormat.DAY_OF_WEEK_FIELD, DateFormat.DAY_OF_YEAR_FIELD, DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD, 14087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*wWa*/ DateFormat.WEEK_OF_YEAR_FIELD, DateFormat.WEEK_OF_MONTH_FIELD, DateFormat.AM_PM_FIELD, 14097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*hKz*/ DateFormat.HOUR1_FIELD, DateFormat.HOUR0_FIELD, DateFormat.TIMEZONE_FIELD, 14107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*Yeu*/ DateFormat.YEAR_WOY_FIELD, DateFormat.DOW_LOCAL_FIELD, DateFormat.EXTENDED_YEAR_FIELD, 14117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*gAZ*/ DateFormat.JULIAN_DAY_FIELD, DateFormat.MILLISECONDS_IN_DAY_FIELD, DateFormat.TIMEZONE_RFC_FIELD, 14127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*v*/ DateFormat.TIMEZONE_GENERIC_FIELD, 14137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*c*/ DateFormat.STANDALONE_DAY_FIELD, 14147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*L*/ DateFormat.STANDALONE_MONTH_FIELD, 14157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*Qq*/ DateFormat.QUARTER_FIELD, DateFormat.STANDALONE_QUARTER_FIELD, 14167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*V*/ DateFormat.TIMEZONE_SPECIAL_FIELD, 14177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*U*/ DateFormat.YEAR_NAME_FIELD, 14187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*O*/ DateFormat.TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD, 14197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*Xx*/ DateFormat.TIMEZONE_ISO_FIELD, DateFormat.TIMEZONE_ISO_LOCAL_FIELD, 1420f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /*r*/ DateFormat.RELATED_YEAR, 1421bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert /*(no pattern character defined for this)*/ DateFormat.TIME_SEPARATOR, 14227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }; 14237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Map pattern character index to DateFormat.Field 14257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final DateFormat.Field[] PATTERN_INDEX_TO_DATE_FORMAT_ATTRIBUTE = { 14267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*GyM*/ DateFormat.Field.ERA, DateFormat.Field.YEAR, DateFormat.Field.MONTH, 14277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*dkH*/ DateFormat.Field.DAY_OF_MONTH, DateFormat.Field.HOUR_OF_DAY1, DateFormat.Field.HOUR_OF_DAY0, 14287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*msS*/ DateFormat.Field.MINUTE, DateFormat.Field.SECOND, DateFormat.Field.MILLISECOND, 14297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*EDF*/ DateFormat.Field.DAY_OF_WEEK, DateFormat.Field.DAY_OF_YEAR, DateFormat.Field.DAY_OF_WEEK_IN_MONTH, 14307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*wWa*/ DateFormat.Field.WEEK_OF_YEAR, DateFormat.Field.WEEK_OF_MONTH, DateFormat.Field.AM_PM, 14317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*hKz*/ DateFormat.Field.HOUR1, DateFormat.Field.HOUR0, DateFormat.Field.TIME_ZONE, 14327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*Yeu*/ DateFormat.Field.YEAR_WOY, DateFormat.Field.DOW_LOCAL, DateFormat.Field.EXTENDED_YEAR, 14337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*gAZ*/ DateFormat.Field.JULIAN_DAY, DateFormat.Field.MILLISECONDS_IN_DAY, DateFormat.Field.TIME_ZONE, 14347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*v*/ DateFormat.Field.TIME_ZONE, 14357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*c*/ DateFormat.Field.DAY_OF_WEEK, 14367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*L*/ DateFormat.Field.MONTH, 14377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*Qq*/ DateFormat.Field.QUARTER, DateFormat.Field.QUARTER, 14387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*V*/ DateFormat.Field.TIME_ZONE, 14397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*U*/ DateFormat.Field.YEAR, 14407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*O*/ DateFormat.Field.TIME_ZONE, 14417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*Xx*/ DateFormat.Field.TIME_ZONE, DateFormat.Field.TIME_ZONE, 1442f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /*r*/ DateFormat.Field.RELATED_YEAR, 1443bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert /*(no pattern character defined for this)*/ DateFormat.Field.TIME_SEPARATOR, 14447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }; 14457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 14477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns a DateFormat.Field constant associated with the specified format pattern 14487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * character. 14497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 14507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ch The pattern character 14517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return DateFormat.Field associated with the pattern character 14527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 14537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 14547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 14557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert protected DateFormat.Field patternCharToDateFormatField(char ch) { 1456f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert int patternCharIndex = getIndexFromChar(ch); 14577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (patternCharIndex != -1) { 14587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return PATTERN_INDEX_TO_DATE_FORMAT_ATTRIBUTE[patternCharIndex]; 14597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 14617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 14647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Formats a single field, given its pattern character. Subclasses may 14657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * override this method in order to modify or add formatting 14667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * capabilities. 14677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ch the pattern character 14687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param count the number of times ch is repeated in the pattern 14697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param beginOffset the offset of the output string at the start of 14707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * this field; used to set pos when appropriate 14717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pos receives the position of a field, when appropriate 14727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param fmtData the symbols for this formatter 14737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 14747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 14757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert protected String subFormat(char ch, int count, int beginOffset, 14767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition pos, DateFormatSymbols fmtData, 14777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar cal) 14787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throws IllegalArgumentException 14797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 14807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Note: formatData is ignored 14817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return subFormat(ch, count, beginOffset, 0, DisplayContext.CAPITALIZATION_NONE, pos, cal); 14827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 14857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Formats a single field. This is the version called internally; it 14867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * adds fieldNum and capitalizationContext parameters. 14877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 14887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 14897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 14907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 14917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 14927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert protected String subFormat(char ch, int count, int beginOffset, 14937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int fieldNum, DisplayContext capitalizationContext, 14947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition pos, 14957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar cal) 14967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 14977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuffer buf = new StringBuffer(); 14987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert subFormat(buf, ch, count, beginOffset, fieldNum, capitalizationContext, pos, cal); 14997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return buf.toString(); 15007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 15037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Formats a single field; useFastFormat variant. Reuses a 15047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * StringBuffer for results instead of creating a String on the 15057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * heap for each call. 15067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 15077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * NOTE We don't really need the beginOffset parameter, EXCEPT for 15087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the need to support the slow subFormat variant (above) which 15097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * has to pass it in to us. 15107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 15117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 15127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 15137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 15147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 15157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @SuppressWarnings("fallthrough") 15167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert protected void subFormat(StringBuffer buf, 15177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char ch, int count, int beginOffset, 15187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int fieldNum, DisplayContext capitalizationContext, 15197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition pos, 15207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar cal) { 15217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert final int maxIntCount = Integer.MAX_VALUE; 15237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert final int bufstart = buf.length(); 15247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert TimeZone tz = cal.getTimeZone(); 15257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert long date = cal.getTimeInMillis(); 15267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String result = null; 15277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1528f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert int patternCharIndex = getIndexFromChar(ch); 15297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (patternCharIndex == -1) { 15307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch == 'l') { // (SMALL LETTER L) deprecated placeholder for leap month marker, ignore 15317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return; 15327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 15337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Illegal pattern character " + 15347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "'" + ch + "' in \"" + 15357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pattern + '"'); 15367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert final int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex]; 1540f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert int value = 0; 1541f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // Don't get value unless it is useful 1542f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if (field >= 0) { 1543f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert value = (patternCharIndex != DateFormat.RELATED_YEAR)? cal.get(field): cal.getRelatedYear(); 1544f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 15457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert NumberFormat currentNumberFormat = getNumberFormat(ch); 15477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateFormatSymbols.CapitalizationContextUsage capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.OTHER; 15487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert switch (patternCharIndex) { 15507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 0: // 'G' - ERA 15517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( cal.getType().equals("chinese") || cal.getType().equals("dangi") ) { 15527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // moved from ChineseDateFormat 15537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert zeroPaddingNumber(currentNumberFormat, buf, value, 1, 9); 15547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 15557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count == 5) { 15567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppend(formatData.narrowEras, value, buf); 15577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.ERA_NARROW; 15587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 4) { 15597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppend(formatData.eraNames, value, buf); 15607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.ERA_WIDE; 15617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 15627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppend(formatData.eras, value, buf); 15637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.ERA_ABBREV; 15647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 15677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 30: // 'U' - YEAR_NAME_FIELD 15687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (formatData.shortYearNames != null && value <= formatData.shortYearNames.length) { 15697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppend(formatData.shortYearNames, value-1, buf); 15707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 15717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // else fall through to numeric year handling, do not break here 15737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 1: // 'y' - YEAR 15747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 18: // 'Y' - YEAR_WOY 15757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( override != null && (override.compareTo("hebr") == 0 || override.indexOf("y=hebr") >= 0) && 15767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert value > HEBREW_CAL_CUR_MILLENIUM_START_YEAR && value < HEBREW_CAL_CUR_MILLENIUM_END_YEAR ) { 15777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert value -= HEBREW_CAL_CUR_MILLENIUM_START_YEAR; 15787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* According to the specification, if the number of pattern letters ('y') is 2, 15807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the year is truncated to 2 digits; otherwise it is interpreted as a number. 15817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * But the original code process 'y', 'yy', 'yyy' in the same way. and process 15827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * patterns with 4 or more than 4 'y' characters in the same way. 15837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * So I change the codes to meet the specification. [Richard/GCl] 15847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 15857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count == 2) { 15867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert zeroPaddingNumber(currentNumberFormat,buf, value, 2, 2); // clip 1996 to 96 15877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { //count = 1 or count > 2 15887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert zeroPaddingNumber(currentNumberFormat,buf, value, count, maxIntCount); 15897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 15917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 2: // 'M' - MONTH 15927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 26: // 'L' - STANDALONE MONTH 15937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( cal.getType().equals("hebrew")) { 15947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isLeap = HebrewCalendar.isLeapYear(cal.get(Calendar.YEAR)); 15957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isLeap && value == 6 && count >= 3 ) { 15967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert value = 13; // Show alternate form for Adar II in leap years in Hebrew calendar. 15977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!isLeap && value >= 6 && count < 3 ) { 15997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert value--; // Adjust the month number down 1 in Hebrew non-leap years, i.e. Adar is 6, not 7. 16007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int isLeapMonth = (formatData.leapMonthPatterns != null && formatData.leapMonthPatterns.length >= DateFormatSymbols.DT_MONTH_PATTERN_COUNT)? 16037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.get(Calendar.IS_LEAP_MONTH): 0; 16047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // should consolidate the next section by using arrays of pointers & counts for the right symbols... 16057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count == 5) { 16067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (patternCharIndex == 2) { 16077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppendWithMonthPattern(formatData.narrowMonths, value, buf, (isLeapMonth!=0)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_FORMAT_NARROW]: null); 16087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 16097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppendWithMonthPattern(formatData.standaloneNarrowMonths, value, buf, (isLeapMonth!=0)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_STANDALONE_NARROW]: null); 16107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.MONTH_NARROW; 16127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 4) { 16137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (patternCharIndex == 2) { 16147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppendWithMonthPattern(formatData.months, value, buf, (isLeapMonth!=0)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_FORMAT_WIDE]: null); 16157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.MONTH_FORMAT; 16167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 16177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppendWithMonthPattern(formatData.standaloneMonths, value, buf, (isLeapMonth!=0)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_STANDALONE_WIDE]: null); 16187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.MONTH_STANDALONE; 16197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 3) { 16217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (patternCharIndex == 2) { 16227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppendWithMonthPattern(formatData.shortMonths, value, buf, (isLeapMonth!=0)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_FORMAT_ABBREV]: null); 16237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.MONTH_FORMAT; 16247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 16257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppendWithMonthPattern(formatData.standaloneShortMonths, value, buf, (isLeapMonth!=0)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_STANDALONE_ABBREV]: null); 16267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.MONTH_STANDALONE; 16277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 16297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuffer monthNumber = new StringBuffer(); 16307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert zeroPaddingNumber(currentNumberFormat, monthNumber, value+1, count, maxIntCount); 16317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String[] monthNumberStrings = new String[1]; 16327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert monthNumberStrings[0] = monthNumber.toString(); 16337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppendWithMonthPattern(monthNumberStrings, 0, buf, (isLeapMonth!=0)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_NUMERIC]: null); 16347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 16367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 4: // 'k' - HOUR_OF_DAY (1..24) 16377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (value == 0) { 16387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert zeroPaddingNumber(currentNumberFormat,buf, 16397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.getMaximum(Calendar.HOUR_OF_DAY)+1, 16407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count, maxIntCount); 16417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 16427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert zeroPaddingNumber(currentNumberFormat,buf, value, count, maxIntCount); 16437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 16457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 8: // 'S' - FRACTIONAL_SECOND 16467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Fractional seconds left-justify 16477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 16487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberFormat.setMinimumIntegerDigits(Math.min(3, count)); 16497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberFormat.setMaximumIntegerDigits(maxIntCount); 16507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count == 1) { 16517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert value /= 100; 16527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 2) { 16537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert value /= 10; 16547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition p = new FieldPosition(-1); 16567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberFormat.format((long) value, buf, p); 16577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count > 3) { 16587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberFormat.setMinimumIntegerDigits(count - 3); 16597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberFormat.format(0L, buf, p); 16607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 16637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 19: // 'e' - DOW_LOCAL (use DOW_LOCAL for numeric, DAY_OF_WEEK for format names) 16647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count < 3) { 16657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert zeroPaddingNumber(currentNumberFormat,buf, value, count, maxIntCount); 16667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 16677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // For alpha day-of-week, we don't want DOW_LOCAL, 16697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // we need the standard DAY_OF_WEEK. 16707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert value = cal.get(Calendar.DAY_OF_WEEK); 16717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // fall through, do not break here 16727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 9: // 'E' - DAY_OF_WEEK 16737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count == 5) { 16747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppend(formatData.narrowWeekdays, value, buf); 16757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.DAY_NARROW; 16767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 4) { 16777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppend(formatData.weekdays, value, buf); 16787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.DAY_FORMAT; 16797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 6 && formatData.shorterWeekdays != null) { 16807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppend(formatData.shorterWeekdays, value, buf); 16817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.DAY_FORMAT; 16827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else {// count <= 3, use abbreviated form if exists 16837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppend(formatData.shortWeekdays, value, buf); 16847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.DAY_FORMAT; 16857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 16877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 14: // 'a' - AM_PM 1688f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // formatData.ampmsNarrow may be null when deserializing DateFormatSymbolsfrom old version 1689f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if (count < 5 || formatData.ampmsNarrow == null) { 1690f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert safeAppend(formatData.ampms, value, buf); 1691f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } else { 1692f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert safeAppend(formatData.ampmsNarrow, value, buf); 1693f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 16947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 16957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 15: // 'h' - HOUR (1..12) 16967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (value == 0) { 16977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert zeroPaddingNumber(currentNumberFormat,buf, 16987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.getLeastMaximum(Calendar.HOUR)+1, 16997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count, maxIntCount); 17007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 17017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert zeroPaddingNumber(currentNumberFormat,buf, value, count, maxIntCount); 17027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 17047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 17057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 17: // 'z' - TIMEZONE_FIELD 17067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count < 4) { 17077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "z", "zz", "zzz" 17087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.SPECIFIC_SHORT, tz, date); 17097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.METAZONE_SHORT; 17107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 17117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.SPECIFIC_LONG, tz, date); 17127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.METAZONE_LONG; 17137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(result); 17157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 17167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 23: // 'Z' - TIMEZONE_RFC_FIELD 17177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count < 4) { 17187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // RFC822 format - equivalent to ISO 8601 local offset fixed width format 17197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.ISO_BASIC_LOCAL_FULL, tz, date); 17207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 5) { 17217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ISO 8601 extended format 17227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.ISO_EXTENDED_FULL, tz, date); 17237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 17247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // long form, localized GMT pattern 17257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.LOCALIZED_GMT, tz, date); 17267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(result); 17287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 17297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 24: // 'v' - TIMEZONE_GENERIC_FIELD 17307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count == 1) { 17317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "v" 17327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.GENERIC_SHORT, tz, date); 17337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.METAZONE_SHORT; 17347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 4) { 17357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "vvvv" 17367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.GENERIC_LONG, tz, date); 17377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.METAZONE_LONG; 17387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(result); 17407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 17417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 29: // 'V' - TIMEZONE_SPECIAL_FIELD 17427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count == 1) { 17437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "V" 17447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.ZONE_ID_SHORT, tz, date); 17457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 2) { 17467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "VV" 17477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.ZONE_ID, tz, date); 17487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 3) { 17497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "VVV" 17507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.EXEMPLAR_LOCATION, tz, date); 17517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 4) { 17527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "VVVV" 17537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.GENERIC_LOCATION, tz, date); 17547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.ZONE_LONG; 17557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(result); 17577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 17587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 31: // 'O' - TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD 17597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count == 1) { 17607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "O" - Short Localized GMT format 17617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.LOCALIZED_GMT_SHORT, tz, date); 17627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 4) { 17637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "OOOO" - Localized GMT format 17647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.LOCALIZED_GMT, tz, date); 17657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(result); 17677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 17687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 32: // 'X' - TIMEZONE_ISO_FIELD 17697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count == 1) { 17707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "X" - ISO Basic/Short 17717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.ISO_BASIC_SHORT, tz, date); 17727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 2) { 17737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "XX" - ISO Basic/Fixed 17747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.ISO_BASIC_FIXED, tz, date); 17757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 3) { 17767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "XXX" - ISO Extended/Fixed 17777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.ISO_EXTENDED_FIXED, tz, date); 17787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 4) { 17797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "XXXX" - ISO Basic/Optional second field 17807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.ISO_BASIC_FULL, tz, date); 17817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 5) { 17827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "XXXXX" - ISO Extended/Optional second field 17837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.ISO_EXTENDED_FULL, tz, date); 17847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(result); 17867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 17877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 33: // 'x' - TIMEZONE_ISO_LOCAL_FIELD 17887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count == 1) { 17897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "x" - ISO Local Basic/Short 17907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.ISO_BASIC_LOCAL_SHORT, tz, date); 17917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 2) { 17927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "x" - ISO Local Basic/Fixed 17937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.ISO_BASIC_LOCAL_FIXED, tz, date); 17947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 3) { 17957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "xxx" - ISO Local Extended/Fixed 17967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.ISO_EXTENDED_LOCAL_FIXED, tz, date); 17977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 4) { 17987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "xxxx" - ISO Local Basic/Optional second field 17997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.ISO_BASIC_LOCAL_FULL, tz, date); 18007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 5) { 18017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "xxxxx" - ISO Local Extended/Optional second field 18027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = tzFormat().format(Style.ISO_EXTENDED_LOCAL_FULL, tz, date); 18037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(result); 18057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 18067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 18077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 25: // 'c' - STANDALONE DAY (use DOW_LOCAL for numeric, DAY_OF_WEEK for standalone) 18087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count < 3) { 18097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert zeroPaddingNumber(currentNumberFormat,buf, value, 1, maxIntCount); 18107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 18117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // For alpha day-of-week, we don't want DOW_LOCAL, 18137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // we need the standard DAY_OF_WEEK. 18147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert value = cal.get(Calendar.DAY_OF_WEEK); 18157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count == 5) { 18167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppend(formatData.standaloneNarrowWeekdays, value, buf); 18177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.DAY_NARROW; 18187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 4) { 18197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppend(formatData.standaloneWeekdays, value, buf); 18207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.DAY_STANDALONE; 18217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 6 && formatData.standaloneShorterWeekdays != null) { 18227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppend(formatData.standaloneShorterWeekdays, value, buf); 18237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.DAY_STANDALONE; 18247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { // count == 3 18257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppend(formatData.standaloneShortWeekdays, value, buf); 18267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.DAY_STANDALONE; 18277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 18297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 27: // 'Q' - QUARTER 18307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count >= 4) { 18317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppend(formatData.quarters, value/3, buf); 18327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 3) { 18337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppend(formatData.shortQuarters, value/3, buf); 18347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 18357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert zeroPaddingNumber(currentNumberFormat,buf, (value/3)+1, count, maxIntCount); 18367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 18387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 28: // 'q' - STANDALONE QUARTER 18397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count >= 4) { 18407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppend(formatData.standaloneQuarters, value/3, buf); 18417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 3) { 18427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert safeAppend(formatData.standaloneShortQuarters, value/3, buf); 18437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 18447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert zeroPaddingNumber(currentNumberFormat,buf, (value/3)+1, count, maxIntCount); 18457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 1847bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 35: // TIME SEPARATOR (no pattern character currently defined, we should 1848bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // not get here but leave support in for future definition. 1849f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert buf.append(formatData.getTimeSeparatorString()); 1850f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert break; 18517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert default: 18527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 3: // 'd' - DATE 18537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 5: // 'H' - HOUR_OF_DAY (0..23) 18547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 6: // 'm' - MINUTE 18557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 7: // 's' - SECOND 18567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 10: // 'D' - DAY_OF_YEAR 18577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 11: // 'F' - DAY_OF_WEEK_IN_MONTH 18587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 12: // 'w' - WEEK_OF_YEAR 18597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 13: // 'W' - WEEK_OF_MONTH 18607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 16: // 'K' - HOUR (0..11) 18617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 20: // 'u' - EXTENDED_YEAR 18627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 21: // 'g' - JULIAN_DAY 18637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 22: // 'A' - MILLISECONDS_IN_DAY 18647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 18657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert zeroPaddingNumber(currentNumberFormat,buf, value, count, maxIntCount); 18667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 18677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } // switch (patternCharIndex) 18687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 18697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldNum == 0 && capitalizationContext != null && UCharacter.isLowerCase(buf.codePointAt(bufstart))) { 18707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean titlecase = false; 18717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert switch (capitalizationContext) { 18727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE: 18737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert titlecase = true; 18747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 18757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case CAPITALIZATION_FOR_UI_LIST_OR_MENU: 18767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case CAPITALIZATION_FOR_STANDALONE: 18777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (formatData.capitalization != null) { 18787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean[] transforms = formatData.capitalization.get(capContextUsageType); 18797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert titlecase = (capitalizationContext==DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU)? 18807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert transforms[0]: transforms[1]; 18817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 18837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert default: 18847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 18857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (titlecase) { 18877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (capitalizationBrkIter == null) { 18887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // should only happen when deserializing, etc. 18897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert capitalizationBrkIter = BreakIterator.getSentenceInstance(locale); 18907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String firstField = buf.substring(bufstart); // bufstart or beginOffset, should be the same 18927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String firstFieldTitleCase = UCharacter.toTitleCase(locale, firstField, capitalizationBrkIter, 18937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UCharacter.TITLECASE_NO_LOWERCASE | UCharacter.TITLECASE_NO_BREAK_ADJUSTMENT); 18947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.replace(bufstart, buf.length(), firstFieldTitleCase); 18957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 18987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Set the FieldPosition (for the first occurrence only) 18997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos.getBeginIndex() == pos.getEndIndex()) { 19007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos.getField() == PATTERN_INDEX_TO_DATE_FORMAT_FIELD[patternCharIndex]) { 19017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setBeginIndex(beginOffset); 19027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setEndIndex(beginOffset + buf.length() - bufstart); 19037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (pos.getFieldAttribute() == 19047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PATTERN_INDEX_TO_DATE_FORMAT_ATTRIBUTE[patternCharIndex]) { 19057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setBeginIndex(beginOffset); 19067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setEndIndex(beginOffset + buf.length() - bufstart); 19077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static void safeAppend(String[] array, int value, StringBuffer appendTo) { 19127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (array != null && value >= 0 && value < array.length) { 19137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert appendTo.append(array[value]); 19147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static void safeAppendWithMonthPattern(String[] array, int value, StringBuffer appendTo, String monthPattern) { 19187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (array != null && value >= 0 && value < array.length) { 19197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (monthPattern == null) { 19207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert appendTo.append(array[value]); 19217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 19227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert appendTo.append(MessageFormat.format(monthPattern, array[value])); 19237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 19287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * PatternItem store parsed date/time field pattern information. 19297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 19307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static class PatternItem { 19317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert final char type; 19327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert final int length; 19337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert final boolean isNumeric; 19347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternItem(char type, int length) { 19367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.type = type; 19377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.length = length; 19387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert isNumeric = isNumeric(type, length); 19397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static ICUCache<String, Object[]> PARSED_PATTERN_CACHE = 19437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert new SimpleCache<String, Object[]>(); 19447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient Object[] patternItems; 19457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 19477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns parsed pattern items. Each item is either String or 19487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * PatternItem. 19497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 19507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Object[] getPatternItems() { 19517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (patternItems != null) { 19527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return patternItems; 19537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternItems = PARSED_PATTERN_CACHE.get(pattern); 19567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (patternItems != null) { 19577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return patternItems; 19587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isPrevQuote = false; 19617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean inQuote = false; 19627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder text = new StringBuilder(); 19637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char itemType = 0; // 0 for string literal, otherwise date/time pattern character 19647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int itemLength = 1; 19657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert List<Object> items = new ArrayList<Object>(); 19677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < pattern.length(); i++) { 19697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char ch = pattern.charAt(i); 19707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch == '\'') { 19717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isPrevQuote) { 19727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert text.append('\''); 19737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert isPrevQuote = false; 19747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 19757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert isPrevQuote = true; 19767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (itemType != 0) { 19777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert items.add(new PatternItem(itemType, itemLength)); 19787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert itemType = 0; 19797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert inQuote = !inQuote; 19827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 19837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert isPrevQuote = false; 19847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (inQuote) { 19857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert text.append(ch); 19867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 1987f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if (isSyntaxChar(ch)) { 19887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // a date/time pattern character 19897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch == itemType) { 19907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert itemLength++; 19917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 19927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (itemType == 0) { 19937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (text.length() > 0) { 19947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert items.add(text.toString()); 19957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert text.setLength(0); 19967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 19987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert items.add(new PatternItem(itemType, itemLength)); 19997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert itemType = ch; 20017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert itemLength = 1; 20027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 20047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // a string literal 20057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (itemType != 0) { 20067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert items.add(new PatternItem(itemType, itemLength)); 20077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert itemType = 0; 20087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert text.append(ch); 20107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // handle last item 20157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (itemType == 0) { 20167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (text.length() > 0) { 20177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert items.add(text.toString()); 20187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert text.setLength(0); 20197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 20217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert items.add(new PatternItem(itemType, itemLength)); 20227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 20247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternItems = items.toArray(new Object[items.size()]); 20257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 20267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PARSED_PATTERN_CACHE.put(pattern, patternItems); 20277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 20287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return patternItems; 20297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 20317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 20327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Internal high-speed method. Reuses a StringBuffer for results 20337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * instead of creating a String on the heap for each call. 20347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 20357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 20367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 20377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 20387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert protected void zeroPaddingNumber(NumberFormat nf,StringBuffer buf, int value, 20397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int minDigits, int maxDigits) { 20407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Note: Indian calendar uses negative value for a calendar 20417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // field. fastZeroPaddingNumber cannot handle negative numbers. 20427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // BTW, it looks like a design bug in the Indian calendar... 20437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useLocalZeroPaddingNumberFormat && value >= 0) { 20447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fastZeroPaddingNumber(buf, value, minDigits, maxDigits); 20457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 20467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert nf.setMinimumIntegerDigits(minDigits); 20477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert nf.setMaximumIntegerDigits(maxDigits); 20487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert nf.format(value, buf, new FieldPosition(-1)); 20497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 20527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 20537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Overrides superclass method and 20547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This method also clears per field NumberFormat instances 20557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * previously set by {@link #setNumberFormat(String, NumberFormat)} 20567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 20577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 20587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 20597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setNumberFormat(NumberFormat newNumberFormat) { 20607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Override this method to update local zero padding number formatter 20617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert super.setNumberFormat(newNumberFormat); 20627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initLocalZeroPaddingNumberFormat(); 20637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initializeTimeZoneFormat(true); 20647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 20657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (numberFormatters != null) { 20667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberFormatters = null; 20677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (overrideMap != null) { 20697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert overrideMap = null; 20707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2073f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /* 2074f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * Initializes transient fields for fast simple numeric formatting 2075f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * code. This method should be called whenever number format is updated. 2076f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert */ 20777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void initLocalZeroPaddingNumberFormat() { 20787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (numberFormat instanceof DecimalFormat) { 20797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decDigits = ((DecimalFormat)numberFormat).getDecimalFormatSymbols().getDigits(); 20807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert useLocalZeroPaddingNumberFormat = true; 20817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (numberFormat instanceof DateNumberFormat) { 20827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decDigits = ((DateNumberFormat)numberFormat).getDigits(); 20837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert useLocalZeroPaddingNumberFormat = true; 20847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 20857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert useLocalZeroPaddingNumberFormat = false; 20867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 20887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useLocalZeroPaddingNumberFormat) { 2089f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert decimalBuf = new char[DECIMAL_BUF_SIZE]; 20907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 20937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If true, use local version of zero padding number format 20947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient boolean useLocalZeroPaddingNumberFormat; 2095f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert private transient char[] decDigits; // read-only - can be shared by multiple instances 2096f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert private transient char[] decimalBuf; // mutable - one per instance 2097f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert private static final int DECIMAL_BUF_SIZE = 10; // sufficient for int numbers 20987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 20997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 21007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Lightweight zero padding integer number format function. 21017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 21027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Note: This implementation is almost equivalent to format method in DateNumberFormat. 21037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * In the method zeroPaddingNumber above should be able to use the one in DateNumberFormat, 21047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * but, it does not help IBM J9's JIT to optimize the performance much. In simple repeative 21057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * date format test case, having local implementation is ~10% faster than using one in 21067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DateNumberFormat on IBM J9 VM. On Sun Hotspot VM, I do not see such difference. 21077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 21087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * -Yoshito 21097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 21107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void fastZeroPaddingNumber(StringBuffer buf, int value, int minDigits, int maxDigits) { 21117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int limit = decimalBuf.length < maxDigits ? decimalBuf.length : maxDigits; 21127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int index = limit - 1; 21137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (true) { 21147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decimalBuf[index] = decDigits[(value % 10)]; 21157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert value /= 10; 21167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (index == 0 || value == 0) { 21177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 21187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert index--; 21207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int padding = minDigits - (limit - index); 21227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (padding > 0 && index > 0) { 21237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decimalBuf[--index] = decDigits[0]; 21247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert padding--; 21257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (padding > 0) { 21277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // when pattern width is longer than decimalBuf, need extra 21287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // leading zeros - ticke#7595 21297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(decDigits[0]); 21307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert padding--; 21317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(decimalBuf, index, limit - index); 21337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 21357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 21367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Formats a number with the specified minimum and maximum number of digits. 21377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 21387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 21397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert protected String zeroPaddingNumber(long value, int minDigits, int maxDigits) 21407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 21417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberFormat.setMinimumIntegerDigits(minDigits); 21427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberFormat.setMaximumIntegerDigits(maxDigits); 21437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return numberFormat.format(value); 21447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 21467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2147bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Format characters that indicate numeric fields always. 2148bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert */ 2149bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private static final String NUMERIC_FORMAT_CHARS = "ADdFgHhKkmrSsuWwYy"; 2150bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 2151bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert /** 2152bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Format characters that indicate numeric fields when pattern lengh 2153bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * is up to 2. 21547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2155bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert private static final String NUMERIC_FORMAT_CHARS2 = "ceLMQq"; 21567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 21577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 21587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Return true if the given format character, occuring count 21597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * times, represents a numeric field. 21607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 21617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final boolean isNumeric(char formatChar, int count) { 2162bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert return NUMERIC_FORMAT_CHARS.indexOf(formatChar) >= 0 2163bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert || (count <= 2 && NUMERIC_FORMAT_CHARS2.indexOf(formatChar) >= 0); 21647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 21667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 21677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Overrides DateFormat 21687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see DateFormat 21697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 21707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 21717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void parse(String text, Calendar cal, ParsePosition parsePos) 21727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 21737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert TimeZone backupTZ = null; 21747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar resultCal = null; 21757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (cal != calendar && !cal.getType().equals(calendar.getType())) { 21767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Different calendar type 21777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We use the time/zone from the input calendar, but 21787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // do not use the input calendar for field calculation. 21797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendar.setTimeInMillis(cal.getTimeInMillis()); 21807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert backupTZ = calendar.getTimeZone(); 21817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendar.setTimeZone(cal.getTimeZone()); 21827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resultCal = cal; 21837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal = calendar; 21847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 21867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int pos = parsePos.getIndex(); 21877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(pos < 0) { 21887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePos.setErrorIndex(0); 21897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return; 21907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int start = pos; 21927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 21937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Output<TimeType> tzTimeType = new Output<TimeType>(TimeType.UNKNOWN); 21947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean[] ambiguousYear = { false }; 21957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 21967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // item index for the first numeric field within a contiguous numeric run 21977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int numericFieldStart = -1; 21987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // item length for the first numeric field within a contiguous numeric run 21997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int numericFieldLength = 0; 22007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // start index of numeric text run in the input text 22017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int numericStartPos = 0; 22027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert MessageFormat numericLeapMonthFormatter = null; 22047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (formatData.leapMonthPatterns != null && formatData.leapMonthPatterns.length >= DateFormatSymbols.DT_MONTH_PATTERN_COUNT) { 22057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numericLeapMonthFormatter = new MessageFormat(formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_NUMERIC], locale); 22067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 22077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Object[] items = getPatternItems(); 22097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int i = 0; 22107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (i < items.length) { 22117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (items[i] instanceof PatternItem) { 22127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Handle pattern field 22137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternItem field = (PatternItem)items[i]; 22147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (field.isNumeric) { 22157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Handle fields within a run of abutting numeric fields. Take 22167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the pattern "HHmmss" as an example. We will try to parse 22177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 2/2/2 characters of the input text, then if that fails, 22187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 1/2/2. We only adjust the width of the leftmost field; the 22197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // others remain fixed. This allows "123456" => 12:34:56, but 22207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "12345" => 1:23:45. Likewise, for the pattern "yyyyMMdd" we 22217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // try 4/2/2, 3/2/2, 2/2/2, and finally 1/2/2. 22227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (numericFieldStart == -1) { 22237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // check if this field is followed by abutting another numeric field 22247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((i + 1) < items.length 22257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && (items[i + 1] instanceof PatternItem) 22267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && ((PatternItem)items[i + 1]).isNumeric) { 22277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // record the first numeric field within a numeric text run 22287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numericFieldStart = i; 22297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numericFieldLength = field.length; 22307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numericStartPos = pos; 22317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 22327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 22337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 22347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (numericFieldStart != -1) { 22357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Handle a numeric field within abutting numeric fields 22367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int len = field.length; 22377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (numericFieldStart == i) { 22387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert len = numericFieldLength; 22397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 22407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Parse a numeric field 22427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = subParse(text, pos, field.type, len, 22437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert true, false, ambiguousYear, cal, numericLeapMonthFormatter, tzTimeType); 22447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos < 0) { 22467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If the parse fails anywhere in the numeric run, back up to the 22477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // start of the run and use shorter pattern length for the first 22487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // numeric field. 22497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert --numericFieldLength; 22507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (numericFieldLength == 0) { 22517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // can not make shorter any more 22527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePos.setIndex(start); 22537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePos.setErrorIndex(pos); 22547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (backupTZ != null) { 22557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendar.setTimeZone(backupTZ); 22567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 22577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return; 22587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 22597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i = numericFieldStart; 22607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = numericStartPos; 22617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 22627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 22637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (field.type != 'l') { // (SMALL LETTER L) obsolete pattern char just gets ignored 22657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Handle a non-numeric field or a non-abutting numeric field 22667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numericFieldStart = -1; 22677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int s = pos; 22697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = subParse(text, pos, field.type, field.length, 22707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert false, true, ambiguousYear, cal, numericLeapMonthFormatter, tzTimeType); 22717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos < 0) { 22737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos == ISOSpecialEra) { 22747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // era not present, in special cases allow this to continue 22757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = s; 22767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (i+1 < items.length) { 22787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String patl = null; 22807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // if it will cause a class cast exception to String, we can't use it 22817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 22827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patl = (String)items[i+1]; 22837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch(ClassCastException cce) { 22847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePos.setIndex(start); 22857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePos.setErrorIndex(s); 22867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (backupTZ != null) { 22877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendar.setTimeZone(backupTZ); 22887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 22897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return; 22907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 22917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // get next item in pattern 22937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(patl == null) 22947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patl = (String)items[i+1]; 22957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int plen = patl.length(); 22967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int idx=0; 22977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // White space characters found in patten. 22997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Skip contiguous white spaces. 23007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (idx < plen) { 23017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char pch = patl.charAt(idx); 23037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (PatternProps.isWhiteSpace(pch)) 23047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert idx++; 23057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert else 23067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 23077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // if next item in pattern is all whitespace, skip it 23107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (idx == plen) { 23117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i++; 23127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 23167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePos.setIndex(start); 23177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePos.setErrorIndex(s); 23187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (backupTZ != null) { 23197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendar.setTimeZone(backupTZ); 23207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return; 23227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2324f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 23257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 23277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Handle literal pattern text literal 23287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numericFieldStart = -1; 23297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean[] complete = new boolean[1]; 23307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = matchLiteral(text, pos, items, i, complete); 23317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!complete[0]) { 23327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Set the position of mismatch 23337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePos.setIndex(start); 23347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePos.setErrorIndex(pos); 23357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (backupTZ != null) { 23367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendar.setTimeZone(backupTZ); 23377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return; 23397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++i; 23427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Special hack for trailing "." after non-numeric field. 23457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos < text.length()) { 23467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char extra = text.charAt(pos); 23477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (extra == '.' && getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_ALLOW_WHITESPACE) && items.length != 0) { 23487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // only do if the last field is not numeric 23497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Object lastItem = items[items.length - 1]; 23507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (lastItem instanceof PatternItem && !((PatternItem)lastItem).isNumeric) { 23517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos++; // skip the extra "." 23527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // At this point the fields of Calendar have been set. Calendar 23577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // will fill in default values for missing fields when the time 23587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // is computed. 23597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePos.setIndex(pos); 23617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // This part is a problem: When we call parsedDate.after, we compute the time. 23637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Take the date April 3 2004 at 2:30 am. When this is first set up, the year 23647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // will be wrong if we're parsing a 2-digit year pattern. It will be 1904. 23657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // April 3 1904 is a Sunday (unlike 2004) so it is the DST onset day. 2:30 am 23667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // is therefore an "impossible" time, since the time goes from 1:59 to 3:00 am 23677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // on that day. It is therefore parsed out to fields as 3:30 am. Then we 23687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // add 100 years, and get April 3 2004 at 3:30 am. Note that April 3 2004 is 23697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // a Saturday, so it can have a 2:30 am -- and it should. [LIU] 23707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 23717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Date parsedDate = cal.getTime(); 23727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if( ambiguousYear[0] && !parsedDate.after(getDefaultCenturyStart()) ) { 23737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.add(Calendar.YEAR, 100); 23747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsedDate = cal.getTime(); 23757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 23777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Because of the above condition, save off the fields in case we need to readjust. 23787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The procedure we use here is not particularly efficient, but there is no other 23797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // way to do this given the API restrictions present in Calendar. We minimize 23807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // inefficiency by only performing this computation when it might apply, that is, 23817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // when the two-digit year is equal to the start year, and thus might fall at the 23827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // front or the back of the default century. This only works because we adjust 23837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the year correctly to start with in other cases -- see subParse(). 23847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 23857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert TimeType tztype = tzTimeType.value; 23867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ambiguousYear[0] || tztype != TimeType.UNKNOWN) { 23877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We need a copy of the fields, and we need to avoid triggering a call to 23887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // complete(), which will recalculate the fields. Since we can't access 23897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the fields[] array in Calendar, we clone the entire object. This will 23907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // stop working if Calendar.clone() is ever rewritten to call complete(). 23917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar copy; 23927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ambiguousYear[0]) { // the two-digit year == the default start year 23937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert copy = (Calendar)cal.clone(); 23947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Date parsedDate = copy.getTime(); 23957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (parsedDate.before(getDefaultCenturyStart())) { 23967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We can't use add here because that does a complete() first. 23977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(Calendar.YEAR, getDefaultCenturyStartYear() + 100); 23987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tztype != TimeType.UNKNOWN) { 24017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert copy = (Calendar)cal.clone(); 24027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert TimeZone tz = copy.getTimeZone(); 24037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert BasicTimeZone btz = null; 24047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tz instanceof BasicTimeZone) { 24057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert btz = (BasicTimeZone)tz; 24067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Get local millis 24097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert copy.set(Calendar.ZONE_OFFSET, 0); 24107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert copy.set(Calendar.DST_OFFSET, 0); 24117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert long localMillis = copy.getTimeInMillis(); 24127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Make sure parsed time zone type (Standard or Daylight) 24147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // matches the rule used by the parsed time zone. 24157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int[] offsets = new int[2]; 24167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (btz != null) { 24177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tztype == TimeType.STANDARD) { 24187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert btz.getOffsetFromLocal(localMillis, 24197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert BasicTimeZone.LOCAL_STD, BasicTimeZone.LOCAL_STD, offsets); 24207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 24217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert btz.getOffsetFromLocal(localMillis, 24227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert BasicTimeZone.LOCAL_DST, BasicTimeZone.LOCAL_DST, offsets); 24237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 24257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // No good way to resolve ambiguous time at transition, 24267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // but following code work in most case. 24277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tz.getOffset(localMillis, true, offsets); 24287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tztype == TimeType.STANDARD && offsets[1] != 0 24307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || tztype == TimeType.DAYLIGHT && offsets[1] == 0) { 24317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Roll back one day and try it again. 24327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Note: This code assumes 1. timezone transition only happens 24337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // once within 24 hours at max 24347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 2. the difference of local offsets at the transition is 24357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // less than 24 hours. 24367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tz.getOffset(localMillis - (24*60*60*1000), true, offsets); 24377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Now, compare the results with parsed type, either standard or 24417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // daylight saving time 24427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int resolvedSavings = offsets[1]; 24437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tztype == TimeType.STANDARD) { 24447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (offsets[1] != 0) { 24457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Override DST_OFFSET = 0 in the result calendar 24467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resolvedSavings = 0; 24477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { // tztype == TZTYPE_DST 24497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (offsets[1] == 0) { 24507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (btz != null) { 24517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert long time = localMillis + offsets[0]; 24527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We use the nearest daylight saving time rule. 24537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert TimeZoneTransition beforeTrs, afterTrs; 24547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert long beforeT = time, afterT = time; 24557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int beforeSav = 0, afterSav = 0; 24567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Search for DST rule before or on the time 24587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (true) { 24597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert beforeTrs = btz.getPreviousTransition(beforeT, true); 24607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (beforeTrs == null) { 24617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 24627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert beforeT = beforeTrs.getTime() - 1; 24647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert beforeSav = beforeTrs.getFrom().getDSTSavings(); 24657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (beforeSav != 0) { 24667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 24677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Search for DST rule after the time 24717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (true) { 24727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert afterTrs = btz.getNextTransition(afterT, false); 24737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (afterTrs == null) { 24747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 24757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert afterT = afterTrs.getTime(); 24777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert afterSav = afterTrs.getTo().getDSTSavings(); 24787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (afterSav != 0) { 24797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 24807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (beforeTrs != null && afterTrs != null) { 24847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (time - beforeT > afterT - time) { 24857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resolvedSavings = afterSav; 24867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 24877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resolvedSavings = beforeSav; 24887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (beforeTrs != null && beforeSav != 0) { 24907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resolvedSavings = beforeSav; 24917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (afterTrs != null && afterSav != 0) { 24927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resolvedSavings = afterSav; 24937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 24947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resolvedSavings = btz.getDSTSavings(); 24957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 24977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resolvedSavings = tz.getDSTSavings(); 24987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (resolvedSavings == 0) { 25007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Final fallback 25017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resolvedSavings = millisPerHour; 25027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(Calendar.ZONE_OFFSET, offsets[0]); 25067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(Calendar.DST_OFFSET, resolvedSavings); 25077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // An IllegalArgumentException will be thrown by Calendar.getTime() 25117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // if any fields are out of range, e.g., MONTH == 17. 25127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert catch (IllegalArgumentException e) { 25137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePos.setErrorIndex(pos); 25147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePos.setIndex(start); 25157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (backupTZ != null) { 25167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendar.setTimeZone(backupTZ); 25177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return; 25197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Set the parsed result if local calendar is used 25217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // instead of the input calendar 25227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (resultCal != null) { 25237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resultCal.setTimeZone(cal.getTimeZone()); 25247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resultCal.setTimeInMillis(cal.getTimeInMillis()); 25257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Restore the original time zone if required 25277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (backupTZ != null) { 25287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendar.setTimeZone(backupTZ); 25297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 25327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 25337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Matches text (starting at pos) with patl. Returns the new pos, and sets complete[0] 25347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * if it matched the entire text. Whitespace sequences are treated as singletons. 25357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>If isLenient and if we fail to match the first time, some special hacks are put into place. 25367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ul><li>we are between date and time fields, then one or more whitespace characters 25377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in the text are accepted instead.</li> 25387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ul><li>we are after a non-numeric field, and the text starts with a ".", we skip it.</li> 25397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ul> 25407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 25417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int matchLiteral(String text, int pos, Object[] items, int itemIndex, boolean[] complete) { 25427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int originalPos = pos; 25437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String patternLiteral = (String)items[itemIndex]; 25447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int plen = patternLiteral.length(); 25457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int tlen = text.length(); 25467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int idx = 0; 25477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (idx < plen && pos < tlen) { 25487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char pch = patternLiteral.charAt(idx); 25497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char ich = text.charAt(pos); 25507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (PatternProps.isWhiteSpace(pch) 25517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && PatternProps.isWhiteSpace(ich)) { 25527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // White space characters found in both patten and input. 25537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Skip contiguous white spaces. 25547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while ((idx + 1) < plen && 25557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternProps.isWhiteSpace(patternLiteral.charAt(idx + 1))) { 25567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++idx; 25577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while ((pos + 1) < tlen && 25597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternProps.isWhiteSpace(text.charAt(pos + 1))) { 25607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++pos; 25617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (pch != ich) { 25637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ich == '.' && pos == originalPos && 0 < itemIndex && getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_ALLOW_WHITESPACE)) { 25647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Object before = items[itemIndex-1]; 25657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (before instanceof PatternItem) { 25667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isNumeric = ((PatternItem) before).isNumeric; 25677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!isNumeric) { 25687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++pos; // just update pos 25697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 25707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ((pch == ' ' || pch == '.') && getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_ALLOW_WHITESPACE)) { 25737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++idx; 25747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 2575bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else if (pos != originalPos && getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_PARTIAL_LITERAL_MATCH)) { 25767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++idx; 25777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 25787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 25807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++idx; 25827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++pos; 25837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert complete[0] = idx == plen; 25857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (complete[0] == false && getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_ALLOW_WHITESPACE) && 0 < itemIndex && itemIndex < items.length - 1) { 25867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If fully lenient, accept " "* for any text between a date and a time field 25877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We don't go more lenient, because we don't want to accept "12/31" for "12:31". 25887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // People may be trying to parse for a date, then for a time. 25897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (originalPos < tlen) { 25907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Object before = items[itemIndex-1]; 25917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Object after = items[itemIndex+1]; 25927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (before instanceof PatternItem && after instanceof PatternItem) { 25937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char beforeType = ((PatternItem) before).type; 25947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char afterType = ((PatternItem) after).type; 25957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (DATE_PATTERN_TYPE.contains(beforeType) != DATE_PATTERN_TYPE.contains(afterType)) { 25967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int newPos = originalPos; 25977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (true) { 25987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char ich = text.charAt(newPos); 25997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!PatternProps.isWhiteSpace(ich)) { 26007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 26017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++newPos; 26037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert complete[0] = newPos > originalPos; 26057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = newPos; 26067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos; 26117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 26137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final UnicodeSet DATE_PATTERN_TYPE = new UnicodeSet("[GyYuUQqMLlwWd]").freeze(); 26147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 26157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 26167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Attempt to match the text at a given position against an array of 26177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * strings. Since multiple strings in the array may match (for 26187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * example, if the array contains "a", "ab", and "abc", all will match 26197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the input string "abcd") the longest match is returned. As a side 26207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * effect, the given field of <code>cal</code> is set to the index 26217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of the best match, if there is one. 26227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param text the time text being parsed. 26237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param start where to start parsing. 26247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param field the date field being parsed. 26257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param data the string array to parsed. 26267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param cal 26277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the new start position if matching succeeded; a negative 26287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number indicating matching failure, otherwise. As a side effect, 26297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * sets the <code>cal</code> field <code>field</code> to the index 26307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of the best match, if matching succeeded. 26317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 26327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 26337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert protected int matchString(String text, int start, int field, String[] data, Calendar cal) 26347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 26357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return matchString(text, start, field, data, null, cal); 26367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 26387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 26397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Attempt to match the text at a given position against an array of 26407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * strings. Since multiple strings in the array may match (for 26417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * example, if the array contains "a", "ab", and "abc", all will match 26427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the input string "abcd") the longest match is returned. As a side 26437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * effect, the given field of <code>cal</code> is set to the index 26447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of the best match, if there is one. 26457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param text the time text being parsed. 26467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param start where to start parsing. 26477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param field the date field being parsed. 26487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param data the string array to parsed. 26497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param monthPattern leap month pattern, or null if none. 26507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param cal 26517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the new start position if matching succeeded; a negative 26527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number indicating matching failure, otherwise. As a side effect, 26537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * sets the <code>cal</code> field <code>field</code> to the index 26547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of the best match, if matching succeeded. 26557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 26567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 26577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 26587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 26597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int matchString(String text, int start, int field, String[] data, String monthPattern, Calendar cal) 26607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 26617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int i = 0; 26627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int count = data.length; 26637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 26647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (field == Calendar.DAY_OF_WEEK) i = 1; 26657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 26667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // There may be multiple strings in the data[] array which begin with 26677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the same prefix (e.g., Cerven and Cervenec (June and July) in Czech). 26687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We keep track of the longest match, and return that. Note that this 26697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // unfortunately requires us to test all array elements. 26707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int bestMatchLength = 0, bestMatch = -1; 26717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int isLeapMonth = 0; 26727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int matchLength = 0; 26737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 26747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (; i<count; ++i) 26757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 26767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int length = data[i].length(); 26777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Always compare if we have no match yet; otherwise only compare 26787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // against potentially better matches (longer strings). 26797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (length > bestMatchLength && 26807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (matchLength = regionMatchesWithOptionalDot(text, start, data[i], length)) >= 0) 26817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 26827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestMatch = i; 26837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestMatchLength = matchLength; 26847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert isLeapMonth = 0; 26857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (monthPattern != null) { 26877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String leapMonthName = MessageFormat.format(monthPattern, data[i]); 26887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert length = leapMonthName.length(); 26897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (length > bestMatchLength && 26907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (matchLength = regionMatchesWithOptionalDot(text, start, leapMonthName, length)) >= 0) 26917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 26927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestMatch = i; 26937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestMatchLength = matchLength; 26947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert isLeapMonth = 1; 26957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (bestMatch >= 0) 26997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 2700f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if (field >= 0) { 2701f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if (field == Calendar.YEAR) { 2702f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert bestMatch++; // only get here for cyclic year names, which match 1-based years 1-60 2703f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 2704f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert cal.set(field, bestMatch); 2705f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if (monthPattern != null) { 2706f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert cal.set(Calendar.IS_LEAP_MONTH, isLeapMonth); 2707f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 27087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return start + bestMatchLength; 27107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ~start; 27127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 27147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int regionMatchesWithOptionalDot(String text, int start, String data, int length) { 27157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean matches = text.regionMatches(true, start, data, 0, length); 27167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (matches) { 27177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return length; 27187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (data.length() > 0 && data.charAt(data.length()-1) == '.') { 27207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (text.regionMatches(true, start, data, 0, length-1)) { 27217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return length - 1; 27227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return -1; 27257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 27277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 27287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Attempt to match the text at a given position against an array of quarter 27297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * strings. Since multiple strings in the array may match (for 27307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * example, if the array contains "a", "ab", and "abc", all will match 27317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the input string "abcd") the longest match is returned. As a side 27327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * effect, the given field of <code>cal</code> is set to the index 27337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of the best match, if there is one. 27347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param text the time text being parsed. 27357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param start where to start parsing. 27367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param field the date field being parsed. 27377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param data the string array to parsed. 27387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the new start position if matching succeeded; a negative 27397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number indicating matching failure, otherwise. As a side effect, 27407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * sets the <code>cal</code> field <code>field</code> to the index 27417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of the best match, if matching succeeded. 27427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 27437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 27447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert protected int matchQuarterString(String text, int start, int field, String[] data, Calendar cal) 27457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 27467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int i = 0; 27477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int count = data.length; 27487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 27497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // There may be multiple strings in the data[] array which begin with 27507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the same prefix (e.g., Cerven and Cervenec (June and July) in Czech). 27517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We keep track of the longest match, and return that. Note that this 27527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // unfortunately requires us to test all array elements. 27537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int bestMatchLength = 0, bestMatch = -1; 27547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int matchLength = 0; 27557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (; i<count; ++i) { 27567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int length = data[i].length(); 27577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Always compare if we have no match yet; otherwise only compare 27587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // against potentially better matches (longer strings). 27597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (length > bestMatchLength && 27607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (matchLength = regionMatchesWithOptionalDot(text, start, data[i], length)) >= 0) { 27617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 27627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestMatch = i; 27637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bestMatchLength = matchLength; 27647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 27677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (bestMatch >= 0) { 27687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(field, bestMatch * 3); 27697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return start + bestMatchLength; 27707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 27727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return -start; 27737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 27757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 27767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Protected method that converts one field of the input string into a 27777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * numeric field value in <code>cal</code>. Returns -start (for 27787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * ParsePosition) if failed. Subclasses may override this method to 27797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * modify or add parsing capabilities. 27807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param text the time text to be parsed. 27817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param start where to start parsing. 27827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ch the pattern character for the date field text to be parsed. 27837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param count the count of a pattern character. 27847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param obeyCount if true, then the next field directly abuts this one, 27857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and we should use the count to know when to stop parsing. 27867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ambiguousYear return parameter; upon return, if ambiguousYear[0] 27877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is true, then a two-digit year was parsed and may need to be readjusted. 27887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param cal 27897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the new start position if matching succeeded; a negative 27907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number indicating matching failure, otherwise. As a side effect, 27917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * set the appropriate field of <code>cal</code> with the parsed 27927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * value. 27937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 27947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 27957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert protected int subParse(String text, int start, char ch, int count, 27967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean obeyCount, boolean allowNegative, 27977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean[] ambiguousYear, Calendar cal) 27987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 27997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return subParse(text, start, ch, count, obeyCount, allowNegative, ambiguousYear, cal, null, null); 28007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 28027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 28037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Protected method that converts one field of the input string into a 28047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * numeric field value in <code>cal</code>. Returns -start (for 28057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * ParsePosition) if failed. Subclasses may override this method to 28067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * modify or add parsing capabilities. 28077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param text the time text to be parsed. 28087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param start where to start parsing. 28097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ch the pattern character for the date field text to be parsed. 28107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param count the count of a pattern character. 28117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param obeyCount if true, then the next field directly abuts this one, 28127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and we should use the count to know when to stop parsing. 28137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ambiguousYear return parameter; upon return, if ambiguousYear[0] 28147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is true, then a two-digit year was parsed and may need to be readjusted. 28157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param cal 28167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param numericLeapMonthFormatter if non-null, used to parse numeric leap months. 28177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param tzTimeType the type of parsed time zone - standard, daylight or unknown (output). 28187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This parameter can be null if caller does not need the information. 28197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the new start position if matching succeeded; a negative 28207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number indicating matching failure, otherwise. As a side effect, 28217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * set the appropriate field of <code>cal</code> with the parsed 28227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * value. 28237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 28247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 28257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 28267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 28277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @SuppressWarnings("fallthrough") 28287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int subParse(String text, int start, char ch, int count, 28297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean obeyCount, boolean allowNegative, 28307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean[] ambiguousYear, Calendar cal, 28317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert MessageFormat numericLeapMonthFormatter, Output<TimeType> tzTimeType) 28327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 28337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Number number = null; 28347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert NumberFormat currentNumberFormat = null; 28357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int value = 0; 28367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int i; 28377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ParsePosition pos = new ParsePosition(0); 28387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2839f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert int patternCharIndex = getIndexFromChar(ch); 28407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (patternCharIndex == -1) { 28417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ~start; 28427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 28447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currentNumberFormat = getNumberFormat(ch); 28457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2846f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex]; // -1 if irrelevant 28477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 28487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (numericLeapMonthFormatter != null) { 28497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numericLeapMonthFormatter.setFormatByArgumentIndex(0, currentNumberFormat); 28507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isChineseCalendar = ( cal.getType().equals("chinese") || cal.getType().equals("dangi") ); 28527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 28537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If there are any spaces here, skip over them. If we hit the end 28547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // of the string, then fail. 28557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (;;) { 28567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (start >= text.length()) { 28577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ~start; 28587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int c = UTF16.charAt(text, start); 28607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!UCharacter.isUWhiteSpace(c) || !PatternProps.isWhiteSpace(c)) { 28617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 28627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert start += UTF16.getCharCount(c); 28647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setIndex(start); 28667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 28677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We handle a few special cases here where we need to parse 28687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // a number value. We handle further, more generic cases below. We need 28697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // to handle some of them here because some fields require extra processing on 28707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the parsed value. 28717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (patternCharIndex == 4 /*'k' HOUR_OF_DAY1_FIELD*/ || 28727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternCharIndex == 15 /*'h' HOUR1_FIELD*/ || 28737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (patternCharIndex == 2 /*'M' MONTH_FIELD*/ && count <= 2) || 28747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternCharIndex == 26 /*'L' STAND_ALONE_MONTH*/ || 28757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternCharIndex == 19 /*'e' DOW_LOCAL*/ || 28767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternCharIndex == 25 /*'c' STAND_ALONE_DAY_OF_WEEK*/ || 28777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternCharIndex == 1 /*'y' YEAR */ || patternCharIndex == 18 /*'Y' YEAR_WOY */ || 28787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternCharIndex == 30 /*'U' YEAR_NAME_FIELD, falls back to numeric */ || 28797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (patternCharIndex == 0 /*'G' ERA */ && isChineseCalendar) || 28807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternCharIndex == 27 /* 'Q' - QUARTER*/ || 28817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternCharIndex == 28 /* 'q' - STANDALONE QUARTER*/ || 28827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternCharIndex == 8 /*'S' FRACTIONAL_SECOND */ ) 28837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 28847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // It would be good to unify this with the obeyCount logic below, 28857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // but that's going to be difficult. 28867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 28877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean parsedNumericLeapMonth = false; 28887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (numericLeapMonthFormatter != null && (patternCharIndex == 2 || patternCharIndex == 26)) { 28897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // First see if we can parse month number with leap month pattern 28907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Object[] args = numericLeapMonthFormatter.parse(text, pos); 28917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (args != null && pos.getIndex() > start && (args[0] instanceof Number)) { 28927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsedNumericLeapMonth = true; 28937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = (Number)args[0]; 28947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(Calendar.IS_LEAP_MONTH, 1); 28957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 28967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setIndex(start); 28977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(Calendar.IS_LEAP_MONTH, 0); 28987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 29017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!parsedNumericLeapMonth) { 29027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (obeyCount) { 29037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((start+count) > text.length()) { 29047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ~start; 29057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = parseInt(text, count, pos, allowNegative,currentNumberFormat); 29077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 29087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = parseInt(text, pos, allowNegative,currentNumberFormat); 29097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (number == null && !allowNumericFallback(patternCharIndex)) { 29117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // only return if pattern is NOT one that allows numeric fallback 29127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ~start; 29137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 29167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (number != null) { 29177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert value = number.intValue(); 29187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 29217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert switch (patternCharIndex) 29227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 29237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 0: // 'G' - ERA 29247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( isChineseCalendar ) { 29257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Numeric era handling moved from ChineseDateFormat, 29267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If we didn't have a number, already returned -start above 29277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(Calendar.ERA, value); 29287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 29297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int ps = 0; 29317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count == 5) { 29327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ps = matchString(text, start, Calendar.ERA, formatData.narrowEras, null, cal); 29337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 4) { 29347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ps = matchString(text, start, Calendar.ERA, formatData.eraNames, null, cal); 29357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 29367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ps = matchString(text, start, Calendar.ERA, formatData.eras, null, cal); 29377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 29397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // check return position, if it equals -start, then matchString error 29407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // special case the return code so we don't necessarily fail out until we 29417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // verify no year information also 29427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ps == ~start) 29437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ps = ISOSpecialEra; 29447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 29457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ps; 29467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 29477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 1: // 'y' - YEAR 29487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 18: // 'Y' - YEAR_WOY 29497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If there are 3 or more YEAR pattern characters, this indicates 29507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // that the year value is to be treated literally, without any 29517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // two-digit year adjustments (e.g., from "01" to 2001). Otherwise 29527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // we made adjustments to place the 2-digit year in the proper 29537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // century, for parsed strings from "00" to "99". Any other string 29547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // is treated literally: "2250", "-1", "1", "002". 29557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 'yy' is the only special case, 'y' is interpreted as number. [Richard/GCL]*/ 29567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* Skip this for Chinese calendar, moved from ChineseDateFormat */ 29577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( override != null && (override.compareTo("hebr") == 0 || override.indexOf("y=hebr") >= 0) && value < 1000 ) { 29587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert value += HEBREW_CAL_CUR_MILLENIUM_START_YEAR; 29597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (count == 2 && (pos.getIndex() - start) == 2 && cal.haveDefaultCentury() 29607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && UCharacter.isDigit(text.charAt(start)) 29617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && UCharacter.isDigit(text.charAt(start+1))) 29627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 29637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Assume for example that the defaultCenturyStart is 6/18/1903. 29647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // This means that two-digit years will be forced into the range 29657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 6/18/1903 to 6/17/2003. As a result, years 00, 01, and 02 29667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // correspond to 2000, 2001, and 2002. Years 04, 05, etc. correspond 29677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // to 1904, 1905, etc. If the year is 03, then it is 2003 if the 29687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // other fields specify a date before 6/18, or 1903 if they specify a 29697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // date afterwards. As a result, 03 is an ambiguous year. All other 29707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // two-digit years are unambiguous. 29717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int ambiguousTwoDigitYear = getDefaultCenturyStartYear() % 100; 29727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ambiguousYear[0] = value == ambiguousTwoDigitYear; 29737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert value += (getDefaultCenturyStartYear()/100)*100 + 29747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (value < ambiguousTwoDigitYear ? 100 : 0); 29757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(field, value); 29777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 29787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Delayed checking for adjustment of Hebrew month numbers in non-leap years. 29797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (DelayedHebrewMonthCheck) { 29807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!HebrewCalendar.isLeapYear(value)) { 29817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.add(Calendar.MONTH,1); 29827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DelayedHebrewMonthCheck = false; 29847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 29867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 30: // 'U' - YEAR_NAME_FIELD 29877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (formatData.shortYearNames != null) { 29887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int newStart = matchString(text, start, Calendar.YEAR, formatData.shortYearNames, null, cal); 29897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (newStart > 0) { 29907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return newStart; 29917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( number != null && (getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_ALLOW_NUMERIC) || formatData.shortYearNames == null || value > formatData.shortYearNames.length) ) { 29947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(Calendar.YEAR, value); 29957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 29967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ~start; 29987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 2: // 'M' - MONTH 29997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 26: // 'L' - STAND_ALONE_MONTH 30007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count <= 2 || (number != null && getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_ALLOW_NUMERIC))) { 30017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // i.e., M/MM, L/LL or lenient & have a number 30027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Don't want to parse the month if it is a string 30037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // while pattern uses numeric style: M/MM, L/LL. 30047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [We computed 'value' above.] 30057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(Calendar.MONTH, value - 1); 30067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // When parsing month numbers from the Hebrew Calendar, we might need 30077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // to adjust the month depending on whether or not it was a leap year. 30087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We may or may not yet know what year it is, so might have to delay 30097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // checking until the year is parsed. 30107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (cal.getType().equals("hebrew") && value >= 6) { 30117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (cal.isSet(Calendar.YEAR)) { 30127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!HebrewCalendar.isLeapYear(cal.get(Calendar.YEAR))) { 30137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(Calendar.MONTH, value); 30147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 30167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DelayedHebrewMonthCheck = true; 30177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 30207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 30217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // count >= 3 // i.e., MMM/MMMM or LLL/LLLL 30227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Want to be able to parse both short and long forms. 30237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean haveMonthPat = (formatData.leapMonthPatterns != null && formatData.leapMonthPatterns.length >= DateFormatSymbols.DT_MONTH_PATTERN_COUNT); 30247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Try count == 4 first:, unless we're strict 30257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int newStart = 0; 30267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 4) { 30277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert newStart = (patternCharIndex == 2)? 30287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert matchString(text, start, Calendar.MONTH, formatData.months, 30297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (haveMonthPat)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_FORMAT_WIDE]: null, cal): 30307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert matchString(text, start, Calendar.MONTH, formatData.standaloneMonths, 30317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (haveMonthPat)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_STANDALONE_WIDE]: null, cal); 30327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (newStart > 0) { 30337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return newStart; 30347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // count == 4 failed, now try count == 3 30377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 3) { 30387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (patternCharIndex == 2)? 30397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert matchString(text, start, Calendar.MONTH, formatData.shortMonths, 30407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (haveMonthPat)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_FORMAT_ABBREV]: null, cal): 30417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert matchString(text, start, Calendar.MONTH, formatData.standaloneShortMonths, 30427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (haveMonthPat)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_STANDALONE_ABBREV]: null, cal); 30437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return newStart; 30457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 4: // 'k' - HOUR_OF_DAY (1..24) 30477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [We computed 'value' above.] 30487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (value == cal.getMaximum(Calendar.HOUR_OF_DAY)+1) { 30497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert value = 0; 30507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(Calendar.HOUR_OF_DAY, value); 30527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 30537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 8: // 'S' - FRACTIONAL_SECOND 30547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Fractional seconds left-justify 30557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i = pos.getIndex() - start; 30567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (i < 3) { 30577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (i < 3) { 30587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert value *= 10; 30597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i++; 30607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 30627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int a = 1; 30637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (i > 3) { 30647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert a *= 10; 30657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i--; 30667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert value /= a; 30687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(Calendar.MILLISECOND, value); 30707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 30717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 19: // 'e' - DOW_LOCAL 30727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(count <= 2 || (number != null && (getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_ALLOW_NUMERIC))) ) { 30737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // i.e. e/ee or lenient and have a number 30747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(field, value); 30757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 30767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // else for eee-eeeeee, fall through to EEE-EEEEEE handling 30787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //$FALL-THROUGH$ 30797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 9: { // 'E' - DAY_OF_WEEK 30807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Want to be able to parse at least wide, abbrev, short, and narrow forms. 30817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int newStart = 0; 30827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 4) { 30837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.weekdays, null, cal)) > 0) { // try EEEE wide 30847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return newStart; 30857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 3) { 30887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.shortWeekdays, null, cal)) > 0) { // try EEE abbrev 30897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return newStart; 30907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 6) { 30937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (formatData.shorterWeekdays != null) { 30947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if((newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.shorterWeekdays, null, cal)) > 0) { // try EEEEEE short 30957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return newStart; 30967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 5) { 31007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (formatData.narrowWeekdays != null) { 31017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if((newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.narrowWeekdays, null, cal)) > 0) { // try EEEEE narrow 31027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return newStart; 31037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return newStart; 31077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 25: { // 'c' - STAND_ALONE_DAY_OF_WEEK 31097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(count == 1 || (number != null && (getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_ALLOW_NUMERIC))) ) { 31107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // i.e. c or lenient and have a number 31117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(field, value); 31127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 31137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Want to be able to parse at least wide, abbrev, short forms. 31157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int newStart = 0; 31167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 4) { 31177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.standaloneWeekdays, null, cal)) > 0) { // try cccc wide 31187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return newStart; 31197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 3) { 31227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((newStart = matchString(text, start, Calendar.DAY_OF_WEEK, formatData.standaloneShortWeekdays, null, cal)) > 0) { // try ccc abbrev 31237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return newStart; 31247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 6) { 31277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (formatData.standaloneShorterWeekdays != null) { 31287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return matchString(text, start, Calendar.DAY_OF_WEEK, formatData.standaloneShorterWeekdays, null, cal); // try cccccc short 31297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return newStart; 31327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3133f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert case 14: { // 'a' - AM_PM 3134f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // Optionally try both wide/abbrev and narrow forms. 3135f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // formatData.ampmsNarrow may be null when deserializing DateFormatSymbolsfrom old version, 3136f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // in which case our only option is wide form 3137f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert int newStart = 0; 3138f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // try wide/abbrev a-aaaa 3139f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if(formatData.ampmsNarrow == null || count < 5 || getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH)) { 3140f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if ((newStart = matchString(text, start, Calendar.AM_PM, formatData.ampms, null, cal)) > 0) { 3141f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert return newStart; 3142f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 3143f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 3144f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // try narrow aaaaa 3145f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if(formatData.ampmsNarrow != null && (count >= 5 || getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH))) { 3146f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if ((newStart = matchString(text, start, Calendar.AM_PM, formatData.ampmsNarrow, null, cal)) > 0) { 3147f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert return newStart; 3148f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 3149f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 3150f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // no matches for given options 3151f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert return ~start; 3152f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 31537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 15: // 'h' - HOUR (1..12) 31547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [We computed 'value' above.] 31557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (value == cal.getLeastMaximum(Calendar.HOUR)+1) { 31567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert value = 0; 31577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(Calendar.HOUR, value); 31597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 31607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 17: // 'z' - ZONE_OFFSET 31617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 31627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Style style = (count < 4) ? Style.SPECIFIC_SHORT : Style.SPECIFIC_LONG; 31637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert TimeZone tz = tzFormat().parse(style, text, pos, tzTimeType); 31647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tz != null) { 31657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.setTimeZone(tz); 31667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 31677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ~start; 31697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 23: // 'Z' - TIMEZONE_RFC 31717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 31727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Style style = (count < 4) ? Style.ISO_BASIC_LOCAL_FULL : ((count == 5) ? Style.ISO_EXTENDED_FULL : Style.LOCALIZED_GMT); 31737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert TimeZone tz = tzFormat().parse(style, text, pos, tzTimeType); 31747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tz != null) { 31757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.setTimeZone(tz); 31767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 31777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ~start; 31797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 24: // 'v' - TIMEZONE_GENERIC 31817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 31827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Note: 'v' only supports count 1 and 4 31837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Style style = (count < 4) ? Style.GENERIC_SHORT : Style.GENERIC_LONG; 31847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert TimeZone tz = tzFormat().parse(style, text, pos, tzTimeType); 31857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tz != null) { 31867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.setTimeZone(tz); 31877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 31887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ~start; 31907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 29: // 'V' - TIMEZONE_SPECIAL 31927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 31937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Style style = null; 31947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert switch (count) { 31957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 1: 31967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert style = Style.ZONE_ID_SHORT; 31977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 31987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 2: 31997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert style = Style.ZONE_ID; 32007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 32017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 3: 32027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert style = Style.EXEMPLAR_LOCATION; 32037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 32047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert default: 32057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert style = Style.GENERIC_LOCATION; 32067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 32077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert TimeZone tz = tzFormat().parse(style, text, pos, tzTimeType); 32097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tz != null) { 32107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.setTimeZone(tz); 32117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 32127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ~start; 32147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 31: // 'O' - TIMEZONE_LOCALIZED_GMT_OFFSET 32167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 32177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Style style = (count < 4) ? Style.LOCALIZED_GMT_SHORT : Style.LOCALIZED_GMT; 32187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert TimeZone tz = tzFormat().parse(style, text, pos, tzTimeType); 32197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tz != null) { 32207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.setTimeZone(tz); 32217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 32227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ~start; 32247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 32: // 'X' - TIMEZONE_ISO 32267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 32277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Style style; 32287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert switch (count) { 32297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 1: 32307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert style = Style.ISO_BASIC_SHORT; 32317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 32327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 2: 32337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert style = Style.ISO_BASIC_FIXED; 32347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 32357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 3: 32367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert style = Style.ISO_EXTENDED_FIXED; 32377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 32387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 4: 32397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert style = Style.ISO_BASIC_FULL; 32407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 32417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert default: // count >= 5 32427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert style = Style.ISO_EXTENDED_FULL; 32437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 32447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert TimeZone tz = tzFormat().parse(style, text, pos, tzTimeType); 32467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tz != null) { 32477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.setTimeZone(tz); 32487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 32497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ~start; 32517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 33: // 'x' - TIMEZONE_ISO_LOCAL 32537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 32547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Style style; 32557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert switch (count) { 32567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 1: 32577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert style = Style.ISO_BASIC_LOCAL_SHORT; 32587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 32597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 2: 32607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert style = Style.ISO_BASIC_LOCAL_FIXED; 32617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 32627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 3: 32637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert style = Style.ISO_EXTENDED_LOCAL_FIXED; 32647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 32657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 4: 32667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert style = Style.ISO_BASIC_LOCAL_FULL; 32677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 32687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert default: // count >= 5 32697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert style = Style.ISO_EXTENDED_LOCAL_FULL; 32707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 32717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert TimeZone tz = tzFormat().parse(style, text, pos, tzTimeType); 32737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tz != null) { 32747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.setTimeZone(tz); 32757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 32767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ~start; 32787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 27: // 'Q' - QUARTER 32807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count <= 2 || (number != null && getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_ALLOW_NUMERIC))) { 32817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // i.e., Q or QQ. or lenient & have number 32827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Don't want to parse the quarter if it is a string 32837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // while pattern uses numeric style: Q or QQ. 32847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [We computed 'value' above.] 32857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(Calendar.MONTH, (value - 1) * 3); 32867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 32877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 32887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // count >= 3 // i.e., QQQ or QQQQ 32897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Want to be able to parse both short and long forms. 32907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Try count == 4 first: 32917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int newStart = 0; 32927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 4) { 32937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if((newStart = matchQuarterString(text, start, Calendar.MONTH, formatData.quarters, cal)) > 0) { 32947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return newStart; 32957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // count == 4 failed, now try count == 3 32987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 3) { 32997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return matchQuarterString(text, start, Calendar.MONTH, 33007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert formatData.shortQuarters, cal); 33017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return newStart; 33037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 33057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 28: // 'q' - STANDALONE QUARTER 33067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count <= 2 || (number != null && getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_ALLOW_NUMERIC))) { 33077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // i.e., q or qq. or lenient & have number 33087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Don't want to parse the quarter if it is a string 33097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // while pattern uses numeric style: q or qq. 33107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [We computed 'value' above.] 33117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal.set(Calendar.MONTH, (value - 1) * 3); 33127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 33137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 33147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // count >= 3 // i.e., qqq or qqqq 33157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Want to be able to parse both short and long forms. 33167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Try count == 4 first: 33177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int newStart = 0; 33187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 4) { 33197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if((newStart = matchQuarterString(text, start, Calendar.MONTH, formatData.standaloneQuarters, cal)) > 0) { 33207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return newStart; 33217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // count == 4 failed, now try count == 3 33247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH) || count == 3) { 33257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return matchQuarterString(text, start, Calendar.MONTH, 33267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert formatData.standaloneShortQuarters, cal); 33277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return newStart; 33297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3331bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert case 35: // TIME SEPARATOR (no pattern character currently defined, we should 3332bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // not get here but leave support in for future definition. 3333f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert { 3334f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // Try matching a time separator. 3335f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert ArrayList<String> data = new ArrayList<String>(3); 3336f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert data.add(formatData.getTimeSeparatorString()); 3337f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 3338f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // Add the default, if different from the locale. 3339f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if (!formatData.getTimeSeparatorString().equals(DateFormatSymbols.DEFAULT_TIME_SEPARATOR)) { 3340f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert data.add(DateFormatSymbols.DEFAULT_TIME_SEPARATOR); 3341f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 3342f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 3343f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // If lenient, add also the alternate, if different from the locale. 3344bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if (getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_PARTIAL_LITERAL_MATCH) && 3345f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert !formatData.getTimeSeparatorString().equals(DateFormatSymbols.ALTERNATE_TIME_SEPARATOR)) { 3346f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert data.add(DateFormatSymbols.ALTERNATE_TIME_SEPARATOR); 3347f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 3348f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 3349f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert return matchString(text, start, -1 /* => nothing to set */, data.toArray(new String[0]), cal); 3350f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 3351f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 33527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert default: 33537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 3: // 'd' - DATE 33547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 5: // 'H' - HOUR_OF_DAY (0..23) 33557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 6: // 'm' - MINUTE 33567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 7: // 's' - SECOND 33577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 10: // 'D' - DAY_OF_YEAR 33587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 11: // 'F' - DAY_OF_WEEK_IN_MONTH 33597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 12: // 'w' - WEEK_OF_YEAR 33607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 13: // 'W' - WEEK_OF_MONTH 33617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 16: // 'K' - HOUR (0..11) 33627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 20: // 'u' - EXTENDED_YEAR 33637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 21: // 'g' - JULIAN_DAY 33647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // case 22: // 'A' - MILLISECONDS_IN_DAY 3365f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // case 34: // 33667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 33677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Handle "generic" fields 33687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (obeyCount) { 33697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((start+count) > text.length()) return -start; 33707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = parseInt(text, count, pos, allowNegative,currentNumberFormat); 33717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 33727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = parseInt(text, pos, allowNegative,currentNumberFormat); 33737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (number != null) { 3375f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if (patternCharIndex != DateFormat.RELATED_YEAR) { 3376f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert cal.set(field, number.intValue()); 3377f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } else { 3378f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert cal.setRelatedYear(number.intValue()); 3379f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 33807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos.getIndex(); 33817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ~start; 33837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 33867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 33877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * return true if the pattern specified by patternCharIndex is one that allows 33887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * numeric fallback regardless of actual pattern size. 33897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 33907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean allowNumericFallback(int patternCharIndex) { 33917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (patternCharIndex == 26 /*'L' STAND_ALONE_MONTH*/ || 33927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternCharIndex == 19 /*'e' DOW_LOCAL*/ || 33937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternCharIndex == 25 /*'c' STAND_ALONE_DAY_OF_WEEK*/ || 33947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternCharIndex == 30 /*'U' YEAR_NAME_FIELD*/ || 33957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternCharIndex == 27 /* 'Q' - QUARTER*/ || 33967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternCharIndex == 28 /* 'q' - STANDALONE QUARTER*/) { 33977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 33987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 34007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 34027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 34037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Parse an integer using numberFormat. This method is semantically 34047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * const, but actually may modify fNumberFormat. 34057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 34067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Number parseInt(String text, 34077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ParsePosition pos, 34087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean allowNegative, 34097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert NumberFormat fmt) { 34107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return parseInt(text, -1, pos, allowNegative, fmt); 34117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 34137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 34147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Parse an integer using numberFormat up to maxDigits. 34157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 34167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Number parseInt(String text, 34177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int maxDigits, 34187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ParsePosition pos, 34197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean allowNegative, 34207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert NumberFormat fmt) { 34217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Number number; 34227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int oldPos = pos.getIndex(); 34237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (allowNegative) { 34247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = fmt.parse(text, pos); 34257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 34267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Invalidate negative numbers 34277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fmt instanceof DecimalFormat) { 34287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String oldPrefix = ((DecimalFormat)fmt).getNegativePrefix(); 34297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ((DecimalFormat)fmt).setNegativePrefix(SUPPRESS_NEGATIVE_PREFIX); 34307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = fmt.parse(text, pos); 34317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ((DecimalFormat)fmt).setNegativePrefix(oldPrefix); 34327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 34337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean dateNumberFormat = (fmt instanceof DateNumberFormat); 34347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (dateNumberFormat) { 34357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ((DateNumberFormat)fmt).setParsePositiveOnly(true); 34367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = fmt.parse(text, pos); 34387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (dateNumberFormat) { 34397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ((DateNumberFormat)fmt).setParsePositiveOnly(false); 34407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (maxDigits > 0) { 34447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // adjust the result to fit into 34457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the maxDigits and move the position back 34467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int nDigits = pos.getIndex() - oldPos; 34477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (nDigits > maxDigits) { 34487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert double val = number.doubleValue(); 34497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert nDigits -= maxDigits; 34507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (nDigits > 0) { 34517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert val /= 10; 34527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert nDigits--; 34537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setIndex(oldPos + maxDigits); 34557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = Integer.valueOf((int)val); 34567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return number; 34597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 34617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 34627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 34637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Translate a pattern, mapping each character in the from string to the 34647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * corresponding character in the to string. 34657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 34667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String translatePattern(String pat, String from, String to) { 34677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder result = new StringBuilder(); 34687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean inQuote = false; 34697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < pat.length(); ++i) { 34707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char c = pat.charAt(i); 34717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (inQuote) { 34727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (c == '\'') 34737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert inQuote = false; 34747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 34757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (c == '\'') { 34767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert inQuote = true; 3477f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } else if (isSyntaxChar(c)) { 34787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int ci = from.indexOf(c); 34797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ci != -1) { 34807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert c = to.charAt(ci); 34817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // do not worry on translatepattern if the character is not listed 34837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // we do the validity check elsewhere 34847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(c); 34877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (inQuote) { 34897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Unfinished quote in pattern"); 34907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return result.toString(); 34927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 34947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 34957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Return a pattern string describing this date format. 34967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 34977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 34987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String toPattern() { 34997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pattern; 35007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 35017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 35027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 35037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Return a localized pattern string describing this date format. 35047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 35057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 35067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String toLocalizedPattern() { 35077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return translatePattern(pattern, 35087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateFormatSymbols.patternChars, 35097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert formatData.localPatternChars); 35107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 35117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 35127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 35137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Apply the given unlocalized pattern string to this date format. 35147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 35157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 35167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void applyPattern(String pat) 35177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 35187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.pattern = pat; 35197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setLocale(null, null); 35207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // reset parsed pattern items 35217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternItems = null; 35227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 35237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 35247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 35257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Apply the given localized pattern string to this date format. 35267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 35277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 35287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void applyLocalizedPattern(String pat) { 35297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.pattern = translatePattern(pat, 35307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert formatData.localPatternChars, 35317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateFormatSymbols.patternChars); 35327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setLocale(null, null); 35337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 35347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 35357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 35367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Gets the date/time formatting data. 35377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return a copy of the date-time formatting data associated 35387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * with this date-time formatter. 35397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 35407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 35417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public DateFormatSymbols getDateFormatSymbols() 35427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 35437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (DateFormatSymbols)formatData.clone(); 35447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 35457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 35467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 35477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Allows you to set the date/time formatting data. 35487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param newFormatSymbols the new symbols 35497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 35507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 35517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setDateFormatSymbols(DateFormatSymbols newFormatSymbols) 35527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 35537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.formatData = (DateFormatSymbols)newFormatSymbols.clone(); 35547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 35557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 35567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 35577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Method for subclasses to access the DateFormatSymbols. 35587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 35597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 35607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert protected DateFormatSymbols getSymbols() { 35617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return formatData; 35627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 35637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 35647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 35657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Gets the time zone formatter which this date/time 35667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * formatter uses to format and parse a time zone. 35677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 35687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the time zone formatter which this date/time 35697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * formatter uses. 35707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 49 35717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 35727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public TimeZoneFormat getTimeZoneFormat() { 35737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return tzFormat().freeze(); 35747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 35757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 35767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 35777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Allows you to set the time zone formatter. 35787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 35797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param tzfmt the new time zone formatter 35807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 49 35817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 35827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setTimeZoneFormat(TimeZoneFormat tzfmt) { 35837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tzfmt.isFrozen()) { 35847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If frozen, use it as is. 35857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tzFormat = tzfmt; 35867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 35877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If not frozen, clone and freeze. 35887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tzFormat = tzfmt.cloneAsThawed().freeze(); 35897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 35907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 35917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 35927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 35937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Overrides Cloneable 35947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 35957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 35967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Object clone() { 35977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert SimpleDateFormat other = (SimpleDateFormat) super.clone(); 35987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert other.formatData = (DateFormatSymbols) formatData.clone(); 3599f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // We must create a new copy of work buffer used by 3600f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert // the fast numeric field format code. 3601f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if (this.decimalBuf != null) { 3602f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert other.decimalBuf = new char[DECIMAL_BUF_SIZE]; 3603f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 36047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return other; 36057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 36077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 36087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Override hashCode. 36097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Generates the hash code for the SimpleDateFormat object 36107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 36117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 36127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int hashCode() 36137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 36147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pattern.hashCode(); 36157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // just enough fields for a reasonable distribution 36167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 36187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 36197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Override equals. 36207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 36217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 36227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean equals(Object obj) 36237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 36247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!super.equals(obj)) return false; // super does class check 36257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert SimpleDateFormat that = (SimpleDateFormat) obj; 36267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (pattern.equals(that.pattern) 36277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && formatData.equals(that.formatData)); 36287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 36307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 36317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Override writeObject. 36327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * See http://docs.oracle.com/javase/6/docs/api/java/io/ObjectOutputStream.html 36337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 36347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void writeObject(ObjectOutputStream stream) throws IOException{ 36357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (defaultCenturyStart == null) { 36367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // if defaultCenturyStart is not yet initialized, 36377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // calculate and set value before serialization. 36387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initializeDefaultCenturyStart(defaultCenturyBase); 36397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initializeTimeZoneFormat(false); 36417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stream.defaultWriteObject(); 36427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stream.writeInt(getContext(DisplayContext.Type.CAPITALIZATION).value()); 36437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 36457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 36467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Override readObject. 36477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * See http://docs.oracle.com/javase/6/docs/api/java/io/ObjectInputStream.html 36487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 36497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void readObject(ObjectInputStream stream) 36507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throws IOException, ClassNotFoundException { 36517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stream.defaultReadObject(); 36527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int capitalizationSettingValue = (serialVersionOnStream > 1)? stream.readInt(): -1; 36537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ///CLOVER:OFF 36547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // don't have old serial data to test with 36557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (serialVersionOnStream < 1) { 36567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // didn't have defaultCenturyStart field 36577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert defaultCenturyBase = System.currentTimeMillis(); 36587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ///CLOVER:ON 36607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert else { 36617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // fill in dependent transient field 36627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parseAmbiguousDatesAsAfter(defaultCenturyStart); 36637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert serialVersionOnStream = currentSerialVersion; 36657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert locale = getLocale(ULocale.VALID_LOCALE); 36667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (locale == null) { 36677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ICU4J 3.6 or older versions did not have UFormat locales 36687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // in the serialized data. This is just for preventing the 36697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // worst case scenario... 36707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert locale = ULocale.getDefault(Category.FORMAT); 36717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 36737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initLocalZeroPaddingNumberFormat(); 36747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 36757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setContext(DisplayContext.CAPITALIZATION_NONE); 36767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (capitalizationSettingValue >= 0) { 36777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (DisplayContext context: DisplayContext.values()) { 36787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (context.value() == capitalizationSettingValue) { 36797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setContext(context); 36807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 36817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3684bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 3685bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // if serialized pre-56 update & turned off partial match switch to new enum value 3686bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if(getBooleanAttribute(DateFormat.BooleanAttribute.PARSE_PARTIAL_MATCH) == false) { 3687bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert setBooleanAttribute(DateFormat.BooleanAttribute.PARSE_PARTIAL_LITERAL_MATCH, false); 3688bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 36897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 36917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 36927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Format the object to an attributed string, and return the corresponding iterator 36937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Overrides superclass method. 36947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 36957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param obj The object to format 36967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return <code>AttributedCharacterIterator</code> describing the formatted value. 36977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 36987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 36997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 37007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public AttributedCharacterIterator formatToCharacterIterator(Object obj) { 37017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar cal = calendar; 37027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (obj instanceof Calendar) { 37037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cal = (Calendar)obj; 37047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (obj instanceof Date) { 37057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendar.setTime((Date)obj); 37067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (obj instanceof Number) { 37077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert calendar.setTimeInMillis(((Number)obj).longValue()); 37087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 37097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Cannot format given Object as a Date"); 37107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuffer toAppendTo = new StringBuffer(); 37127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition pos = new FieldPosition(0); 37137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert List<FieldPosition> attributes = new ArrayList<FieldPosition>(); 37147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert format(cal, getContext(DisplayContext.Type.CAPITALIZATION), toAppendTo, pos, attributes); 37157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert AttributedString as = new AttributedString(toAppendTo.toString()); 37177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // add DateFormat field attributes to the AttributedString 37197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < attributes.size(); i++) { 37207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition fp = attributes.get(i); 37217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Format.Field attribute = fp.getFieldAttribute(); 37227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert as.addAttribute(attribute, attribute, fp.getBeginIndex(), fp.getEndIndex()); 37237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // return the CharacterIterator from AttributedString 37257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return as.getIterator(); 37267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 37297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Get the locale of this simple date formatter. 37307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It is package accessible. also used in DateIntervalFormat. 37317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 37327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return locale in this simple date formatter 37337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 37347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ULocale getLocale() 37357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 37367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return locale; 37377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 37427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Check whether the 'field' is smaller than all the fields covered in 37437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern, return true if it is. 37447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The sequence of calendar field, 37457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * from large to small is: ERA, YEAR, MONTH, DATE, AM_PM, HOUR, MINUTE,... 37467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param field the calendar field need to check against 37477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true if the 'field' is smaller than all the fields 37487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * covered in pattern. false otherwise. 37497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 37507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isFieldUnitIgnored(int field) { 37527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return isFieldUnitIgnored(pattern, field); 37537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 37577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Check whether the 'field' is smaller than all the fields covered in 37587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern, return true if it is. 37597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The sequence of calendar field, 37607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * from large to small is: ERA, YEAR, MONTH, DATE, AM_PM, HOUR, MINUTE,... 37617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pattern the pattern to check against 37627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param field the calendar field need to check against 37637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true if the 'field' is smaller than all the fields 37647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * covered in pattern. false otherwise. 37657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 37667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static boolean isFieldUnitIgnored(String pattern, int field) { 37677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int fieldLevel = CALENDAR_FIELD_TO_LEVEL[field]; 37687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int level; 37697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char ch; 37707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean inQuote = false; 37717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char prevCh = 0; 37727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int count = 0; 37737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < pattern.length(); ++i) { 37757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ch = pattern.charAt(i); 37767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch != prevCh && count > 0) { 3777f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert level = getLevelFromChar(prevCh); 3778f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if (fieldLevel <= level) { 37797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 37807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = 0; 37827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch == '\'') { 37847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((i+1) < pattern.length() && pattern.charAt(i+1) == '\'') { 37857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++i; 37867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 37877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert inQuote = ! inQuote; 37887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3789f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } else if (!inQuote && isSyntaxChar(ch)) { 37907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert prevCh = ch; 37917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++count; 37927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count > 0) { 37957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // last item 3796f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert level = getLevelFromChar(prevCh); 3797f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if (fieldLevel <= level) { 37987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 37997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 38027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 38067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Format date interval by algorithm. 38077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It is supposed to be used only by CLDR survey tool. 38087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 38097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param fromCalendar calendar set to the from date in date interval 38107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to be formatted into date interval stirng 38117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param toCalendar calendar set to the to date in date interval 38127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to be formatted into date interval stirng 38137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param appendTo Output parameter to receive result. 38147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Result is appended to existing contents. 38157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pos On input: an alignment field, if desired. 38167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * On output: the offsets of the alignment field. 38177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @exception IllegalArgumentException when there is non-recognized 38187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern letter 38197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return Reference to 'appendTo' parameter. 38207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 38217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 38227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 38237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 38247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public final StringBuffer intervalFormatByAlgorithm(Calendar fromCalendar, 38257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar toCalendar, 38267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuffer appendTo, 38277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition pos) 38287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throws IllegalArgumentException 38297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 38307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // not support different calendar types and time zones 38317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( !fromCalendar.isEquivalentTo(toCalendar) ) { 38327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("can not format on two different calendars"); 38337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Object[] items = getPatternItems(); 38367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int diffBegin = -1; 38377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int diffEnd = -1; 38387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* look for different formatting string range */ 38407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // look for start of difference 38417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 38427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < items.length; i++) { 38437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( diffCalFieldValue(fromCalendar, toCalendar, items, i) ) { 38447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert diffBegin = i; 38457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 38467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( diffBegin == -1 ) { 38507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // no difference, single date format 38517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return format(fromCalendar, appendTo, pos); 38527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // look for end of difference 38557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = items.length-1; i >= diffBegin; i--) { 38567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( diffCalFieldValue(fromCalendar, toCalendar, items, i) ) { 38577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert diffEnd = i; 38587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 38597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch ( IllegalArgumentException e ) { 38627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(e.toString()); 38637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // full range is different 38667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( diffBegin == 0 && diffEnd == items.length-1 ) { 38677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert format(fromCalendar, appendTo, pos); 38687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert appendTo.append(" \u2013 "); // default separator 38697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert format(toCalendar, appendTo, pos); 38707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return appendTo; 38717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* search for largest calendar field within the different range */ 38757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int highestLevel = 1000; 38767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = diffBegin; i <= diffEnd; i++) { 38777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( items[i] instanceof String) { 38787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 38797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternItem item = (PatternItem)items[i]; 38817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char ch = item.type; 3882f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert int patternCharIndex = getIndexFromChar(ch); 38837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (patternCharIndex == -1) { 38847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Illegal pattern character " + 38857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "'" + ch + "' in \"" + 38867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pattern + '"'); 38877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( patternCharIndex < highestLevel ) { 38907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert highestLevel = patternCharIndex; 38917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* re-calculate diff range, including those calendar field which 38957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert is in lower level than the largest calendar field covered 38967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert in diff range calculated. */ 38977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 38987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < diffBegin; i++) { 38997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( lowerLevel(items, i, highestLevel) ) { 39007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert diffBegin = i; 39017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 39027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 39057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 39067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = items.length-1; i > diffEnd; i--) { 39077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( lowerLevel(items, i, highestLevel) ) { 39087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert diffEnd = i; 39097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 39107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch ( IllegalArgumentException e ) { 39137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(e.toString()); 39147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 39167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 39177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // full range is different 39187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( diffBegin == 0 && diffEnd == items.length-1 ) { 39197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert format(fromCalendar, appendTo, pos); 39207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert appendTo.append(" \u2013 "); // default separator 39217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert format(toCalendar, appendTo, pos); 39227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return appendTo; 39237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 39257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 39267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // formatting 39277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Initialize 39287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setBeginIndex(0); 39297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setEndIndex(0); 39307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DisplayContext capSetting = getContext(DisplayContext.Type.CAPITALIZATION); 39317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 39327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // formatting date 1 39337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i <= diffEnd; i++) { 39347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (items[i] instanceof String) { 39357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert appendTo.append((String)items[i]); 39367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 39377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternItem item = (PatternItem)items[i]; 39387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useFastFormat) { 39397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert subFormat(appendTo, item.type, item.length, appendTo.length(), 39407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i, capSetting, pos, fromCalendar); 39417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 39427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert appendTo.append(subFormat(item.type, item.length, appendTo.length(), 39437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i, capSetting, pos, fromCalendar)); 39447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 39487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert appendTo.append(" \u2013 "); // default separator 39497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 39507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // formatting date 2 39517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = diffBegin; i < items.length; i++) { 39527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (items[i] instanceof String) { 39537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert appendTo.append((String)items[i]); 39547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 39557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternItem item = (PatternItem)items[i]; 39567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useFastFormat) { 39577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert subFormat(appendTo, item.type, item.length, appendTo.length(), 39587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i, capSetting, pos, toCalendar); 39597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 39607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert appendTo.append(subFormat(item.type, item.length, appendTo.length(), 39617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i, capSetting, pos, toCalendar)); 39627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return appendTo; 39667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 39687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 39697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 39707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * check whether the i-th item in 2 calendar is in different value. 39717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 39727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It is supposed to be used only by CLDR survey tool. 39737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It is used by intervalFormatByAlgorithm(). 39747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 39757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param fromCalendar one calendar 39767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param toCalendar the other calendar 39777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param items pattern items 39787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param i the i-th item in pattern items 39797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @exception IllegalArgumentException when there is non-recognized 39807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern letter 39817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true is i-th item in 2 calendar is in different 39827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * value, false otherwise. 39837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 39847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean diffCalFieldValue(Calendar fromCalendar, 39857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Calendar toCalendar, 39867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Object[] items, 39877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int i) throws IllegalArgumentException { 39887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( items[i] instanceof String) { 39897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 39907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternItem item = (PatternItem)items[i]; 39927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char ch = item.type; 3993f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert int patternCharIndex = getIndexFromChar(ch); 39947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (patternCharIndex == -1) { 39957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Illegal pattern character " + 39967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "'" + ch + "' in \"" + 39977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pattern + '"'); 39987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 40007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert final int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex]; 4001f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if (field >= 0) { 4002f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert int value = fromCalendar.get(field); 4003f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert int value_2 = toCalendar.get(field); 4004f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if ( value != value_2 ) { 4005f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert return true; 4006f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 40077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 40097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 40117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 40127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 40137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * check whether the i-th item's level is lower than the input 'level' 40147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 40157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It is supposed to be used only by CLDR survey tool. 40167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It is used by intervalFormatByAlgorithm(). 40177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 40187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param items the pattern items 40197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param i the i-th item in pattern items 40207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param level the level with which the i-th pattern item compared to 40217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @exception IllegalArgumentException when there is non-recognized 40227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern letter 40237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true if i-th pattern item is lower than 'level', 40247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * false otherwise 40257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 40267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean lowerLevel(Object[] items, int i, int level) 40277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throws IllegalArgumentException { 4028f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if (items[i] instanceof String) { 40297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 40307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PatternItem item = (PatternItem)items[i]; 40327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char ch = item.type; 4033f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert int patternCharIndex = getLevelFromChar(ch); 40347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (patternCharIndex == -1) { 40357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Illegal pattern character " + 40367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "'" + ch + "' in \"" + 40377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pattern + '"'); 40387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4040f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert if (patternCharIndex >= level) { 40417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 40427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 40447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 40467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 40477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * allow the user to set the NumberFormat for several fields 40487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It can be a single field like: "y"(year) or "M"(month) 40497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It can be several field combined together: "yMd"(year, month and date) 40507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Note: 40517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1 symbol field is enough for multiple symbol fields (so "y" will override "yy", "yyy") 40527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If the field is not numeric, then override has no effect (like "MMM" will use abbreviation, not numerical field) 40537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 40547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param fields the fields to override 40557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param overrideNF the NumbeferFormat used 40567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @exception IllegalArgumentException when the fields contain invalid field 4057bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * @stable ICU 54 40587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 40597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setNumberFormat(String fields, NumberFormat overrideNF) { 40607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert overrideNF.setGroupingUsed(false); 40617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String nsName = "$" + UUID.randomUUID().toString(); 40627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 40637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // initialize mapping if not there 40647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (numberFormatters == null) { 40657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberFormatters = new HashMap<String, NumberFormat>(); 40667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (overrideMap == null) { 40687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert overrideMap = new HashMap<Character, String>(); 40697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 40717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // separate string into char and add to maps 40727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < fields.length(); i++) { 40737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char field = fields.charAt(i); 40747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (DateFormatSymbols.patternChars.indexOf(field) == -1) { 40757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Illegal field character " + "'" + field + "' in setNumberFormat."); 40767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert overrideMap.put(field, nsName); 40787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberFormatters.put(nsName, overrideNF); 40797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 40817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Since one or more of the override number formatters might be complex, 40827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // we can't rely on the fast numfmt where we have a partial field override. 40837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert useLocalZeroPaddingNumberFormat = false; 40847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 40867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 40877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * give the NumberFormat used for the field like 'y'(year) and 'M'(year) 40887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 40897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param field the field the user wants 40907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return override NumberFormat used for the field 4091bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * @stable ICU 54 40927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 40937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public NumberFormat getNumberFormat(char field) { 40947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Character ovrField; 40957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ovrField = Character.valueOf(field); 40967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (overrideMap != null && overrideMap.containsKey(ovrField)) { 40977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String nsName = overrideMap.get(ovrField).toString(); 40987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert NumberFormat nf = numberFormatters.get(nsName); 40997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return nf; 41007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 41017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return numberFormat; 41027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 41057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void initNumberFormatters(ULocale loc) { 41067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 41077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberFormatters = new HashMap<String, NumberFormat>(); 41087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert overrideMap = new HashMap<Character, String>(); 41097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert processOverrideString(loc,override); 41107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 41117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 41137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void processOverrideString(ULocale loc, String str) { 41147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 41157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( str == null || str.length() == 0 ) 41167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return; 41177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 41187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int start = 0; 41197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int end; 41207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String nsName; 41217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Character ovrField; 41227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean moreToProcess = true; 41237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean fullOverride; 41247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 41257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (moreToProcess) { 41267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int delimiterPosition = str.indexOf(";",start); 41277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (delimiterPosition == -1) { 41287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert moreToProcess = false; 41297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert end = str.length(); 41307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 41317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert end = delimiterPosition; 41327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 41347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String currentString = str.substring(start,end); 41357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int equalSignPosition = currentString.indexOf("="); 41367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (equalSignPosition == -1) { // Simple override string such as "hebrew" 41377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert nsName = currentString; 41387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fullOverride = true; 41397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { // Field specific override string such as "y=hebrew" 41407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert nsName = currentString.substring(equalSignPosition+1); 41417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ovrField = Character.valueOf(currentString.charAt(0)); 41427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert overrideMap.put(ovrField,nsName); 41437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fullOverride = false; 41447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 41467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ULocale ovrLoc = new ULocale(loc.getBaseName()+"@numbers="+nsName); 41477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert NumberFormat nf = NumberFormat.createInstance(ovrLoc,NumberFormat.NUMBERSTYLE); 41487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert nf.setGroupingUsed(false); 41497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 41507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fullOverride) { 41517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setNumberFormat(nf); 41527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 41537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Since one or more of the override number formatters might be complex, 41547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // we can't rely on the fast numfmt where we have a partial field override. 41557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert useLocalZeroPaddingNumberFormat = false; 41567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 41587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!fullOverride && !numberFormatters.containsKey(nsName)) { 41597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberFormatters.put(nsName,nf); 41607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 41627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert start = delimiterPosition + 1; 41637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert} 4166