151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (C) Copyright IBM Corp. 1996-1998 - All Rights Reserved 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The original version of this source code and documentation is copyrighted 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * materials are provided under terms of a License Agreement between Taligent 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and Sun. This technology is protected by multiple US and International 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * patents. This notice and attribution to Taligent may not be removed. 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Taligent is a registered trademark of Taligent, Inc. 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.text; 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 424947038a7acb466855746df19d41ef26be507aa4Joachim Sauerimport android.icu.text.TimeZoneFormat; 434947038a7acb466855746df19d41ef26be507aa4Joachim Sauerimport android.icu.text.TimeZoneNames; 444947038a7acb466855746df19d41ef26be507aa4Joachim Sauerimport android.icu.util.ULocale; 454947038a7acb466855746df19d41ef26be507aa4Joachim Sauer 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException; 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.InvalidObjectException; 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.ObjectInputStream; 494947038a7acb466855746df19d41ef26be507aa4Joachim Sauerimport java.util.Arrays; 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Calendar; 514947038a7acb466855746df19d41ef26be507aa4Joachim Sauerimport java.util.Collection; 524947038a7acb466855746df19d41ef26be507aa4Joachim Sauerimport java.util.Collections; 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Date; 544947038a7acb466855746df19d41ef26be507aa4Joachim Sauerimport java.util.EnumSet; 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.GregorianCalendar; 564947038a7acb466855746df19d41ef26be507aa4Joachim Sauerimport java.util.HashSet; 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Locale; 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Map; 594947038a7acb466855746df19d41ef26be507aa4Joachim Sauerimport java.util.Set; 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.SimpleTimeZone; 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.TimeZone; 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.concurrent.ConcurrentHashMap; 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.concurrent.ConcurrentMap; 649c853c5b9ebbb0ef60a013ae10ee411d70dfa832Piotr Jastrzebskiimport libcore.icu.LocaleData; 65d8bef3c23bf1851242cc2dc189edaa544eeabe58Joachim Sauer 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.util.calendar.CalendarUtils; 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport static java.text.DateFormatSymbols.*; 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 70a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak// Android-changed: Added supported API level, removed unnecessary <br> 71d48197ec78f54c6adb3fec78c3bcc384b7ce2e40Przemyslaw Szczepaniak// Android-changed: Clarified info about X symbol time zone parsing 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>SimpleDateFormat</code> is a concrete class for formatting and 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * parsing dates in a locale-sensitive manner. It allows for formatting 756e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * (date → text), parsing (text → date), and normalization. 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>SimpleDateFormat</code> allows you to start by choosing 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * any user-defined patterns for date-time formatting. However, you 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are encouraged to create a date-time formatter with either 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>getTimeInstance</code>, <code>getDateInstance</code>, or 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>getDateTimeInstance</code> in <code>DateFormat</code>. Each 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of these class methods can return a date/time formatter initialized 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * with a default format pattern. You may modify the format pattern 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * using the <code>applyPattern</code> methods as desired. 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For more information on using these methods, see 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link DateFormat}. 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 896e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <h3>Date and Time Patterns</h3> 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Date and time formats are specified by <em>date and time pattern</em> 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * strings. 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Within date and time pattern strings, unquoted letters from 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>'A'</code> to <code>'Z'</code> and from <code>'a'</code> to 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>'z'</code> are interpreted as pattern letters representing the 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * components of a date or time string. 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Text can be quoted using single quotes (<code>'</code>) to avoid 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * interpretation. 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>"''"</code> represents a single quote. 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * All other characters are not interpreted; they're simply copied into the 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * output string during formatting or matched against the input string 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * during parsing. 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The following pattern letters are defined (all other characters from 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>'A'</code> to <code>'Z'</code> and from <code>'a'</code> to 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>'z'</code> are reserved): 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote> 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <table border=0 cellspacing=3 cellpadding=0 summary="Chart shows pattern letters, date/time component, presentation, and examples."> 1096e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr style="background-color: rgb(204, 204, 255);"> 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <th align=left>Letter 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <th align=left>Date or Time Component 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <th align=left>Presentation 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <th align=left>Examples 114a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <th align=left>Supported (API Levels) 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tr> 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>G</code> 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Era designator 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#text">Text</a> 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>AD</code> 120a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 1216e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr style="background-color: rgb(238, 238, 255);"> 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>y</code> 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Year 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#year">Year</a> 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>1996</code>; <code>96</code> 126a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tr> 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>Y</code> 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Week year 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#year">Year</a> 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>2009</code>; <code>09</code> 1324772860a6a2e4b4a64747c82a51a968ec08f7e13Joachim Sauer * <td>24+</td> 1336e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr style="background-color: rgb(238, 238, 255);"> 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>M</code> 1356e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <td>Month in year (context sensitive) 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#month">Month</a> 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>July</code>; <code>Jul</code>; <code>07</code> 138a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tr> 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>w</code> 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Week in year 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#number">Number</a> 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>27</code> 144a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 1456e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr> 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>W</code> 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Week in month 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#number">Number</a> 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>2</code> 150a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 1516e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr style="background-color: rgb(238, 238, 255);"> 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>D</code> 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Day in year 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#number">Number</a> 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>189</code> 156a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 1576e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr> 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>d</code> 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Day in month 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#number">Number</a> 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>10</code> 162a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 1636e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr style="background-color: rgb(238, 238, 255);"> 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>F</code> 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Day of week in month 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#number">Number</a> 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>2</code> 168a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 1696e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr> 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>E</code> 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Day name in week 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#text">Text</a> 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>Tuesday</code>; <code>Tue</code> 174a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 1756e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr style="background-color: rgb(238, 238, 255);"> 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>u</code> 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Day number of week (1 = Monday, ..., 7 = Sunday) 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#number">Number</a> 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>1</code> 180a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>24+</td> 1816e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr> 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>a</code> 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Am/pm marker 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#text">Text</a> 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>PM</code> 186a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 1876e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr style="background-color: rgb(238, 238, 255);"> 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>H</code> 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Hour in day (0-23) 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#number">Number</a> 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>0</code> 192a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 1936e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr> 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>k</code> 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Hour in day (1-24) 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#number">Number</a> 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>24</code> 198a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 1996e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr style="background-color: rgb(238, 238, 255);"> 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>K</code> 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Hour in am/pm (0-11) 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#number">Number</a> 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>0</code> 204a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 2056e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr> 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>h</code> 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Hour in am/pm (1-12) 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#number">Number</a> 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>12</code> 210a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 2116e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr style="background-color: rgb(238, 238, 255);"> 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>m</code> 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Minute in hour 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#number">Number</a> 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>30</code> 216a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 2176e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr> 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>s</code> 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Second in minute 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#number">Number</a> 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>55</code> 222a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 2236e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr style="background-color: rgb(238, 238, 255);"> 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>S</code> 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Millisecond 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#number">Number</a> 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>978</code> 228a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 2296e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr> 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>z</code> 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Time zone 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#timezone">General time zone</a> 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>Pacific Standard Time</code>; <code>PST</code>; <code>GMT-08:00</code> 234a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 2356e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr style="background-color: rgb(238, 238, 255);"> 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>Z</code> 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Time zone 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#rfc822timezone">RFC 822 time zone</a> 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>-0800</code> 240a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * <td>1+</td> 2416e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr> 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>X</code> 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td>Time zone 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><a href="#iso8601timezone">ISO 8601 time zone</a> 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>-08</code>; <code>-0800</code>; <code>-08:00</code> 2464772860a6a2e4b4a64747c82a51a968ec08f7e13Joachim Sauer * <td>24+</td> 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </table> 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </blockquote> 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Pattern letters are usually repeated, as their number determines the 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * exact presentation: 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <ul> 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li><strong><a name="text">Text:</a></strong> 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For formatting, if the number of pattern letters is 4 or more, 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the full form is used; otherwise a short or abbreviated form 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is used if available. 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For parsing, both forms are accepted, independent of the number 257a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * of pattern letters.</li> 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li><strong><a name="number">Number:</a></strong> 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For formatting, the number of pattern letters is the minimum 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * number of digits, and shorter numbers are zero-padded to this amount. 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For parsing, the number of pattern letters is ignored unless 262a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * it's needed to separate two adjacent fields.</li> 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li><strong><a name="year">Year:</a></strong> 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If the formatter's {@link #getCalendar() Calendar} is the Gregorian 265a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * calendar, the following rules are applied. 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <ul> 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li>For formatting, if the number of pattern letters is 2, the year 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is truncated to 2 digits; otherwise it is interpreted as a 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <a href="#number">number</a>. 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li>For parsing, if the number of pattern letters is more than 2, 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the year is interpreted literally, regardless of the number of 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * digits. So using the pattern "MM/dd/yyyy", "01/11/12" parses to 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Jan 11, 12 A.D. 27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li>For parsing with the abbreviated year pattern ("y" or "yy"), 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>SimpleDateFormat</code> must interpret the abbreviated year 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * relative to some century. It does this by adjusting dates to be 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * within 80 years before and 20 years after the time the <code>SimpleDateFormat</code> 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * instance is created. For example, using a pattern of "MM/dd/yy" and a 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>SimpleDateFormat</code> instance created on Jan 1, 1997, the string 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * "01/11/12" would be interpreted as Jan 11, 2012 while the string "05/04/64" 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * would be interpreted as May 4, 1964. 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * During parsing, only strings consisting of exactly two digits, as defined by 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link Character#isDigit(char)}, will be parsed into the default century. 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Any other numeric string, such as a one digit string, a three or more digit 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * string, or a two digit string that isn't all digits (for example, "-1"), is 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * interpreted literally. So "01/02/3" or "01/02/003" are parsed, using the 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * same pattern, as Jan 2, 3 AD. Likewise, "01/02/-3" is parsed as Jan 2, 4 BC. 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </ul> 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Otherwise, calendar system specific forms are applied. 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For both formatting and parsing, if the number of pattern 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * letters is 4 or more, a calendar specific {@linkplain 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Calendar#LONG long form} is used. Otherwise, a calendar 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * specific {@linkplain Calendar#SHORT short or abbreviated form} 294a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * is used. 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <br> 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If week year {@code 'Y'} is specified and the {@linkplain 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * #getCalendar() calendar} doesn't support any <a 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * href="../util/GregorianCalendar.html#week_year"> week 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * years</a>, the calendar year ({@code 'y'}) is used instead. The 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * support of week years can be tested with a call to {@link 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DateFormat#getCalendar() getCalendar()}.{@link 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * java.util.Calendar#isWeekDateSupported() 303a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * isWeekDateSupported()}.</li> 30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li><strong><a name="month">Month:</a></strong> 30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If the number of pattern letters is 3 or more, the month is 30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * interpreted as <a href="#text">text</a>; otherwise, 307a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * it is interpreted as a <a href="#number">number</a>.</li> 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li><strong><a name="timezone">General time zone:</a></strong> 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Time zones are interpreted as <a href="#text">text</a> if they have 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * names. For time zones representing a GMT offset value, the 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * following syntax is used: 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <pre> 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <a name="GMTOffsetTimeZone"><i>GMTOffsetTimeZone:</i></a> 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>GMT</code> <i>Sign</i> <i>Hours</i> <code>:</code> <i>Minutes</i> 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>Sign:</i> one of 31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>+ -</code> 31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>Hours:</i> 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>Digit</i> 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>Digit</i> <i>Digit</i> 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>Minutes:</i> 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>Digit</i> <i>Digit</i> 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>Digit:</i> one of 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>0 1 2 3 4 5 6 7 8 9</code></pre> 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>Hours</i> must be between 0 and 23, and <i>Minutes</i> must be between 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 00 and 59. The format is locale independent and digits must be taken 32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * from the Basic Latin block of the Unicode standard. 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>For parsing, <a href="#rfc822timezone">RFC 822 time zones</a> are also 328a17c83ea5f83606615aed6a86cbb8a8ad8444723Przemyslaw Szczepaniak * accepted.</li> 32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li><strong><a name="rfc822timezone">RFC 822 time zone:</a></strong> 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For formatting, the RFC 822 4-digit time zone format is used: 33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <pre> 33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>RFC822TimeZone:</i> 33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>Sign</i> <i>TwoDigitHours</i> <i>Minutes</i> 33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>TwoDigitHours:</i> 33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>Digit Digit</i></pre> 33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>TwoDigitHours</i> must be between 00 and 23. Other definitions 33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are as for <a href="#timezone">general time zones</a>. 33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>For parsing, <a href="#timezone">general time zones</a> are also 34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accepted. 34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li><strong><a name="iso8601timezone">ISO 8601 Time zone:</a></strong> 34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The number of pattern letters designates the format for both formatting 34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and parsing as follows: 34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <pre> 34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>ISO8601TimeZone:</i> 34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>OneLetterISO8601TimeZone</i> 34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>TwoLetterISO8601TimeZone</i> 34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>ThreeLetterISO8601TimeZone</i> 35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>OneLetterISO8601TimeZone:</i> 35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>Sign</i> <i>TwoDigitHours</i> 35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@code Z} 35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>TwoLetterISO8601TimeZone:</i> 35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>Sign</i> <i>TwoDigitHours</i> <i>Minutes</i> 35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@code Z} 35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>ThreeLetterISO8601TimeZone:</i> 35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>Sign</i> <i>TwoDigitHours</i> {@code :} <i>Minutes</i> 35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@code Z}</pre> 35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Other definitions are as for <a href="#timezone">general time zones</a> or 36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <a href="#rfc822timezone">RFC 822 time zones</a>. 36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>For formatting, if the offset value from GMT is 0, {@code "Z"} is 36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * produced. If the number of pattern letters is 1, any fraction of an hour 36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is ignored. For example, if the pattern is {@code "X"} and the time zone is 36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@code "GMT+05:30"}, {@code "+05"} is produced. 36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 367d48197ec78f54c6adb3fec78c3bcc384b7ce2e40Przemyslaw Szczepaniak * <p>For parsing, the letter {@code "Z"} is parsed as the UTC time zone designator (therefore 368d48197ec78f54c6adb3fec78c3bcc384b7ce2e40Przemyslaw Szczepaniak * {@code "09:30Z"} is parsed as {@code "09:30 UTC"}. 36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <a href="#timezone">General time zones</a> are <em>not</em> accepted. 370d48197ec78f54c6adb3fec78c3bcc384b7ce2e40Przemyslaw Szczepaniak * <p>If the number of {@code "X"} pattern letters is 4 or more (e.g. {@code XXXX}), {@link 37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * IllegalArgumentException} is thrown when constructing a {@code 37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * SimpleDateFormat} or {@linkplain #applyPattern(String) applying a 37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * pattern}. 37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </ul> 37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>SimpleDateFormat</code> also supports <em>localized date and time 37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * pattern</em> strings. In these strings, the pattern letters described above 37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * may be replaced with other, locale dependent, pattern letters. 37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>SimpleDateFormat</code> does not deal with the localization of text 37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * other than the pattern letters; that's up to the client of the class. 38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <h4>Examples</h4> 38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The following examples show how date and time patterns are interpreted in 38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the U.S. locale. The given date and time are 2001-07-04 12:08:56 local time 38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * in the U.S. Pacific Time time zone. 38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote> 38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <table border=0 cellspacing=3 cellpadding=0 summary="Examples of date and time patterns interpreted in the U.S. locale"> 3886e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr style="background-color: rgb(204, 204, 255);"> 38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <th align=left>Date and Time Pattern 39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <th align=left>Result 39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tr> 39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>"yyyy.MM.dd G 'at' HH:mm:ss z"</code> 39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>2001.07.04 AD at 12:08:56 PDT</code> 3946e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr style="background-color: rgb(238, 238, 255);"> 39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>"EEE, MMM d, ''yy"</code> 39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>Wed, Jul 4, '01</code> 39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tr> 39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>"h:mm a"</code> 39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>12:08 PM</code> 4006e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr style="background-color: rgb(238, 238, 255);"> 40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>"hh 'o''clock' a, zzzz"</code> 40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>12 o'clock PM, Pacific Daylight Time</code> 40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tr> 40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>"K:mm a, z"</code> 40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>0:08 PM, PDT</code> 4066e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr style="background-color: rgb(238, 238, 255);"> 40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>"yyyyy.MMMMM.dd GGG hh:mm aaa"</code> 40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>02001.July.04 AD 12:08 PM</code> 40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tr> 41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>"EEE, d MMM yyyy HH:mm:ss Z"</code> 41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>Wed, 4 Jul 2001 12:08:56 -0700</code> 4126e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr style="background-color: rgb(238, 238, 255);"> 41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>"yyMMddHHmmssZ"</code> 41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>010704120856-0700</code> 41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tr> 41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>"yyyy-MM-dd'T'HH:mm:ss.SSSZ"</code> 41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>2001-07-04T12:08:56.235-0700</code> 4186e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <tr style="background-color: rgb(238, 238, 255);"> 41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"</code> 42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>2001-07-04T12:08:56.235-07:00</code> 42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tr> 42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>"YYYY-'W'ww-u"</code> 42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <td><code>2001-W27-3</code> 42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </table> 42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </blockquote> 42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <h4><a name="synchronization">Synchronization</a></h4> 42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Date formats are not synchronized. 43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * It is recommended to create separate format instances for each thread. 43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If multiple threads access a format concurrently, it must be synchronized 43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * externally. 43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 4356e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * @see <a href="https://docs.oracle.com/javase/tutorial/i18n/format/simpleDateFormat.html">Java Tutorial</a> 43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.util.Calendar 43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.util.TimeZone 43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see DateFormat 43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see DateFormatSymbols 44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Mark Davis, Chen-Lieh Huang, Alan Liu 44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class SimpleDateFormat extends DateFormat { 44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // the official serial version ID which says cryptically 44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // which version we're compatible with 44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static final long serialVersionUID = 4774881970558875024L; 44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // the internal serial version which says which version was written 44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // - 0 (default) for version up to JDK 1.1.3 45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // - 1 for version from JDK 1.1.4, which includes a new field 45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static final int currentSerialVersion = 1; 45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The version of the serialized data on the stream. Possible values: 45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <ul> 45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li><b>0</b> or not present on stream: JDK 1.1.3. This version 45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * has no <code>defaultCenturyStart</code> on stream. 45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li><b>1</b> JDK 1.1.4 or later. This version adds 45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>defaultCenturyStart</code>. 46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </ul> 46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * When streaming out this class, the most recent format 46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and the highest allowable <code>serialVersionOnStream</code> 46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is written. 46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @serial 46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since JDK1.1.4 46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int serialVersionOnStream = currentSerialVersion; 46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The pattern string of this formatter. This is always a non-localized 47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * pattern. May not be null. See class documentation for details. 47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @serial 47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private String pattern; 47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Saved numberFormat and pattern. 47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see SimpleDateFormat#checkNegativeNumberExpression 47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski transient private NumberFormat originalNumberFormat; 48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski transient private String originalNumberPattern; 48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The minus sign to be used with format and parse. 48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski transient private char minusSign = '-'; 48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * True when a negative sign follows a number. 49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (True as default in Arabic.) 49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski transient private boolean hasFollowingMinusSign = false; 49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The compiled pattern. 49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski transient private char[] compiledPattern; 49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Tags for the compiled pattern. 50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final static int TAG_QUOTE_ASCII_CHAR = 100; 50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final static int TAG_QUOTE_CHARS = 101; 50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Locale dependent digit zero. 50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #zeroPaddingNumber 50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.text.DecimalFormatSymbols#getZeroDigit 50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski transient private char zeroDigit; 51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The symbols used by this formatter for week names, month names, 51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * etc. May not be null. 51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @serial 51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.text.DateFormatSymbols 51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private DateFormatSymbols formatData; 51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * We map dates with two-digit years into the century starting at 52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>defaultCenturyStart</code>, which may be any date. May 52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * not be null. 52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @serial 52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since JDK1.1.4 52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Date defaultCenturyStart; 52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski transient private int defaultCenturyStartYear; 53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int MILLIS_PER_MINUTE = 60 * 1000; 53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // For time zones that have no names, use strings GMT+minutes and 53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // GMT-minutes. For instance, in France the time zone is GMT+60. 53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final String GMT = "GMT"; 53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Cache NumberFormat instances with Locale key. 53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final ConcurrentMap<Locale, NumberFormat> cachedNumberFormatData 541af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin = new ConcurrentHashMap<>(3); 54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The Locale used to instantiate this 54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>SimpleDateFormat</code>. The value may be null if this object 54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * has been created by an older <code>SimpleDateFormat</code> and 54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * deserialized. 54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @serial 55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.6 55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Locale locale; 55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Indicates whether this <code>SimpleDateFormat</code> should use 55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the DateFormatSymbols. If true, the format and parse methods 55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * use the DateFormatSymbols values. If false, the format and 55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * parse methods call Calendar.getDisplayName or 55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Calendar.getDisplayNames. 56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski transient boolean useDateFormatSymbols; 56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 563d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // Android-added: ICU TimeZoneNames field. 56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 5654947038a7acb466855746df19d41ef26be507aa4Joachim Sauer * ICU TimeZoneNames used to format and parse time zone names. 5664947038a7acb466855746df19d41ef26be507aa4Joachim Sauer */ 5674947038a7acb466855746df19d41ef26be507aa4Joachim Sauer private transient TimeZoneNames timeZoneNames; 5684947038a7acb466855746df19d41ef26be507aa4Joachim Sauer 5694947038a7acb466855746df19d41ef26be507aa4Joachim Sauer /** 57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Constructs a <code>SimpleDateFormat</code> using the default pattern and 5716e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * date format symbols for the default 5726e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * {@link java.util.Locale.Category#FORMAT FORMAT} locale. 57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <b>Note:</b> This constructor may not support all locales. 57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For full coverage, use the factory methods in the {@link DateFormat} 57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * class. 57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public SimpleDateFormat() { 57859f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang // Android-changed: Android has no LocaleProviderAdapter. Use ICU locale data. 57959f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang // this("", Locale.getDefault(Locale.Category.FORMAT)); 58059f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang // applyPatternImpl(LocaleProviderAdapter.getResourceBundleBased().getLocaleResources(locale) 58159f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang // .getDateTimePattern(SHORT, SHORT, calendar)); 58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this(SHORT, SHORT, Locale.getDefault(Locale.Category.FORMAT)); 58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 58559f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang // BEGIN Android-added: Ctor used by DateFormat to remove use of LocaleProviderAdapter. 58659f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang /** 58759f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang * Constructs a <code>SimpleDateFormat</code> using the given date and time formatting styles. 58859f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang * @param timeStyle the given date formatting style. 58959f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang * @param dateStyle the given time formatting style. 59059f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang * @param locale the locale whose pattern and date format symbols should be used 59159f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang */ 59259f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang SimpleDateFormat(int timeStyle, int dateStyle, Locale locale) { 59359f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang this(getDateTimeFormat(timeStyle, dateStyle, locale), locale); 59459f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang } 59559f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang 59659f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang private static String getDateTimeFormat(int timeStyle, int dateStyle, Locale locale) { 59759f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang LocaleData localeData = LocaleData.get(locale); 59859f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang if ((timeStyle >= 0) && (dateStyle >= 0)) { 59959f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang Object[] dateTimeArgs = { 60059f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang localeData.getDateFormat(dateStyle), 60159f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang localeData.getTimeFormat(timeStyle), 60259f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang }; 60359f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang return MessageFormat.format("{0} {1}", dateTimeArgs); 60459f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang } else if (timeStyle >= 0) { 60559f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang return localeData.getTimeFormat(timeStyle); 60659f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang } else if (dateStyle >= 0) { 60759f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang return localeData.getDateFormat(dateStyle); 60859f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang } else { 60959f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang throw new IllegalArgumentException("No date or time style specified"); 61059f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang } 61159f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang } 61259f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang // END Android-added: Ctor used by DateFormat to remove use of LocaleProviderAdapter. 61359f1a7d46654a2893d38532d2cfb33c1e6af1dd4Victor Chang 61451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 61551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Constructs a <code>SimpleDateFormat</code> using the given pattern and 6166e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * the default date format symbols for the default 6176e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * {@link java.util.Locale.Category#FORMAT FORMAT} locale. 61851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <b>Note:</b> This constructor may not support all locales. 61951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For full coverage, use the factory methods in the {@link DateFormat} 62051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * class. 6216e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * <p>This is equivalent to calling 6226e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * {@link #SimpleDateFormat(String, Locale) 6236e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * SimpleDateFormat(pattern, Locale.getDefault(Locale.Category.FORMAT))}. 62451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 6256e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * @see java.util.Locale#getDefault(java.util.Locale.Category) 6266e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * @see java.util.Locale.Category#FORMAT 62751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param pattern the pattern describing the date and time format 62851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception NullPointerException if the given pattern is null 62951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IllegalArgumentException if the given pattern is invalid 63051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 63151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public SimpleDateFormat(String pattern) 63251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 63351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this(pattern, Locale.getDefault(Locale.Category.FORMAT)); 63451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 63551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 63651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 63751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Constructs a <code>SimpleDateFormat</code> using the given pattern and 63851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the default date format symbols for the given locale. 63951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <b>Note:</b> This constructor may not support all locales. 64051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For full coverage, use the factory methods in the {@link DateFormat} 64151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * class. 64251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 64351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param pattern the pattern describing the date and time format 64451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param locale the locale whose date format symbols should be used 64551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception NullPointerException if the given pattern or locale is null 64651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IllegalArgumentException if the given pattern is invalid 64751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 64851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public SimpleDateFormat(String pattern, Locale locale) 64951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 65051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pattern == null || locale == null) { 65151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new NullPointerException(); 65251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 65351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 65451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski initializeCalendar(locale); 65551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.pattern = pattern; 65651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.formatData = DateFormatSymbols.getInstanceRef(locale); 65751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.locale = locale; 65851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski initialize(locale); 65951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 66051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 66151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 66251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Constructs a <code>SimpleDateFormat</code> using the given pattern and 66351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * date format symbols. 66451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 66551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param pattern the pattern describing the date and time format 66651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param formatSymbols the date format symbols to be used for formatting 66751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception NullPointerException if the given pattern or formatSymbols is null 66851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IllegalArgumentException if the given pattern is invalid 66951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 67051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public SimpleDateFormat(String pattern, DateFormatSymbols formatSymbols) 67151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 67251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pattern == null || formatSymbols == null) { 67351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new NullPointerException(); 67451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 67551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 67651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.pattern = pattern; 67751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.formatData = (DateFormatSymbols) formatSymbols.clone(); 67851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.locale = Locale.getDefault(Locale.Category.FORMAT); 67951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski initializeCalendar(this.locale); 68051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski initialize(this.locale); 68151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski useDateFormatSymbols = true; 68251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 68351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 68451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Initialize compiledPattern and numberFormat fields */ 68551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void initialize(Locale loc) { 68651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Verify and compile the given pattern. 68751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski compiledPattern = compile(pattern); 68851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 68951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* try the cache first */ 69051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski numberFormat = cachedNumberFormatData.get(loc); 69151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (numberFormat == null) { /* cache miss */ 69251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski numberFormat = NumberFormat.getIntegerInstance(loc); 69351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski numberFormat.setGroupingUsed(false); 69451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 69551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* update cache */ 69651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cachedNumberFormatData.putIfAbsent(loc, numberFormat); 69751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 69851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski numberFormat = (NumberFormat) numberFormat.clone(); 69951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 70051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski initializeDefaultCentury(); 70151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 70251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 70351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void initializeCalendar(Locale loc) { 70451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (calendar == null) { 70551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski assert loc != null; 70651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // The format object must be constructed using the symbols for this zone. 70751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // However, the calendar should use the current default TimeZone. 70851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // If this is not contained in the locale zone strings, then the zone 70951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // will be formatted using generic GMT+/-H:MM nomenclature. 71051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski calendar = Calendar.getInstance(TimeZone.getDefault(), loc); 71151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 71251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 71351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 71451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 71551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the compiled form of the given pattern. The syntax of 71651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the compiled pattern is: 71751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote> 71851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * CompiledPattern: 71951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * EntryList 72051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * EntryList: 72151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Entry 72251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * EntryList Entry 72351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Entry: 72451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * TagField 72551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * TagField data 72651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * TagField: 72751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Tag Length 72851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * TaggedData 72951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Tag: 73051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * pattern_char_index 73151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * TAG_QUOTE_CHARS 73251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Length: 73351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * short_length 73451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * long_length 73551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * TaggedData: 73651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * TAG_QUOTE_ASCII_CHAR ascii_char 73751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 73851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </blockquote> 73951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 74051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * where `short_length' is an 8-bit unsigned integer between 0 and 74151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 254. `long_length' is a sequence of an 8-bit integer 255 and a 74251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 32-bit signed integer value which is split into upper and lower 74351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 16-bit fields in two char's. `pattern_char_index' is an 8-bit 74451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * integer between 0 and 18. `ascii_char' is an 7-bit ASCII 74551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * character value. `data' depends on its Tag value. 74651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 74751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If Length is short_length, Tag and short_length are packed in a 74851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * single char, as illustrated below. 74951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote> 75051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * char[0] = (Tag << 8) | short_length; 75151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </blockquote> 75251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 75351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If Length is long_length, Tag and 255 are packed in the first 75451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * char and a 32-bit integer, as illustrated below. 75551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote> 75651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * char[0] = (Tag << 8) | 255; 75751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * char[1] = (char) (long_length >>> 16); 75851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * char[2] = (char) (long_length & 0xffff); 75951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </blockquote> 76051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 76151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If Tag is a pattern_char_index, its Length is the number of 76251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * pattern characters. For example, if the given pattern is 76351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * "yyyy", Tag is 1 and Length is 4, followed by no data. 76451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 76551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If Tag is TAG_QUOTE_CHARS, its Length is the number of char's 76651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * following the TagField. For example, if the given pattern is 76751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * "'o''clock'", Length is 7 followed by a char sequence of 76851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>o&nbs;'&nbs;c&nbs;l&nbs;o&nbs;c&nbs;k</code>. 76951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 77051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * TAG_QUOTE_ASCII_CHAR is a special tag and has an ASCII 77151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * character in place of Length. For example, if the given pattern 77251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is "'o'", the TaggedData entry is 77351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>((TAG_QUOTE_ASCII_CHAR&nbs;<<&nbs;8)&nbs;|&nbs;'o')</code>. 77451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 77551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception NullPointerException if the given pattern is null 77651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IllegalArgumentException if the given pattern is invalid 77751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 77851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private char[] compile(String pattern) { 77951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int length = pattern.length(); 78051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean inQuote = false; 781af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin StringBuilder compiledCode = new StringBuilder(length * 2); 78251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski StringBuilder tmpBuffer = null; 78351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int count = 0; 78451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int lastTag = -1; 78551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 78651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < length; i++) { 78751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = pattern.charAt(i); 78851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 78951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c == '\'') { 79051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // '' is treated as a single quote regardless of being 79151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // in a quoted section. 79251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((i + 1) < length) { 79351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski c = pattern.charAt(i + 1); 79451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c == '\'') { 79551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski i++; 79651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (count != 0) { 797af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin encode(lastTag, count, compiledCode); 79851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski lastTag = -1; 79951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count = 0; 80051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 80151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (inQuote) { 80251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tmpBuffer.append(c); 80351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 804af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin compiledCode.append((char)(TAG_QUOTE_ASCII_CHAR << 8 | c)); 80551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 80651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski continue; 80751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 80851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 80951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!inQuote) { 81051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (count != 0) { 811af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin encode(lastTag, count, compiledCode); 81251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski lastTag = -1; 81351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count = 0; 81451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 81551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tmpBuffer == null) { 81651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tmpBuffer = new StringBuilder(length); 81751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 81851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tmpBuffer.setLength(0); 81951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 82051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski inQuote = true; 82151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 82251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int len = tmpBuffer.length(); 82351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len == 1) { 82451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char ch = tmpBuffer.charAt(0); 82551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (ch < 128) { 826af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin compiledCode.append((char)(TAG_QUOTE_ASCII_CHAR << 8 | ch)); 82751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 828af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin compiledCode.append((char)(TAG_QUOTE_CHARS << 8 | 1)); 829af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin compiledCode.append(ch); 83051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 83151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 832af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin encode(TAG_QUOTE_CHARS, len, compiledCode); 833af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin compiledCode.append(tmpBuffer); 83451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 83551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski inQuote = false; 83651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 83751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski continue; 83851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 83951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (inQuote) { 84051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tmpBuffer.append(c); 84151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski continue; 84251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 84351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) { 84451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (count != 0) { 845af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin encode(lastTag, count, compiledCode); 84651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski lastTag = -1; 84751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count = 0; 84851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 84951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c < 128) { 85051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // In most cases, c would be a delimiter, such as ':'. 851af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin compiledCode.append((char)(TAG_QUOTE_ASCII_CHAR << 8 | c)); 85251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 85351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Take any contiguous non-ASCII alphabet characters and 85451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // put them in a single TAG_QUOTE_CHARS. 85551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int j; 85651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (j = i + 1; j < length; j++) { 85751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char d = pattern.charAt(j); 85851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (d == '\'' || (d >= 'a' && d <= 'z' || d >= 'A' && d <= 'Z')) { 85951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 86051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 86151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 862af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin compiledCode.append((char)(TAG_QUOTE_CHARS << 8 | (j - i))); 86351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (; i < j; i++) { 864af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin compiledCode.append(pattern.charAt(i)); 86551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 86651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski i--; 86751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 86851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski continue; 86951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 87051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 87151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int tag; 87251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((tag = DateFormatSymbols.patternChars.indexOf(c)) == -1) { 87351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("Illegal pattern character " + 87451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "'" + c + "'"); 87551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 87651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (lastTag == -1 || lastTag == tag) { 87751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski lastTag = tag; 87851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count++; 87951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski continue; 88051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 881af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin encode(lastTag, count, compiledCode); 88251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski lastTag = tag; 88351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count = 1; 88451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 88551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 88651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (inQuote) { 88751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("Unterminated quote"); 88851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 88951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 89051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (count != 0) { 891af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin encode(lastTag, count, compiledCode); 89251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 89351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 89451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Copy the compiled pattern to a char array 895af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin int len = compiledCode.length(); 89651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char[] r = new char[len]; 897af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin compiledCode.getChars(0, len, r, 0); 89851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return r; 89951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 90051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 90151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 90251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Encodes the given tag and length and puts encoded char(s) into buffer. 90351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 9046e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin private static void encode(int tag, int length, StringBuilder buffer) { 90551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tag == PATTERN_ISO_ZONE && length >= 4) { 90651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("invalid ISO 8601 format: length=" + length); 90751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 90851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (length < 255) { 90951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append((char)(tag << 8 | length)); 91051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 91151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append((char)((tag << 8) | 0xff)); 91251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append((char)(length >>> 16)); 91351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append((char)(length & 0xffff)); 91451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 91551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 91651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 91751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Initialize the fields we use to disambiguate ambiguous years. Separate 91851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * so we can call it from readObject(). 91951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 92051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void initializeDefaultCentury() { 92151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski calendar.setTimeInMillis(System.currentTimeMillis()); 92251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski calendar.add( Calendar.YEAR, -80 ); 92351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski parseAmbiguousDatesAsAfter(calendar.getTime()); 92451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 92551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 92651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Define one-century window into which to disambiguate dates using 92751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * two-digit years. 92851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 92951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void parseAmbiguousDatesAsAfter(Date startDate) { 93051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski defaultCenturyStart = startDate; 93151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski calendar.setTime(startDate); 93251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski defaultCenturyStartYear = calendar.get(Calendar.YEAR); 93351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 93451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 93551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 93651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sets the 100-year period 2-digit years will be interpreted as being in 93751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to begin on the date the user specifies. 93851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 93951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param startDate During parsing, two digit years will be placed in the range 94051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>startDate</code> to <code>startDate + 100 years</code>. 94151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #get2DigitYearStart 94251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.2 94351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 94451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void set2DigitYearStart(Date startDate) { 94551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski parseAmbiguousDatesAsAfter(new Date(startDate.getTime())); 94651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 94751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 94851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 94951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the beginning date of the 100-year period 2-digit years are interpreted 95051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as being within. 95151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 95251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the start of the 100-year period into which two digit years are 95351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * parsed 95451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #set2DigitYearStart 95551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.2 95651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 95751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Date get2DigitYearStart() { 95851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (Date) defaultCenturyStart.clone(); 95951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 96051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 96151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 96251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Formats the given <code>Date</code> into a date/time string and appends 96351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the result to the given <code>StringBuffer</code>. 96451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 96551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param date the date-time value to be formatted into a date-time string. 96651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param toAppendTo where the new date-time text is to be appended. 96751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param pos the formatting position. On input: an alignment field, 96851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if desired. On output: the offsets of the alignment field. 96951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the formatted date-time string. 97051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception NullPointerException if the given {@code date} is {@code null}. 97151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 9726e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin @Override 97351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public StringBuffer format(Date date, StringBuffer toAppendTo, 97451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FieldPosition pos) 97551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 97651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos.beginIndex = pos.endIndex = 0; 97751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return format(date, toAppendTo, pos.getFieldDelegate()); 97851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 97951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 98051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Called from Format after creating a FieldDelegate 98151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private StringBuffer format(Date date, StringBuffer toAppendTo, 98251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FieldDelegate delegate) { 98351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Convert input date to time field list 98451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski calendar.setTime(date); 98551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 98651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean useDateFormatSymbols = useDateFormatSymbols(); 98751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 98851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < compiledPattern.length; ) { 98951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int tag = compiledPattern[i] >>> 8; 99051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int count = compiledPattern[i++] & 0xff; 99151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (count == 255) { 99251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count = compiledPattern[i++] << 16; 99351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count |= compiledPattern[i++]; 99451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 99551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 99651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski switch (tag) { 99751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case TAG_QUOTE_ASCII_CHAR: 99851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski toAppendTo.append((char)count); 99951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 100051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 100151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case TAG_QUOTE_CHARS: 100251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski toAppendTo.append(compiledPattern, i, count); 100351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski i += count; 100451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 100551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 100651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski default: 100751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols); 100851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 100951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 101051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 101151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return toAppendTo; 101251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 101351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 101451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 101551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Formats an Object producing an <code>AttributedCharacterIterator</code>. 101651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You can use the returned <code>AttributedCharacterIterator</code> 101751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to build the resulting String, as well as to determine information 101851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * about the resulting String. 101951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 102051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Each attribute key of the AttributedCharacterIterator will be of type 102151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>DateFormat.Field</code>, with the corresponding attribute value 102251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * being the same as the attribute key. 102351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 102451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception NullPointerException if obj is null. 102551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IllegalArgumentException if the Format cannot format the 102651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * given object, or if the Format's pattern string is invalid. 102751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param obj The object to format 102851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return AttributedCharacterIterator describing the formatted value. 102951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.4 103051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 10316e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin @Override 103251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public AttributedCharacterIterator formatToCharacterIterator(Object obj) { 103351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski StringBuffer sb = new StringBuffer(); 103451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CharacterIteratorFieldDelegate delegate = new 103551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CharacterIteratorFieldDelegate(); 103651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 103751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (obj instanceof Date) { 103851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski format((Date)obj, sb, delegate); 103951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 104051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else if (obj instanceof Number) { 104151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski format(new Date(((Number)obj).longValue()), sb, delegate); 104251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 104351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else if (obj == null) { 104451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new NullPointerException( 104551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "formatToCharacterIterator must be passed non-null object"); 104651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 104751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else { 104851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException( 104951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "Cannot format given Object as a Date"); 105051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 105151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return delegate.getIterator(sb.toString()); 105251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 105351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 105451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Map index into pattern character string to Calendar field number 10556e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin private static final int[] PATTERN_INDEX_TO_CALENDAR_FIELD = { 10566e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.ERA, 10576e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.YEAR, 10586e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.MONTH, 10596e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.DATE, 10606e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.HOUR_OF_DAY, 10616e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.HOUR_OF_DAY, 10626e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.MINUTE, 10636e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.SECOND, 10646e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.MILLISECOND, 10656e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.DAY_OF_WEEK, 10666e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.DAY_OF_YEAR, 10676e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.DAY_OF_WEEK_IN_MONTH, 10686e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.WEEK_OF_YEAR, 10696e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.WEEK_OF_MONTH, 10706e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.AM_PM, 10716e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.HOUR, 10726e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.HOUR, 107351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Calendar.ZONE_OFFSET, 10746e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Calendar.ZONE_OFFSET, 10756e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin CalendarBuilder.WEEK_YEAR, // Pseudo Calendar field 10766e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin CalendarBuilder.ISO_DAY_OF_WEEK, // Pseudo Calendar field 1077b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath Calendar.ZONE_OFFSET, 1078b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath Calendar.MONTH, 1079d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // Android-added: 'c' for standalone day of week. 108080339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang Calendar.DAY_OF_WEEK, 108180339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang // Android-added: Support for 'b'/'B' (day period). Calendar.AM_PM is just used as a 108280339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang // placeholder in the absence of full support for day period. 108380339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang Calendar.AM_PM, 108480339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang Calendar.AM_PM 108551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }; 108651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 108751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Map index into pattern character string to DateFormat field number 108851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int[] PATTERN_INDEX_TO_DATE_FORMAT_FIELD = { 10896e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.ERA_FIELD, 10906e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.YEAR_FIELD, 10916e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.MONTH_FIELD, 10926e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.DATE_FIELD, 10936e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.HOUR_OF_DAY1_FIELD, 10946e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.HOUR_OF_DAY0_FIELD, 10956e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.MINUTE_FIELD, 10966e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.SECOND_FIELD, 10976e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.MILLISECOND_FIELD, 10986e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.DAY_OF_WEEK_FIELD, 10996e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.DAY_OF_YEAR_FIELD, 11006e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD, 11016e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.WEEK_OF_YEAR_FIELD, 11026e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.WEEK_OF_MONTH_FIELD, 11036e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.AM_PM_FIELD, 11046e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.HOUR1_FIELD, 11056e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.HOUR0_FIELD, 11066e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.TIMEZONE_FIELD, 11076e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.TIMEZONE_FIELD, 11086e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.YEAR_FIELD, 11096e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin DateFormat.DAY_OF_WEEK_FIELD, 1110b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath DateFormat.TIMEZONE_FIELD, 1111b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath DateFormat.MONTH_FIELD, 1112d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // Android-added: 'c' for standalone day of week. 111380339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang DateFormat.DAY_OF_WEEK_FIELD, 111480339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang // Android-added: Support for 'b'/'B' (day period). DateFormat.AM_PM_FIELD is just used as a 111580339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang // placeholder in the absence of full support for day period. 111680339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang DateFormat.AM_PM_FIELD, 111780339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang DateFormat.AM_PM_FIELD 111851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }; 111951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 112051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Maps from DecimalFormatSymbols index to Field constant 112151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final Field[] PATTERN_INDEX_TO_DATE_FORMAT_FIELD_ID = { 11226e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.ERA, 11236e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.YEAR, 11246e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.MONTH, 11256e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.DAY_OF_MONTH, 11266e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.HOUR_OF_DAY1, 11276e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.HOUR_OF_DAY0, 11286e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.MINUTE, 11296e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.SECOND, 11306e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.MILLISECOND, 11316e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.DAY_OF_WEEK, 11326e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.DAY_OF_YEAR, 11336e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.DAY_OF_WEEK_IN_MONTH, 11346e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.WEEK_OF_YEAR, 11356e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.WEEK_OF_MONTH, 11366e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.AM_PM, 11376e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.HOUR1, 11386e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.HOUR0, 113951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Field.TIME_ZONE, 11406e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.TIME_ZONE, 11416e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.YEAR, 11426e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Field.DAY_OF_WEEK, 1143b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath Field.TIME_ZONE, 1144b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath Field.MONTH, 1145d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // Android-added: 'c' for standalone day of week. 114680339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang Field.DAY_OF_WEEK, 114780339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang // Android-added: Support for 'b'/'B' (day period). Field.AM_PM is just used as a 114880339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang // placeholder in the absence of full support for day period. 114980339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang Field.AM_PM, 115080339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang Field.AM_PM 115151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }; 115251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 115351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 115451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Private member function that does the real date/time formatting. 115551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 115651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void subFormat(int patternCharIndex, int count, 115751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FieldDelegate delegate, StringBuffer buffer, 115851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean useDateFormatSymbols) 115951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 116051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int maxIntCount = Integer.MAX_VALUE; 116151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String current = null; 116251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int beginOffset = buffer.length(); 116351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 116451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex]; 116551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int value; 116651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (field == CalendarBuilder.WEEK_YEAR) { 116751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (calendar.isWeekDateSupported()) { 116851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value = calendar.getWeekYear(); 116951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 117051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // use calendar year 'y' instead 117151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski patternCharIndex = PATTERN_YEAR; 117251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex]; 117351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value = calendar.get(field); 117451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 117551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (field == CalendarBuilder.ISO_DAY_OF_WEEK) { 117651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value = CalendarBuilder.toISODayOfWeek(calendar.get(Calendar.DAY_OF_WEEK)); 117751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 117851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value = calendar.get(field); 117951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 118051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 118151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int style = (count >= 4) ? Calendar.LONG : Calendar.SHORT; 118251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!useDateFormatSymbols && field != CalendarBuilder.ISO_DAY_OF_WEEK) { 118351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski current = calendar.getDisplayName(field, style, locale); 118451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 118551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 118651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Note: zeroPaddingNumber() assumes that maxDigits is either 118751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 2 or maxIntCount. If we make any changes to this, 118851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // zeroPaddingNumber() must be fixed. 118951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 119051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski switch (patternCharIndex) { 119151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_ERA: // 'G' 119251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (useDateFormatSymbols) { 119351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String[] eras = formatData.getEras(); 11946e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin if (value < eras.length) { 119551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski current = eras[value]; 11966e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin } 119751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11986e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin if (current == null) { 119951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski current = ""; 12006e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin } 120151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 120251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 120351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_WEEK_YEAR: // 'Y' 120451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_YEAR: // 'y' 120551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (calendar instanceof GregorianCalendar) { 12066e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin if (count != 2) { 120751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski zeroPaddingNumber(value, count, maxIntCount, buffer); 1208af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin } else { 12096e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin zeroPaddingNumber(value, 2, 2, buffer); 12106e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin } // clip 1996 to 96 121151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 121251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (current == null) { 121351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski zeroPaddingNumber(value, style == Calendar.LONG ? 1 : count, 121451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski maxIntCount, buffer); 121551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 121651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 121751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 121851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12194c8d6d2a84cffba9a34ea03d534d77027fb1974ePaul Duffin case PATTERN_MONTH: // 'M' 12207355fec3783cb45ef6770ce7969c1319347c8b6aJoachim Sauer if (useDateFormatSymbols) { 12217355fec3783cb45ef6770ce7969c1319347c8b6aJoachim Sauer current = formatMonth(count, value, maxIntCount, buffer, useDateFormatSymbols, 12227355fec3783cb45ef6770ce7969c1319347c8b6aJoachim Sauer false /* standalone */); 12237355fec3783cb45ef6770ce7969c1319347c8b6aJoachim Sauer } 1224d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath break; 1225d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 1226af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin case PATTERN_MONTH_STANDALONE: // 'L' 12277355fec3783cb45ef6770ce7969c1319347c8b6aJoachim Sauer if (useDateFormatSymbols) { 12287355fec3783cb45ef6770ce7969c1319347c8b6aJoachim Sauer current = formatMonth(count, value, maxIntCount, buffer, useDateFormatSymbols, 12297355fec3783cb45ef6770ce7969c1319347c8b6aJoachim Sauer true /* standalone */); 12307355fec3783cb45ef6770ce7969c1319347c8b6aJoachim Sauer } 123151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 123251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 123351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_HOUR_OF_DAY1: // 'k' 1-based. eg, 23:59 + 1 hour =>> 24:59 123451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (current == null) { 12356e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin if (value == 0) { 12366e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin zeroPaddingNumber(calendar.getMaximum(Calendar.HOUR_OF_DAY) + 1, 123751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count, maxIntCount, buffer); 12386e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin } else { 123951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski zeroPaddingNumber(value, count, maxIntCount, buffer); 12406e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin } 124151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 124251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 124351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12444c8d6d2a84cffba9a34ea03d534d77027fb1974ePaul Duffin case PATTERN_DAY_OF_WEEK: // 'E' 12457355fec3783cb45ef6770ce7969c1319347c8b6aJoachim Sauer if (current == null) { 1246d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // Android-changed: extract formatWeekday() method. 12477355fec3783cb45ef6770ce7969c1319347c8b6aJoachim Sauer current = formatWeekday(count, value, useDateFormatSymbols, false /* standalone */); 12487355fec3783cb45ef6770ce7969c1319347c8b6aJoachim Sauer } 1249d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath break; 1250d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 1251d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // BEGIN Android-added: support for 'c' (standalone day of week). 12524c8d6d2a84cffba9a34ea03d534d77027fb1974ePaul Duffin case PATTERN_STANDALONE_DAY_OF_WEEK: // 'c' 12537355fec3783cb45ef6770ce7969c1319347c8b6aJoachim Sauer if (current == null) { 1254d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // Android-changed: extract formatWeekday() method. 12557355fec3783cb45ef6770ce7969c1319347c8b6aJoachim Sauer current = formatWeekday(count, value, useDateFormatSymbols, true /* standalone */); 12567355fec3783cb45ef6770ce7969c1319347c8b6aJoachim Sauer } 125751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 1258d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // END Android-added: support for 'c' (standalone day of week). 125951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 126051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_AM_PM: // 'a' 126151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (useDateFormatSymbols) { 126251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String[] ampm = formatData.getAmPmStrings(); 126351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski current = ampm[value]; 126451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 126551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 126651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 126780339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang // Android-added: Ignore 'b' and 'B' introduced in CLDR 32+ pattern data. http://b/68139386 126880339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang // Not currently supported here. 126980339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang case PATTERN_DAY_PERIOD: 127080339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang case PATTERN_FLEXIBLE_DAY_PERIOD: 127180339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang current = ""; 127280339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang break; 127380339f4741bb174f9c6148b843ac0dcfc6422306Victor Chang 127451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_HOUR1: // 'h' 1-based. eg, 11PM + 1 hour =>> 12 AM 127551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (current == null) { 12766e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin if (value == 0) { 12776e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin zeroPaddingNumber(calendar.getLeastMaximum(Calendar.HOUR) + 1, 127851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count, maxIntCount, buffer); 12796e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin } else { 128051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski zeroPaddingNumber(value, count, maxIntCount, buffer); 12816e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin } 128251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 128351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 128451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 128551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_ZONE_NAME: // 'z' 128651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (current == null) { 1287d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // BEGIN Android-changed: format time zone name using ICU. 12889c853c5b9ebbb0ef60a013ae10ee411d70dfa832Piotr Jastrzebski TimeZone tz = calendar.getTimeZone(); 12899c853c5b9ebbb0ef60a013ae10ee411d70dfa832Piotr Jastrzebski boolean daylight = (calendar.get(Calendar.DST_OFFSET) != 0); 1290d8bef3c23bf1851242cc2dc189edaa544eeabe58Joachim Sauer String zoneString; 1291d8bef3c23bf1851242cc2dc189edaa544eeabe58Joachim Sauer if (formatData.isZoneStringsSet) { 12924947038a7acb466855746df19d41ef26be507aa4Joachim Sauer // DateFormatSymbols.setZoneStrings() has be used, use those values instead of 12934947038a7acb466855746df19d41ef26be507aa4Joachim Sauer // ICU code. 12944947038a7acb466855746df19d41ef26be507aa4Joachim Sauer int tzstyle = count < 4 ? TimeZone.SHORT : TimeZone.LONG; 12954947038a7acb466855746df19d41ef26be507aa4Joachim Sauer zoneString = libcore.icu.TimeZoneNames.getDisplayName( 1296d8bef3c23bf1851242cc2dc189edaa544eeabe58Joachim Sauer formatData.getZoneStringsWrapper(), tz.getID(), daylight, tzstyle); 1297d8bef3c23bf1851242cc2dc189edaa544eeabe58Joachim Sauer } else { 1298fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller TimeZoneNames.NameType nameType; 1299fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller if (count < 4) { 1300fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller nameType = daylight 1301fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller ? TimeZoneNames.NameType.SHORT_DAYLIGHT 1302fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller : TimeZoneNames.NameType.SHORT_STANDARD; 13034947038a7acb466855746df19d41ef26be507aa4Joachim Sauer } else { 1304fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller nameType = daylight 1305fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller ? TimeZoneNames.NameType.LONG_DAYLIGHT 1306fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller : TimeZoneNames.NameType.LONG_STANDARD; 13074947038a7acb466855746df19d41ef26be507aa4Joachim Sauer } 1308fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller String canonicalID = android.icu.util.TimeZone.getCanonicalID(tz.getID()); 1309fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller zoneString = getTimeZoneNames() 1310fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller .getDisplayName(canonicalID, nameType, calendar.getTimeInMillis()); 1311d8bef3c23bf1851242cc2dc189edaa544eeabe58Joachim Sauer } 13129c853c5b9ebbb0ef60a013ae10ee411d70dfa832Piotr Jastrzebski if (zoneString != null) { 13139c853c5b9ebbb0ef60a013ae10ee411d70dfa832Piotr Jastrzebski buffer.append(zoneString); 131451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 13159c853c5b9ebbb0ef60a013ae10ee411d70dfa832Piotr Jastrzebski int offsetMillis = calendar.get(Calendar.ZONE_OFFSET) + 13169c853c5b9ebbb0ef60a013ae10ee411d70dfa832Piotr Jastrzebski calendar.get(Calendar.DST_OFFSET); 13179c853c5b9ebbb0ef60a013ae10ee411d70dfa832Piotr Jastrzebski buffer.append(TimeZone.createGmtOffsetString(true, true, offsetMillis)); 131851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 1319d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // END Android-changed: format time zone name using ICU. 132051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 132151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 132251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 132351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_ZONE_VALUE: // 'Z' ("-/+hhmm" form) 1324c99342bb4ce22d842e806d9ebf2f9fcc761c05fbTobias Thierer // BEGIN Android-changed: use shared code in TimeZone for zone offset string. 1325d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath { 1326d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath value = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET); 1327d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath final boolean includeSeparator = (count >= 4); 1328d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath final boolean includeGmt = (count == 4); 1329d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath buffer.append(TimeZone.createGmtOffsetString(includeGmt, includeSeparator, value)); 133051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 133151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 1332d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 1333c99342bb4ce22d842e806d9ebf2f9fcc761c05fbTobias Thierer // END Android-changed: use shared code in TimeZone for zone offset string. 133451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 133551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_ISO_ZONE: // 'X' 133651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value = calendar.get(Calendar.ZONE_OFFSET) 133751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski + calendar.get(Calendar.DST_OFFSET); 133851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 133951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (value == 0) { 134051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append('Z'); 134151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 134251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 134351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 134451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value /= 60000; 134551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (value >= 0) { 134651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append('+'); 134751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 134851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append('-'); 134951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value = -value; 135051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 135151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 135251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CalendarUtils.sprintf0d(buffer, value / 60, 2); 135351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (count == 1) { 135451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 135551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 135651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 135751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (count == 3) { 135851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append(':'); 135951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 136051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CalendarUtils.sprintf0d(buffer, value % 60, 2); 136151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 1362d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // BEGIN Android-added: Better UTS#35 conformity for fractional seconds. 1363afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath case PATTERN_MILLISECOND: // 'S' 1364afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath // Fractional seconds must be treated specially. We must always convert the parsed 1365afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath // value into a fractional second [0, 1) and then widen it out to the appropriate 1366afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath // formatted size. For example, an initial value of 789 will be converted 1367afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath // 0.789 and then become ".7" (S) or ".78" (SS) or "0.789" (SSS) or "0.7890" (SSSS) 1368afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath // in the resulting formatted output. 1369afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath if (current == null) { 1370afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath value = (int) (((double) value / 1000) * Math.pow(10, count)); 1371afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath zeroPaddingNumber(value, count, count, buffer); 1372afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath } 1373afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath break; 1374d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // END Android-added: Better UTS#35 conformity for fractional seconds. 137551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 137651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski default: 137751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_DAY_OF_MONTH: // 'd' 137851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_HOUR_OF_DAY0: // 'H' 0-based. eg, 23:59 + 1 hour =>> 00:59 137951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_MINUTE: // 'm' 138051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_SECOND: // 's' 1381d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // Android-removed: PATTERN_MILLISECONDS handled in an explicit case above. 1382d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer //// case PATTERN_MILLISECOND: // 'S' 138351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_DAY_OF_YEAR: // 'D' 138451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_DAY_OF_WEEK_IN_MONTH: // 'F' 138551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_WEEK_OF_YEAR: // 'w' 138651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_WEEK_OF_MONTH: // 'W' 138751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_HOUR0: // 'K' eg, 11PM + 1 hour =>> 0 AM 138851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_ISO_DAY_OF_WEEK: // 'u' pseudo field, Monday = 1, ..., Sunday = 7 138951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (current == null) { 139051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski zeroPaddingNumber(value, count, maxIntCount, buffer); 139151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 139251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 139351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } // switch (patternCharIndex) 139451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 139551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (current != null) { 139651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append(current); 139751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 139851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 139951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int fieldID = PATTERN_INDEX_TO_DATE_FORMAT_FIELD[patternCharIndex]; 140051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Field f = PATTERN_INDEX_TO_DATE_FORMAT_FIELD_ID[patternCharIndex]; 140151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 140251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski delegate.formatted(fieldID, f, f, beginOffset, buffer.length(), buffer); 140351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 140451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 1405d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // BEGIN Android-added: formatWeekday and formatMonth methods to format using ICU data. 1406d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath private String formatWeekday(int count, int value, boolean useDateFormatSymbols, 1407d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath boolean standalone) { 1408d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if (useDateFormatSymbols) { 1409d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath final String[] weekdays; 1410d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if (count == 4) { 1411d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath weekdays = standalone ? formatData.getStandAloneWeekdays() : formatData.getWeekdays(); 1412d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } else if (count == 5) { 1413d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath weekdays = 1414d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath standalone ? formatData.getTinyStandAloneWeekdays() : formatData.getTinyWeekdays(); 1415d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 1416d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } else { // count < 4, use abbreviated form if exists 1417d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath weekdays = standalone ? formatData.getShortStandAloneWeekdays() : formatData.getShortWeekdays(); 1418d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 1419d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 1420d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath return weekdays[value]; 1421d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 1422d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 1423d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath return null; 1424d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 1425d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 1426d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath private String formatMonth(int count, int value, int maxIntCount, StringBuffer buffer, 1427d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath boolean useDateFormatSymbols, boolean standalone) { 1428d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath String current = null; 1429d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if (useDateFormatSymbols) { 1430d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath final String[] months; 1431d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if (count == 4) { 1432d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath months = standalone ? formatData.getStandAloneMonths() : formatData.getMonths(); 1433d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } else if (count == 5) { 1434d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath months = standalone ? formatData.getTinyStandAloneMonths() : formatData.getTinyMonths(); 1435d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } else if (count == 3) { 1436d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath months = standalone ? formatData.getShortStandAloneMonths() : formatData.getShortMonths(); 1437d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } else { 1438d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath months = null; 1439d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 1440d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 1441d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if (months != null) { 1442d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath current = months[value]; 1443d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 1444d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } else { 1445d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if (count < 3) { 1446d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath current = null; 1447d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 1448d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 1449d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 1450d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if (current == null) { 1451d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath zeroPaddingNumber(value+1, count, maxIntCount, buffer); 1452d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 1453d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 1454d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath return current; 1455d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 1456d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // END Android-added: formatWeekday and formatMonth methods to format using ICU data. 1457d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 145851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 145951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Formats a number with the specified minimum and maximum number of digits. 146051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 14616e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin private void zeroPaddingNumber(int value, int minDigits, int maxDigits, StringBuffer buffer) 146251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 146351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Optimization for 1, 2 and 4 digit numbers. This should 146451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // cover most cases of formatting date/time related items. 146551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Note: This optimization code assumes that maxDigits is 146651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // either 2 or Integer.MAX_VALUE (maxIntCount in format()). 146751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 146851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (zeroDigit == 0) { 146951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski zeroDigit = ((DecimalFormat)numberFormat).getDecimalFormatSymbols().getZeroDigit(); 147051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 147151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (value >= 0) { 147251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (value < 100 && minDigits >= 1 && minDigits <= 2) { 147351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (value < 10) { 147451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (minDigits == 2) { 147551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append(zeroDigit); 147651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 147751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append((char)(zeroDigit + value)); 147851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 147951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append((char)(zeroDigit + value / 10)); 148051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append((char)(zeroDigit + value % 10)); 148151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 148251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 148351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (value >= 1000 && value < 10000) { 148451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (minDigits == 4) { 148551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append((char)(zeroDigit + value / 1000)); 148651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value %= 1000; 148751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append((char)(zeroDigit + value / 100)); 148851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value %= 100; 148951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append((char)(zeroDigit + value / 10)); 149051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.append((char)(zeroDigit + value % 10)); 149151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 149251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 149351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (minDigits == 2 && maxDigits == 2) { 149451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski zeroPaddingNumber(value % 100, 2, 2, buffer); 149551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 149651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 149751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 149851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 149951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (Exception e) { 150051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 150151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 150251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski numberFormat.setMinimumIntegerDigits(minDigits); 150351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski numberFormat.setMaximumIntegerDigits(maxDigits); 150451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski numberFormat.format((long)value, buffer, DontCareFieldPosition.INSTANCE); 150551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 150651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 150751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 150851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 150951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Parses text from a string to produce a <code>Date</code>. 151051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 151151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The method attempts to parse text starting at the index given by 151251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>pos</code>. 151351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If parsing succeeds, then the index of <code>pos</code> is updated 151451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to the index after the last character used (parsing does not necessarily 151551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * use all characters up to the end of the string), and the parsed 151651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * date is returned. The updated <code>pos</code> can be used to 151751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * indicate the starting point for the next call to this method. 151851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If an error occurs, then the index of <code>pos</code> is not 151951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * changed, the error index of <code>pos</code> is set to the index of 152051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the character where the error occurred, and null is returned. 152151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 152251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>This parsing operation uses the {@link DateFormat#calendar 152351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * calendar} to produce a {@code Date}. All of the {@code 152451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * calendar}'s date-time fields are {@linkplain Calendar#clear() 152551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * cleared} before parsing, and the {@code calendar}'s default 152651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * values of the date-time fields are used for any missing 152751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * date-time information. For example, the year value of the 152851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * parsed {@code Date} is 1970 with {@link GregorianCalendar} if 152951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * no year value is given from the parsing operation. The {@code 153051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * TimeZone} value may be overwritten, depending on the given 153151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * pattern and the time zone value in {@code text}. Any {@code 153251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * TimeZone} value that has previously been set by a call to 153351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link #setTimeZone(java.util.TimeZone) setTimeZone} may need 153451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to be restored for further operations. 153551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 153651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param text A <code>String</code>, part of which should be parsed. 153751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param pos A <code>ParsePosition</code> object with index and error 153851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * index information as described above. 153951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return A <code>Date</code> parsed from the string. In case of 154051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * error, returns null. 154151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception NullPointerException if <code>text</code> or <code>pos</code> is null. 154251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 15436e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin @Override 15442015e08d682be61dacd76c51bb0345f357fc4e96Narayan Kamath public Date parse(String text, ParsePosition pos) { 1545d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // BEGIN Android-changed: extract parseInternal() and avoid modifying timezone during parse. 15462015e08d682be61dacd76c51bb0345f357fc4e96Narayan Kamath // Make sure the timezone associated with this dateformat instance (set via 15472015e08d682be61dacd76c51bb0345f357fc4e96Narayan Kamath // {@code setTimeZone} isn't change as a side-effect of parsing a date. 15482015e08d682be61dacd76c51bb0345f357fc4e96Narayan Kamath final TimeZone tz = getTimeZone(); 15492015e08d682be61dacd76c51bb0345f357fc4e96Narayan Kamath try { 15502015e08d682be61dacd76c51bb0345f357fc4e96Narayan Kamath return parseInternal(text, pos); 15512015e08d682be61dacd76c51bb0345f357fc4e96Narayan Kamath } finally { 15522015e08d682be61dacd76c51bb0345f357fc4e96Narayan Kamath setTimeZone(tz); 15532015e08d682be61dacd76c51bb0345f357fc4e96Narayan Kamath } 15542015e08d682be61dacd76c51bb0345f357fc4e96Narayan Kamath } 15552015e08d682be61dacd76c51bb0345f357fc4e96Narayan Kamath 15562015e08d682be61dacd76c51bb0345f357fc4e96Narayan Kamath private Date parseInternal(String text, ParsePosition pos) 155751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 1558d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // END Android-changed: extract parseInternal() and avoid modifying timezone during parse. 155951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski checkNegativeNumberExpression(); 156051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 156151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int start = pos.index; 156251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int oldStart = start; 156351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int textLength = text.length(); 156451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 156551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean[] ambiguousYear = {false}; 156651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 156751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CalendarBuilder calb = new CalendarBuilder(); 156851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 156951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < compiledPattern.length; ) { 157051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int tag = compiledPattern[i] >>> 8; 157151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int count = compiledPattern[i++] & 0xff; 157251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (count == 255) { 157351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count = compiledPattern[i++] << 16; 157451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count |= compiledPattern[i++]; 157551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 157651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 157751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski switch (tag) { 157851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case TAG_QUOTE_ASCII_CHAR: 157951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (start >= textLength || text.charAt(start) != (char)count) { 158051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos.index = oldStart; 158151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos.errorIndex = start; 158251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 158351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 158451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski start++; 158551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 158651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 158751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case TAG_QUOTE_CHARS: 158851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (count-- > 0) { 158951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (start >= textLength || text.charAt(start) != compiledPattern[i++]) { 159051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos.index = oldStart; 159151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos.errorIndex = start; 159251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 159351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 159451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski start++; 159551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 159651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 159751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 159851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski default: 159951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Peek the next pattern to determine if we need to 160051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // obey the number of pattern letters for 160151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // parsing. It's required when parsing contiguous 160251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // digit text (e.g., "20010704") with a pattern which 160351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // has no delimiters between fields, like "yyyyMMdd". 160451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean obeyCount = false; 160551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 160651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // In Arabic, a minus sign for a negative number is put after 160751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // the number. Even in another locale, a minus sign can be 160851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // put after a number using DateFormat.setNumberFormat(). 160951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // If both the minus sign and the field-delimiter are '-', 161051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // subParse() needs to determine whether a '-' after a number 161151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // in the given text is a delimiter or is a minus sign for the 161251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // preceding number. We give subParse() a clue based on the 161351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // information in compiledPattern. 161451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean useFollowingMinusSignAsDelimiter = false; 161551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 161651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (i < compiledPattern.length) { 161751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int nextTag = compiledPattern[i] >>> 8; 161851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!(nextTag == TAG_QUOTE_ASCII_CHAR || 161951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski nextTag == TAG_QUOTE_CHARS)) { 162051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski obeyCount = true; 162151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 162251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 162351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (hasFollowingMinusSign && 162451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (nextTag == TAG_QUOTE_ASCII_CHAR || 162551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski nextTag == TAG_QUOTE_CHARS)) { 162651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int c; 162751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (nextTag == TAG_QUOTE_ASCII_CHAR) { 162851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski c = compiledPattern[i] & 0xff; 162951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 163051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski c = compiledPattern[i+1]; 163151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 163251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 163351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c == minusSign) { 163451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski useFollowingMinusSignAsDelimiter = true; 163551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 163651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 163751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 163851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski start = subParse(text, start, tag, count, obeyCount, 163951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ambiguousYear, pos, 164051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski useFollowingMinusSignAsDelimiter, calb); 164151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (start < 0) { 164251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos.index = oldStart; 164351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 164451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 164551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 164651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 164751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 164851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // At this point the fields of Calendar have been set. Calendar 164951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // will fill in default values for missing fields when the time 165051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // is computed. 165151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 165251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos.index = start; 165351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 165451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Date parsedDate; 165551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 165651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski parsedDate = calb.establish(calendar).getTime(); 165751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // If the year value is ambiguous, 165851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // then the two-digit year == the default start year 165951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (ambiguousYear[0]) { 166051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (parsedDate.before(defaultCenturyStart)) { 166151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski parsedDate = calb.addYear(100).establish(calendar).getTime(); 166251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 166351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 166451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 166551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // An IllegalArgumentException will be thrown by Calendar.getTime() 166651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // if any fields are out of range, e.g., MONTH == 17. 166751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski catch (IllegalArgumentException e) { 166851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos.errorIndex = start; 166951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos.index = oldStart; 167051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 167151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 167251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 167351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return parsedDate; 167451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 167551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 167651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 167751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Private code-size reduction function used by subParse. 167851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param text the time text being parsed. 167951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param start where to start parsing. 168051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param field the date field being parsed. 168151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param data the string array to parsed. 168251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the new start position if matching succeeded; a negative number 168351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * indicating matching failure, otherwise. 168451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 168551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int matchString(String text, int start, int field, String[] data, CalendarBuilder calb) 168651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 168751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int i = 0; 168851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int count = data.length; 168951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16906e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin if (field == Calendar.DAY_OF_WEEK) { 16916e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin i = 1; 16926e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin } 169351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 169451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // There may be multiple strings in the data[] array which begin with 169551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // the same prefix (e.g., Cerven and Cervenec (June and July) in Czech). 169651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // We keep track of the longest match, and return that. Note that this 169751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // unfortunately requires us to test all array elements. 169851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int bestMatchLength = 0, bestMatch = -1; 169951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (; i<count; ++i) 170051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 170151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int length = data[i].length(); 170251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Always compare if we have no match yet; otherwise only compare 170351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // against potentially better matches (longer strings). 170451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (length > bestMatchLength && 170551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski text.regionMatches(true, start, data[i], 0, length)) 170651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 170751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bestMatch = i; 170851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bestMatchLength = length; 170951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 171000617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath 1711d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // BEGIN Android-changed: Handle abbreviated fields that end with a '.'. 171200617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath // When the input option ends with a period (usually an abbreviated form), attempt 171300617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath // to match all chars up to that period. 171400617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath if ((data[i].charAt(length - 1) == '.') && 171500617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath ((length - 1) > bestMatchLength) && 171600617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath text.regionMatches(true, start, data[i], 0, length - 1)) { 171700617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath bestMatch = i; 171800617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath bestMatchLength = (length - 1); 171900617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath } 1720d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // END Android-changed: Handle abbreviated fields that end with a '.'. 172151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 172251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (bestMatch >= 0) 172351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 172451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski calb.set(field, bestMatch); 172551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return start + bestMatchLength; 172651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 172751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return -start; 172851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 172951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 173051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 173151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Performs the same thing as matchString(String, int, int, 173251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * String[]). This method takes a Map<String, Integer> instead of 173351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * String[]. 173451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 173551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int matchString(String text, int start, int field, 173651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Map<String,Integer> data, CalendarBuilder calb) { 173751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (data != null) { 173851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String bestMatch = null; 173951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 174051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (String name : data.keySet()) { 174151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int length = name.length(); 174251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (bestMatch == null || length > bestMatch.length()) { 174351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (text.regionMatches(true, start, name, 0, length)) { 174451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bestMatch = name; 174551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 174651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 174751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 174851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 174951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (bestMatch != null) { 175051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski calb.set(field, data.get(bestMatch)); 175151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return start + bestMatch.length(); 175251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 175351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 175451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return -start; 175551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 175651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 175751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int matchZoneString(String text, int start, String[] zoneNames) { 175851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 1; i <= 4; ++i) { 175951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Checking long and short zones [1 & 2], 176051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // and long and short daylight [3 & 4]. 176151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String zoneName = zoneNames[i]; 176251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (text.regionMatches(true, start, 176351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski zoneName, 0, zoneName.length())) { 176451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return i; 176551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 176651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 176751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return -1; 176851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 176951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 1770d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // Android-removed: unused private method matchDSTString. 1771d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer 1772d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // BEGIN Android-changed: Parse time zone strings using ICU TimeZoneNames. 1773d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // Note that this change falls back to the upstream zone names parsing code if the zoneStrings 1774d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // for the formatData field has been set by the user. The original code of subParseZoneString 1775d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // can be found in subParseZoneStringFromSymbols(). 17764947038a7acb466855746df19d41ef26be507aa4Joachim Sauer /** 17774947038a7acb466855746df19d41ef26be507aa4Joachim Sauer * Parses the string in {@code text} (starting at {@code start}), interpreting it as a time zone 17784947038a7acb466855746df19d41ef26be507aa4Joachim Sauer * name. If a time zone is found, the internal calendar is set to that timezone and the index of 17794947038a7acb466855746df19d41ef26be507aa4Joachim Sauer * the first character after the time zone name is returned. Otherwise, returns {@code 0}. 17804947038a7acb466855746df19d41ef26be507aa4Joachim Sauer * @return the index of the next character to parse or {@code 0} on error. 17814947038a7acb466855746df19d41ef26be507aa4Joachim Sauer */ 17824947038a7acb466855746df19d41ef26be507aa4Joachim Sauer private int subParseZoneString(String text, int start, CalendarBuilder calb) { 17834947038a7acb466855746df19d41ef26be507aa4Joachim Sauer if (formatData.isZoneStringsSet) { 17844947038a7acb466855746df19d41ef26be507aa4Joachim Sauer // DateFormatSymbols.setZoneStrings() has be used, use those values instead of ICU code. 17854947038a7acb466855746df19d41ef26be507aa4Joachim Sauer return subParseZoneStringFromSymbols(text, start, calb); 17864947038a7acb466855746df19d41ef26be507aa4Joachim Sauer } else { 17874947038a7acb466855746df19d41ef26be507aa4Joachim Sauer return subParseZoneStringFromICU(text, start, calb); 17884947038a7acb466855746df19d41ef26be507aa4Joachim Sauer } 17894947038a7acb466855746df19d41ef26be507aa4Joachim Sauer } 17904947038a7acb466855746df19d41ef26be507aa4Joachim Sauer 17914947038a7acb466855746df19d41ef26be507aa4Joachim Sauer private TimeZoneNames getTimeZoneNames() { 17924947038a7acb466855746df19d41ef26be507aa4Joachim Sauer if (timeZoneNames == null) { 17934947038a7acb466855746df19d41ef26be507aa4Joachim Sauer timeZoneNames = TimeZoneNames.getInstance(locale); 179451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17954947038a7acb466855746df19d41ef26be507aa4Joachim Sauer return timeZoneNames; 179651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 179751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 179851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 17994947038a7acb466855746df19d41ef26be507aa4Joachim Sauer * The set of name types accepted when parsing time zone names. 180051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 18014947038a7acb466855746df19d41ef26be507aa4Joachim Sauer private static final EnumSet<TimeZoneNames.NameType> NAME_TYPES = 18024947038a7acb466855746df19d41ef26be507aa4Joachim Sauer EnumSet.of(TimeZoneNames.NameType.LONG_GENERIC, TimeZoneNames.NameType.LONG_STANDARD, 18034947038a7acb466855746df19d41ef26be507aa4Joachim Sauer TimeZoneNames.NameType.LONG_DAYLIGHT, TimeZoneNames.NameType.SHORT_GENERIC, 18044947038a7acb466855746df19d41ef26be507aa4Joachim Sauer TimeZoneNames.NameType.SHORT_STANDARD, TimeZoneNames.NameType.SHORT_DAYLIGHT); 18054947038a7acb466855746df19d41ef26be507aa4Joachim Sauer 18064947038a7acb466855746df19d41ef26be507aa4Joachim Sauer /** 18074947038a7acb466855746df19d41ef26be507aa4Joachim Sauer * Time zone name types that indicate daylight saving time. 18084947038a7acb466855746df19d41ef26be507aa4Joachim Sauer */ 18094947038a7acb466855746df19d41ef26be507aa4Joachim Sauer private static final Set<TimeZoneNames.NameType> DST_NAME_TYPES = 18104947038a7acb466855746df19d41ef26be507aa4Joachim Sauer Collections.unmodifiableSet(EnumSet.of( 18114947038a7acb466855746df19d41ef26be507aa4Joachim Sauer TimeZoneNames.NameType.LONG_DAYLIGHT, TimeZoneNames.NameType.SHORT_DAYLIGHT)); 18124947038a7acb466855746df19d41ef26be507aa4Joachim Sauer 18134947038a7acb466855746df19d41ef26be507aa4Joachim Sauer /** 18144947038a7acb466855746df19d41ef26be507aa4Joachim Sauer * Parses the time zone string using the ICU4J class {@link TimeZoneNames}. 18154947038a7acb466855746df19d41ef26be507aa4Joachim Sauer */ 18164947038a7acb466855746df19d41ef26be507aa4Joachim Sauer private int subParseZoneStringFromICU(String text, int start, CalendarBuilder calb) { 18174947038a7acb466855746df19d41ef26be507aa4Joachim Sauer String currentTimeZoneID = android.icu.util.TimeZone.getCanonicalID(getTimeZone().getID()); 18184947038a7acb466855746df19d41ef26be507aa4Joachim Sauer 18194947038a7acb466855746df19d41ef26be507aa4Joachim Sauer TimeZoneNames tzNames = getTimeZoneNames(); 18204947038a7acb466855746df19d41ef26be507aa4Joachim Sauer TimeZoneNames.MatchInfo bestMatch = null; 18214947038a7acb466855746df19d41ef26be507aa4Joachim Sauer // The MetaZones associated with the current time zone are needed in two places, both of 18224947038a7acb466855746df19d41ef26be507aa4Joachim Sauer // which are avoided in some cases, so they are computed lazily. 18234947038a7acb466855746df19d41ef26be507aa4Joachim Sauer Set<String> currentTzMetaZoneIds = null; 18244947038a7acb466855746df19d41ef26be507aa4Joachim Sauer 1825fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller Collection<TimeZoneNames.MatchInfo> matches = tzNames.find(text, start, NAME_TYPES); 1826fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller for (TimeZoneNames.MatchInfo match : matches) { 1827fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller if (bestMatch == null || bestMatch.matchLength() < match.matchLength()) { 1828fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller bestMatch = match; 1829fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller } else if (bestMatch.matchLength() == match.matchLength()) { 1830fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller if (currentTimeZoneID.equals(match.tzID())) { 1831fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller // Prefer the currently set timezone over other matches, even if they are 1832fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller // the same length. 18334947038a7acb466855746df19d41ef26be507aa4Joachim Sauer bestMatch = match; 1834fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller break; 1835fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller } else if (match.mzID() != null) { 1836fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller if (currentTzMetaZoneIds == null) { 1837fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller currentTzMetaZoneIds = 1838fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller tzNames.getAvailableMetaZoneIDs(currentTimeZoneID); 1839fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller } 1840fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller if (currentTzMetaZoneIds.contains(match.mzID())) { 18414947038a7acb466855746df19d41ef26be507aa4Joachim Sauer bestMatch = match; 18424947038a7acb466855746df19d41ef26be507aa4Joachim Sauer break; 18434947038a7acb466855746df19d41ef26be507aa4Joachim Sauer } 18444947038a7acb466855746df19d41ef26be507aa4Joachim Sauer } 18454947038a7acb466855746df19d41ef26be507aa4Joachim Sauer } 1846fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller } 1847fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller if (bestMatch == null) { 1848fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller // No match found, return error. 1849fb1a78d35d56cc48cc5ec5503d2bfff3406b923fNeil Fuller return -start; 18504947038a7acb466855746df19d41ef26be507aa4Joachim Sauer } 18514947038a7acb466855746df19d41ef26be507aa4Joachim Sauer 18524947038a7acb466855746df19d41ef26be507aa4Joachim Sauer String tzId = bestMatch.tzID(); 18534947038a7acb466855746df19d41ef26be507aa4Joachim Sauer if (tzId == null) { 18544947038a7acb466855746df19d41ef26be507aa4Joachim Sauer if (currentTzMetaZoneIds == null) { 18554947038a7acb466855746df19d41ef26be507aa4Joachim Sauer currentTzMetaZoneIds = tzNames.getAvailableMetaZoneIDs(currentTimeZoneID); 18564947038a7acb466855746df19d41ef26be507aa4Joachim Sauer } 18574947038a7acb466855746df19d41ef26be507aa4Joachim Sauer if (currentTzMetaZoneIds.contains(bestMatch.mzID())) { 18584947038a7acb466855746df19d41ef26be507aa4Joachim Sauer tzId = currentTimeZoneID; 18594947038a7acb466855746df19d41ef26be507aa4Joachim Sauer } else { 18604947038a7acb466855746df19d41ef26be507aa4Joachim Sauer // Match was for a meta-zone, find the matching reference zone. 18614947038a7acb466855746df19d41ef26be507aa4Joachim Sauer ULocale uLocale = ULocale.forLocale(locale); 18624947038a7acb466855746df19d41ef26be507aa4Joachim Sauer String region = uLocale.getCountry(); 18634947038a7acb466855746df19d41ef26be507aa4Joachim Sauer if (region.length() == 0) { 18644947038a7acb466855746df19d41ef26be507aa4Joachim Sauer uLocale = ULocale.addLikelySubtags(uLocale); 18654947038a7acb466855746df19d41ef26be507aa4Joachim Sauer region = uLocale.getCountry(); 18664947038a7acb466855746df19d41ef26be507aa4Joachim Sauer } 18674947038a7acb466855746df19d41ef26be507aa4Joachim Sauer tzId = tzNames.getReferenceZoneID(bestMatch.mzID(), region); 18684947038a7acb466855746df19d41ef26be507aa4Joachim Sauer } 18694947038a7acb466855746df19d41ef26be507aa4Joachim Sauer } 18704947038a7acb466855746df19d41ef26be507aa4Joachim Sauer 18714947038a7acb466855746df19d41ef26be507aa4Joachim Sauer TimeZone newTimeZone = TimeZone.getTimeZone(tzId); 18724947038a7acb466855746df19d41ef26be507aa4Joachim Sauer if (!currentTimeZoneID.equals(tzId)) { 18734947038a7acb466855746df19d41ef26be507aa4Joachim Sauer setTimeZone(newTimeZone); 18744947038a7acb466855746df19d41ef26be507aa4Joachim Sauer } 18754947038a7acb466855746df19d41ef26be507aa4Joachim Sauer 18764947038a7acb466855746df19d41ef26be507aa4Joachim Sauer // Same logic as in subParseZoneStringFromSymbols, see below for details. 18774947038a7acb466855746df19d41ef26be507aa4Joachim Sauer boolean isDst = DST_NAME_TYPES.contains(bestMatch.nameType()); 18784947038a7acb466855746df19d41ef26be507aa4Joachim Sauer int dstAmount = isDst ? newTimeZone.getDSTSavings() : 0; 18794947038a7acb466855746df19d41ef26be507aa4Joachim Sauer if (!isDst || dstAmount != 0) { 18804947038a7acb466855746df19d41ef26be507aa4Joachim Sauer calb.clear(Calendar.ZONE_OFFSET).set(Calendar.DST_OFFSET, dstAmount); 18814947038a7acb466855746df19d41ef26be507aa4Joachim Sauer } 18824947038a7acb466855746df19d41ef26be507aa4Joachim Sauer 18834947038a7acb466855746df19d41ef26be507aa4Joachim Sauer return bestMatch.matchLength() + start; 18844947038a7acb466855746df19d41ef26be507aa4Joachim Sauer } 18854947038a7acb466855746df19d41ef26be507aa4Joachim Sauer 18864947038a7acb466855746df19d41ef26be507aa4Joachim Sauer /** 18874947038a7acb466855746df19d41ef26be507aa4Joachim Sauer * Parses the time zone string using the information in {@link #formatData}. 18884947038a7acb466855746df19d41ef26be507aa4Joachim Sauer */ 18894947038a7acb466855746df19d41ef26be507aa4Joachim Sauer private int subParseZoneStringFromSymbols(String text, int start, CalendarBuilder calb) { 1890d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // END Android-changed: Parse time zone strings using ICU TimeZoneNames. 189151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean useSameName = false; // true if standard and daylight time use the same abbreviation. 189251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski TimeZone currentTimeZone = getTimeZone(); 189351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 189451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // At this point, check for named time zones by looking through 189551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // the locale data from the TimeZoneNames strings. 189651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Want to be able to parse both short and long forms. 189751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int zoneIndex = formatData.getZoneIndex(currentTimeZone.getID()); 189851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski TimeZone tz = null; 189951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String[][] zoneStrings = formatData.getZoneStringsWrapper(); 190051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String[] zoneNames = null; 190151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int nameIndex = 0; 190251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (zoneIndex != -1) { 190351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski zoneNames = zoneStrings[zoneIndex]; 190451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((nameIndex = matchZoneString(text, start, zoneNames)) > 0) { 190551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (nameIndex <= 2) { 190651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Check if the standard name (abbr) and the daylight name are the same. 190751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski useSameName = zoneNames[nameIndex].equalsIgnoreCase(zoneNames[nameIndex + 2]); 190851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 190951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tz = TimeZone.getTimeZone(zoneNames[0]); 191051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 191151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 191251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tz == null) { 191351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski zoneIndex = formatData.getZoneIndex(TimeZone.getDefault().getID()); 191451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (zoneIndex != -1) { 191551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski zoneNames = zoneStrings[zoneIndex]; 191651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((nameIndex = matchZoneString(text, start, zoneNames)) > 0) { 191751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (nameIndex <= 2) { 191851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski useSameName = zoneNames[nameIndex].equalsIgnoreCase(zoneNames[nameIndex + 2]); 191951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 192051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tz = TimeZone.getTimeZone(zoneNames[0]); 192151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 192251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 192351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 192451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 192551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tz == null) { 192651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int len = zoneStrings.length; 192751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < len; i++) { 192851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski zoneNames = zoneStrings[i]; 192951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((nameIndex = matchZoneString(text, start, zoneNames)) > 0) { 193051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (nameIndex <= 2) { 193151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski useSameName = zoneNames[nameIndex].equalsIgnoreCase(zoneNames[nameIndex + 2]); 193251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 193351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tz = TimeZone.getTimeZone(zoneNames[0]); 193451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 193551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 193651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 193751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 193851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tz != null) { // Matched any ? 193951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!tz.equals(currentTimeZone)) { 194051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski setTimeZone(tz); 194151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 194251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // If the time zone matched uses the same name 194351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // (abbreviation) for both standard and daylight time, 194451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // let the time zone in the Calendar decide which one. 194551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 194651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Also if tz.getDSTSaving() returns 0 for DST, use tz to 194751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // determine the local time. (6645292) 194851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int dstAmount = (nameIndex >= 3) ? tz.getDSTSavings() : 0; 194951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!(useSameName || (nameIndex >= 3 && dstAmount == 0))) { 195051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski calb.clear(Calendar.ZONE_OFFSET).set(Calendar.DST_OFFSET, dstAmount); 195151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 195251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (start + zoneNames[nameIndex].length()); 195351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 1954242478c8a84d2fc9fd2e47f2b143622f1c9405dbJoachim Sauer return -start; 195551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 195651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 195751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 195851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Parses numeric forms of time zone offset, such as "hh:mm", and 195951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * sets calb to the parsed value. 196051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 196151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param text the text to be parsed 196251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param start the character position to start parsing 196351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param sign 1: positive; -1: negative 196451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param count 0: 'Z' or "GMT+hh:mm" parsing; 1 - 3: the number of 'X's 1965d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath * @param colonRequired true - colon required between hh and mm; false - no colon required 196651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param calb a CalendarBuilder in which the parsed value is stored 196751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return updated parsed position, or its negative value to indicate a parsing error 196851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 196951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int subParseNumericZone(String text, int start, int sign, int count, 1970d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath boolean colonRequired, CalendarBuilder calb) { 197151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int index = start; 197251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 197351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski parse: 197451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 197551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = text.charAt(index++); 197651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Parse hh 197751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int hours; 197851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!isDigit(c)) { 197951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parse; 198051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 198151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hours = c - '0'; 198251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski c = text.charAt(index++); 198351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isDigit(c)) { 198451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hours = hours * 10 + (c - '0'); 198551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 198651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski --index; 198751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 198851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (hours > 23) { 198951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parse; 199051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 199151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int minutes = 0; 199251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (count != 1) { 199351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Proceed with parsing mm 199451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski c = text.charAt(index++); 1995d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // BEGIN Android-changed: Intentional change in behavior from OpenJDK. 1996d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // OpenJDK will return an error code if a : is found and colonRequired is false, 1997d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // this will return an error code if a : is not found and colonRequired is true. 1998af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin // 1999af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin // colonRequired | c == ':' | OpenJDK | this 2000af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin // false | false | ok | ok 2001af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin // false | true | error | ok 2002af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin // true | false | ok | error 2003af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin // true | true | ok | ok 2004d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath if (c == ':') { 200551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski c = text.charAt(index++); 2006d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath } else if (colonRequired) { 2007d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath break parse; 200851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 2009d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // END Android-changed: Intentional change in behavior from OpenJDK. 201051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!isDigit(c)) { 201151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parse; 201251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 201351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski minutes = c - '0'; 201451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski c = text.charAt(index++); 201551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!isDigit(c)) { 201651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parse; 201751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 201851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski minutes = minutes * 10 + (c - '0'); 201951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (minutes > 59) { 202051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parse; 202151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 202251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 202351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski minutes += hours * 60; 202451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski calb.set(Calendar.ZONE_OFFSET, minutes * MILLIS_PER_MINUTE * sign) 202551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski .set(Calendar.DST_OFFSET, 0); 202651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return index; 202751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (IndexOutOfBoundsException e) { 202851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 202951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return 1 - index; // -(index - 1) 203051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 203151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 203251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private boolean isDigit(char c) { 203351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return c >= '0' && c <= '9'; 203451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 203551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 203651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 203751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Private member function that converts the parsed date strings into 203851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * timeFields. Returns -start (for ParsePosition) if failed. 203951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param text the time text to be parsed. 204051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param start where to start parsing. 20416e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin * @param patternCharIndex the index of the pattern character. 204251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param count the count of a pattern character. 204351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param obeyCount if true, then the next field directly abuts this one, 204451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and we should use the count to know when to stop parsing. 204551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param ambiguousYear return parameter; upon return, if ambiguousYear[0] 204651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is true, then a two-digit year was parsed and may need to be readjusted. 204751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param origPos origPos.errorIndex is used to return an error index 204851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * at which a parse error occurred, if matching failure occurs. 204951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the new start position if matching succeeded; -1 indicating 205051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * matching failure, otherwise. In case matching failure occurred, 205151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * an error index is set to origPos.errorIndex. 205251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 205351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int subParse(String text, int start, int patternCharIndex, int count, 205451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean obeyCount, boolean[] ambiguousYear, 205551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ParsePosition origPos, 205651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean useFollowingMinusSignAsDelimiter, CalendarBuilder calb) { 20576e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin Number number; 205851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int value = 0; 205951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ParsePosition pos = new ParsePosition(0); 206051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos.index = start; 206151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (patternCharIndex == PATTERN_WEEK_YEAR && !calendar.isWeekDateSupported()) { 206251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // use calendar year 'y' instead 206351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski patternCharIndex = PATTERN_YEAR; 206451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 206551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex]; 206651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 206751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // If there are any spaces here, skip over them. If we hit the end 206851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // of the string, then fail. 206951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (;;) { 207051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pos.index >= text.length()) { 207151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski origPos.errorIndex = start; 207251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return -1; 207351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 207451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = text.charAt(pos.index); 20756e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin if (c != ' ' && c != '\t') { 20766e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin break; 20776e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin } 207851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ++pos.index; 207951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 208051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 208151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski parsing: 208251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 208351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // We handle a few special cases here where we need to parse 208451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // a number value. We handle further, more generic cases below. We need 208551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // to handle some of them here because some fields require extra processing on 208651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // the parsed value. 208751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (patternCharIndex == PATTERN_HOUR_OF_DAY1 || 208851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski patternCharIndex == PATTERN_HOUR1 || 208951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (patternCharIndex == PATTERN_MONTH && count <= 2) || 209051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski patternCharIndex == PATTERN_YEAR || 209151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski patternCharIndex == PATTERN_WEEK_YEAR) { 209251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // It would be good to unify this with the obeyCount logic below, 209351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // but that's going to be difficult. 209451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (obeyCount) { 209551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((start+count) > text.length()) { 209651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parsing; 209751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 209851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski number = numberFormat.parse(text.substring(0, start+count), pos); 209951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 210051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski number = numberFormat.parse(text, pos); 210151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 210251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (number == null) { 210351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (patternCharIndex != PATTERN_YEAR || calendar instanceof GregorianCalendar) { 210451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parsing; 210551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 210651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 210751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value = number.intValue(); 210851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 210951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (useFollowingMinusSignAsDelimiter && (value < 0) && 211051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (((pos.index < text.length()) && 211151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (text.charAt(pos.index) != minusSign)) || 211251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ((pos.index == text.length()) && 211351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (text.charAt(pos.index-1) == minusSign)))) { 211451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value = -value; 211551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos.index--; 211651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 211751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 211851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 211951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 212051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean useDateFormatSymbols = useDateFormatSymbols(); 212151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 212251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int index; 212351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski switch (patternCharIndex) { 212451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_ERA: // 'G' 212551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (useDateFormatSymbols) { 212651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((index = matchString(text, start, Calendar.ERA, formatData.getEras(), calb)) > 0) { 212751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return index; 212851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 212951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 213051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Map<String, Integer> map = calendar.getDisplayNames(field, 213151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Calendar.ALL_STYLES, 213251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski locale); 213351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((index = matchString(text, start, field, map, calb)) > 0) { 213451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return index; 213551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 213651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 213751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parsing; 213851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 213951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_WEEK_YEAR: // 'Y' 214051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_YEAR: // 'y' 214151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!(calendar instanceof GregorianCalendar)) { 214251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // calendar might have text representations for year values, 214351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // such as "\u5143" in JapaneseImperialCalendar. 214451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int style = (count >= 4) ? Calendar.LONG : Calendar.SHORT; 214551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Map<String, Integer> map = calendar.getDisplayNames(field, style, locale); 214651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (map != null) { 214751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((index = matchString(text, start, field, map, calb)) > 0) { 214851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return index; 214951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 215051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 215151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski calb.set(field, value); 215251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return pos.index; 215351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 215451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 215551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // If there are 3 or more YEAR pattern characters, this indicates 215651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // that the year value is to be treated literally, without any 215751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // two-digit year adjustments (e.g., from "01" to 2001). Otherwise 215851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // we made adjustments to place the 2-digit year in the proper 215951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // century, for parsed strings from "00" to "99". Any other string 216051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // is treated literally: "2250", "-1", "1", "002". 216151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (count <= 2 && (pos.index - start) == 2 216251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && Character.isDigit(text.charAt(start)) 216351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && Character.isDigit(text.charAt(start+1))) { 216451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Assume for example that the defaultCenturyStart is 6/18/1903. 216551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // This means that two-digit years will be forced into the range 216651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 6/18/1903 to 6/17/2003. As a result, years 00, 01, and 02 216751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // correspond to 2000, 2001, and 2002. Years 04, 05, etc. correspond 216851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // to 1904, 1905, etc. If the year is 03, then it is 2003 if the 216951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // other fields specify a date before 6/18, or 1903 if they specify a 217051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // date afterwards. As a result, 03 is an ambiguous year. All other 217151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // two-digit years are unambiguous. 217251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int ambiguousTwoDigitYear = defaultCenturyStartYear % 100; 217351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ambiguousYear[0] = value == ambiguousTwoDigitYear; 217451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value += (defaultCenturyStartYear/100)*100 + 217551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (value < ambiguousTwoDigitYear ? 100 : 0); 217651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 217751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski calb.set(field, value); 217851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return pos.index; 217951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21804c8d6d2a84cffba9a34ea03d534d77027fb1974ePaul Duffin case PATTERN_MONTH: // 'M' 2181d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // BEGIN Android-changed: extract parseMonth method. 2182d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath { 2183d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath final int idx = parseMonth(text, count, value, start, field, pos, 21844c8d6d2a84cffba9a34ea03d534d77027fb1974ePaul Duffin useDateFormatSymbols, false /* isStandalone */, calb); 2185d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if (idx > 0) { 2186d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath return idx; 218751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21884c8d6d2a84cffba9a34ea03d534d77027fb1974ePaul Duffin 2189d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath break parsing; 2190d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 219151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2192af18bc9973eca35fc0d4db6e240323f38c9d7a91Paul Duffin case PATTERN_MONTH_STANDALONE: // 'L'. 2193d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath { 2194d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath final int idx = parseMonth(text, count, value, start, field, pos, 21954c8d6d2a84cffba9a34ea03d534d77027fb1974ePaul Duffin useDateFormatSymbols, true /* isStandalone */, calb); 2196d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if (idx > 0) { 2197d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath return idx; 219851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 219951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parsing; 2200d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 2201d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // END Android-changed: extract parseMonth method. 220251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 220351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_HOUR_OF_DAY1: // 'k' 1-based. eg, 23:59 + 1 hour =>> 24:59 220451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!isLenient()) { 220551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Validate the hour value in non-lenient 220651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (value < 1 || value > 24) { 220751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parsing; 220851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 220951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 221051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // [We computed 'value' above.] 22116e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin if (value == calendar.getMaximum(Calendar.HOUR_OF_DAY) + 1) { 221251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value = 0; 22136e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin } 221451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski calb.set(Calendar.HOUR_OF_DAY, value); 221551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return pos.index; 221651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22174c8d6d2a84cffba9a34ea03d534d77027fb1974ePaul Duffin case PATTERN_DAY_OF_WEEK: // 'E' 2218d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // BEGIN Android-changed: extract parseWeekday method. 2219d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath { 2220d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath final int idx = parseWeekday(text, start, field, useDateFormatSymbols, 2221d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath false /* standalone */, calb); 2222d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if (idx > 0) { 2223d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath return idx; 2224d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 2225d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath break parsing; 2226d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 2227d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // END Android-changed: extract parseWeekday method. 2228d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 2229d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // BEGIN Android-added: support for 'c' (standalone day of week). 22304c8d6d2a84cffba9a34ea03d534d77027fb1974ePaul Duffin case PATTERN_STANDALONE_DAY_OF_WEEK: // 'c' 2231d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath { 2232d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath final int idx = parseWeekday(text, start, field, useDateFormatSymbols, 223391116215bcb3e903fc334eaf23898b0d8ece6924Joachim Sauer true /* standalone */, calb); 2234d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if (idx > 0) { 2235d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath return idx; 223651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 2237d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 223851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parsing; 2239d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 2240d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // END Android-added: support for 'c' (standalone day of week). 2241d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 224251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_AM_PM: // 'a' 224351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (useDateFormatSymbols) { 224451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((index = matchString(text, start, Calendar.AM_PM, 224551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski formatData.getAmPmStrings(), calb)) > 0) { 224651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return index; 224751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 224851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 224951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Map<String,Integer> map = calendar.getDisplayNames(field, Calendar.ALL_STYLES, locale); 225051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((index = matchString(text, start, field, map, calb)) > 0) { 225151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return index; 225251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 225351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 225451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parsing; 225551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 225651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_HOUR1: // 'h' 1-based. eg, 11PM + 1 hour =>> 12 AM 225751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!isLenient()) { 225851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Validate the hour value in non-lenient 225951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (value < 1 || value > 12) { 226051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parsing; 226151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 226251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 226351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // [We computed 'value' above.] 22646e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin if (value == calendar.getLeastMaximum(Calendar.HOUR) + 1) { 226551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value = 0; 22666e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin } 226751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski calb.set(Calendar.HOUR, value); 226851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return pos.index; 226951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 227051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_ZONE_NAME: // 'z' 227151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_ZONE_VALUE: // 'Z' 227251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 227351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int sign = 0; 227451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 227551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = text.charAt(pos.index); 227651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c == '+') { 227751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sign = 1; 227851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (c == '-') { 227951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sign = -1; 228051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 228151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (sign == 0) { 228251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Try parsing a custom time zone "GMT+hh:mm" or "GMT". 228351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((c == 'G' || c == 'g') 228451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && (text.length() - start) >= GMT.length() 228551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && text.regionMatches(true, start, GMT, 0, GMT.length())) { 228651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos.index = start + GMT.length(); 228751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 228851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((text.length() - pos.index) > 0) { 228951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski c = text.charAt(pos.index); 229051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c == '+') { 229151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sign = 1; 229251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (c == '-') { 229351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sign = -1; 229451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 229551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 229651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 229751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (sign == 0) { /* "GMT" without offset */ 229851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski calb.set(Calendar.ZONE_OFFSET, 0) 229951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski .set(Calendar.DST_OFFSET, 0); 230051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return pos.index; 230151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 2302d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // Android-changed: tolerate colon in zone offset. 2303d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath // Parse the rest as "hh[:]?mm" 2304d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath int i = subParseNumericZone(text, ++pos.index, sign, 0, 2305d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath false, calb); 230651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (i > 0) { 230751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return i; 230851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 230951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos.index = -i; 231051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 231151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Try parsing the text as a time zone 231251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // name or abbreviation. 231351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int i = subParseZoneString(text, pos.index, calb); 231451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (i > 0) { 231551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return i; 231651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 231751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos.index = -i; 231851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 231951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 2320d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // Android-changed: tolerate colon in zone offset. 2321d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath // Parse the rest as "hh[:]?mm" (RFC 822) 2322d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath int i = subParseNumericZone(text, ++pos.index, sign, 0, 2323d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath false, calb); 232451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (i > 0) { 232551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return i; 232651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 232751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos.index = -i; 232851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 232951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (IndexOutOfBoundsException e) { 233051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 233151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 233251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parsing; 233351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 233451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case PATTERN_ISO_ZONE: // 'X' 233551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 233651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((text.length() - pos.index) <= 0) { 233751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parsing; 233851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 233951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23406e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin int sign; 234151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = text.charAt(pos.index); 234251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c == 'Z') { 234351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski calb.set(Calendar.ZONE_OFFSET, 0).set(Calendar.DST_OFFSET, 0); 234451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return ++pos.index; 234551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 234651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 234751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // parse text as "+/-hh[[:]mm]" based on count 234851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c == '+') { 234951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sign = 1; 235051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (c == '-') { 235151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sign = -1; 235251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 235351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ++pos.index; 235451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parsing; 235551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23566e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin int i = subParseNumericZone(text, ++pos.index, sign, count, 23576e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin count == 3, calb); 235851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (i > 0) { 235951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return i; 236051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 236151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos.index = -i; 236251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 236351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parsing; 236451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 236551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski default: 236651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_DAY_OF_MONTH: // 'd' 236751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_HOUR_OF_DAY0: // 'H' 0-based. eg, 23:59 + 1 hour =>> 00:59 236851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_MINUTE: // 'm' 236951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_SECOND: // 's' 237051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_MILLISECOND: // 'S' 237151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_DAY_OF_YEAR: // 'D' 237251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_DAY_OF_WEEK_IN_MONTH: // 'F' 237351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_WEEK_OF_YEAR: // 'w' 237451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_WEEK_OF_MONTH: // 'W' 237551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_HOUR0: // 'K' 0-based. eg, 11PM + 1 hour =>> 0 AM 237651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // case PATTERN_ISO_DAY_OF_WEEK: // 'u' (pseudo field); 237751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 237851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Handle "generic" fields 2379afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath int parseStart = pos.getIndex(); 238051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (obeyCount) { 238151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((start+count) > text.length()) { 238251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parsing; 238351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 238451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski number = numberFormat.parse(text.substring(0, start+count), pos); 238551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 238651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski number = numberFormat.parse(text, pos); 238751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 238851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (number != null) { 2389d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // BEGIN Android-changed: Better UTS#35 conformity for fractional seconds. 2390afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath if (patternCharIndex == PATTERN_MILLISECOND) { 2391afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath // Fractional seconds must be treated specially. We must always 2392afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath // normalize them to their fractional second value [0, 1) before we attempt 2393afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath // to parse them. 2394afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath // 2395afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath // Case 1: 11.78 seconds is 11 seconds and 780 (not 78) milliseconds. 2396afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath // Case 2: 11.7890567 seconds is 11 seconds and 789 (not 7890567) milliseconds. 2397afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath double doubleValue = number.doubleValue(); 2398afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath int width = pos.getIndex() - parseStart; 2399afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath final double divisor = Math.pow(10, width); 2400afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath value = (int) ((doubleValue / divisor) * 1000); 2401afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath } else { 2402afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath value = number.intValue(); 2403afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath } 2404d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // END Android-changed: Better UTS#35 conformity for fractional seconds. 240551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 240651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (useFollowingMinusSignAsDelimiter && (value < 0) && 24074c8d6d2a84cffba9a34ea03d534d77027fb1974ePaul Duffin (((pos.index < text.length()) && 24084c8d6d2a84cffba9a34ea03d534d77027fb1974ePaul Duffin (text.charAt(pos.index) != minusSign)) || 24094c8d6d2a84cffba9a34ea03d534d77027fb1974ePaul Duffin ((pos.index == text.length()) && 24104c8d6d2a84cffba9a34ea03d534d77027fb1974ePaul Duffin (text.charAt(pos.index-1) == minusSign)))) { 241151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value = -value; 241251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pos.index--; 241351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 241451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 241551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski calb.set(field, value); 241651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return pos.index; 241751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 241851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break parsing; 241951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 242051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 242151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 242251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Parsing failed. 242351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski origPos.errorIndex = pos.index; 242451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return -1; 242551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 242651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2427d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // BEGIN Android-added: parseMonth and parseWeekday methods to parse using ICU data. 2428d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath private int parseMonth(String text, int count, int value, int start, 2429d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath int field, ParsePosition pos, boolean useDateFormatSymbols, 2430d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath boolean standalone, 2431d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath CalendarBuilder out) { 2432d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if (count <= 2) // i.e., M or MM. 2433d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath { 2434d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath // Don't want to parse the month if it is a string 2435d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath // while pattern uses numeric style: M or MM. 2436d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath // [We computed 'value' above.] 2437d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath out.set(Calendar.MONTH, value - 1); 2438d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath return pos.index; 2439d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 2440d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 2441d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath int index = -1; 2442d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if (useDateFormatSymbols) { 2443d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath // count >= 3 // i.e., MMM or MMMM 2444d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath // Want to be able to parse both short and long forms. 2445d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath // Try count == 4 first: 2446d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if ((index = matchString( 2447d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath text, start, Calendar.MONTH, 2448d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath standalone ? formatData.getStandAloneMonths() : formatData.getMonths(), 2449d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath out)) > 0) { 2450d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath return index; 2451d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 2452d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath // count == 4 failed, now try count == 3 2453d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if ((index = matchString( 2454d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath text, start, Calendar.MONTH, 2455d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath standalone ? formatData.getShortStandAloneMonths() : formatData.getShortMonths(), 2456d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath out)) > 0) { 2457d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath return index; 2458d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 2459d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } else { 2460d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath Map<String, Integer> map = calendar.getDisplayNames(field, 2461d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath Calendar.ALL_STYLES, 2462d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath locale); 2463d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if ((index = matchString(text, start, field, map, out)) > 0) { 2464d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath return index; 2465d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 2466d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 2467d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 2468d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath return index; 2469d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 2470d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 2471d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath private int parseWeekday(String text, int start, int field, boolean useDateFormatSymbols, 2472d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath boolean standalone, CalendarBuilder out) { 2473d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath int index = -1; 2474d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if (useDateFormatSymbols) { 2475d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath // Want to be able to parse both short and long forms. 2476d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath // Try count == 4 (DDDD) first: 2477d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if ((index=matchString( 2478d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath text, start, Calendar.DAY_OF_WEEK, 2479d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath standalone ? formatData.getStandAloneWeekdays() : formatData.getWeekdays(), 2480d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath out)) > 0) { 2481d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath return index; 2482d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 2483d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 2484d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath // DDDD failed, now try DDD 2485d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if ((index = matchString( 2486d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath text, start, Calendar.DAY_OF_WEEK, 2487d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath standalone ? formatData.getShortStandAloneWeekdays() : formatData.getShortWeekdays(), 2488d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath out)) > 0) { 2489d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath return index; 2490d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 2491d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } else { 2492d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath int[] styles = { Calendar.LONG, Calendar.SHORT }; 2493d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath for (int style : styles) { 2494d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath Map<String,Integer> map = calendar.getDisplayNames(field, style, locale); 2495d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath if ((index = matchString(text, start, field, map, out)) > 0) { 2496d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath return index; 2497d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 2498d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 2499d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 2500d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 2501d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath return index; 2502d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath } 2503d7c6839b0afae1fc8ad25d8495aac3b34daf12ddJoachim Sauer // END Android-added: parseMonth and parseWeekday methods to parse using ICU data. 2504d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath 250551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final String getCalendarName() { 250651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return calendar.getClass().getName(); 250751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 250851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 250951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private boolean useDateFormatSymbols() { 251051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (useDateFormatSymbols) { 251151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return true; 251251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 251351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return isGregorianCalendar() || locale == null; 251451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 251551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 251651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private boolean isGregorianCalendar() { 251751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return "java.util.GregorianCalendar".equals(getCalendarName()); 251851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 251951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 252051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 252151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Translates a pattern, mapping each character in the from string to the 252251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * corresponding character in the to string. 252351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 252451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IllegalArgumentException if the given pattern is invalid 252551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 252651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private String translatePattern(String pattern, String from, String to) { 252751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski StringBuilder result = new StringBuilder(); 252851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean inQuote = false; 252951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < pattern.length(); ++i) { 253051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = pattern.charAt(i); 253151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (inQuote) { 25326e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin if (c == '\'') { 253351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski inQuote = false; 25346e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin } 253551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 253651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else { 25376e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin if (c == '\'') { 253851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski inQuote = true; 25396e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin } else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { 254051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int ci = from.indexOf(c); 254151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (ci >= 0) { 254251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // patternChars is longer than localPatternChars due 254351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // to serialization compatibility. The pattern letters 254451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // unsupported by localPatternChars pass through. 254551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (ci < to.length()) { 254651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski c = to.charAt(ci); 254751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 254851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 254951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("Illegal pattern " + 255051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski " character '" + 255151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski c + "'"); 255251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 255351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 255451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 255551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski result.append(c); 255651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25576e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin if (inQuote) { 255851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("Unfinished quote in pattern"); 25596e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin } 256051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return result.toString(); 256151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 256251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 256351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 256451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a pattern string describing this date format. 256551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 256651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a pattern string describing this date format. 256751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 256851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String toPattern() { 256951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return pattern; 257051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 257151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 257251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 257351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a localized pattern string describing this date format. 257451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 257551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a localized pattern string describing this date format. 257651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 257751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String toLocalizedPattern() { 257851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return translatePattern(pattern, 257951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DateFormatSymbols.patternChars, 258051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski formatData.getLocalPatternChars()); 258151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 258251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 258351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 258451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Applies the given pattern string to this date format. 258551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 258651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param pattern the new date and time pattern for this date format 258751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception NullPointerException if the given pattern is null 258851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IllegalArgumentException if the given pattern is invalid 258951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 259051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void applyPattern(String pattern) 259151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 259251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski compiledPattern = compile(pattern); 259351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.pattern = pattern; 259451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 259551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 259651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 259751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Applies the given localized pattern string to this date format. 259851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 259951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param pattern a String to be mapped to the new date and time format 260051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * pattern for this format 260151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception NullPointerException if the given pattern is null 260251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IllegalArgumentException if the given pattern is invalid 260351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 260451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void applyLocalizedPattern(String pattern) { 260551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String p = translatePattern(pattern, 260651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski formatData.getLocalPatternChars(), 260751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DateFormatSymbols.patternChars); 260851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski compiledPattern = compile(p); 260951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.pattern = p; 261051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 261151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 261251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 261351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Gets a copy of the date and time format symbols of this date format. 261451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 261551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the date and time format symbols of this date format 261651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #setDateFormatSymbols 261751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 261851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DateFormatSymbols getDateFormatSymbols() 261951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 262051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (DateFormatSymbols)formatData.clone(); 262151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 262251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 262351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 262451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sets the date and time format symbols of this date format. 262551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 262651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param newFormatSymbols the new date and time format symbols 262751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception NullPointerException if the given newFormatSymbols is null 262851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #getDateFormatSymbols 262951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 263051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void setDateFormatSymbols(DateFormatSymbols newFormatSymbols) 263151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 263251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.formatData = (DateFormatSymbols)newFormatSymbols.clone(); 263351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski useDateFormatSymbols = true; 263451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 263551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 263651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 263751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Creates a copy of this <code>SimpleDateFormat</code>. This also 263851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * clones the format's date format symbols. 263951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 264051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a clone of this <code>SimpleDateFormat</code> 264151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 26426e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin @Override 264351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Object clone() { 264451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski SimpleDateFormat other = (SimpleDateFormat) super.clone(); 264551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski other.formatData = (DateFormatSymbols) formatData.clone(); 264651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return other; 264751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 264851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 264951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 265051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the hash code value for this <code>SimpleDateFormat</code> object. 265151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 265251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the hash code value for this <code>SimpleDateFormat</code> object. 265351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 26546e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin @Override 265551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int hashCode() 265651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 265751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return pattern.hashCode(); 265851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // just enough fields for a reasonable distribution 265951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 266051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 266151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 266251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Compares the given object with this <code>SimpleDateFormat</code> for 266351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * equality. 266451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 266551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return true if the given object is equal to this 266651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>SimpleDateFormat</code> 266751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 26686e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin @Override 266951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean equals(Object obj) 267051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 26716e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin if (!super.equals(obj)) { 26726e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin return false; // super does class check 26736e42190c7f7d7cf3d8b787c918de0d797c6ddbbaPaul Duffin } 267451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski SimpleDateFormat that = (SimpleDateFormat) obj; 267551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (pattern.equals(that.pattern) 267651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && formatData.equals(that.formatData)); 267751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 267851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 267951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 268051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * After reading an object from the input stream, the format 268151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * pattern in the object is verified. 268251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 268351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception InvalidObjectException if the pattern is invalid 268451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 268551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void readObject(ObjectInputStream stream) 268651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException, ClassNotFoundException { 268751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski stream.defaultReadObject(); 268851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 268951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 269051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski compiledPattern = compile(pattern); 269151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (Exception e) { 269251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new InvalidObjectException("invalid pattern"); 269351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 269451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 269551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (serialVersionOnStream < 1) { 269651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // didn't have defaultCenturyStart field 269751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski initializeDefaultCentury(); 269851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 269951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else { 270051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // fill in dependent transient field 270151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski parseAmbiguousDatesAsAfter(defaultCenturyStart); 270251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 270351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski serialVersionOnStream = currentSerialVersion; 270451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 270551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // If the deserialized object has a SimpleTimeZone, try 270651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // to replace it with a ZoneInfo equivalent in order to 270751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // be compatible with the SimpleTimeZone-based 270851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // implementation as much as possible. 270951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski TimeZone tz = getTimeZone(); 271051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tz instanceof SimpleTimeZone) { 271151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String id = tz.getID(); 271251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski TimeZone zi = TimeZone.getTimeZone(id); 271351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (zi != null && zi.hasSameRules(tz) && zi.getID().equals(id)) { 271451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski setTimeZone(zi); 271551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 271651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 271751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 271851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 271951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 272051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Analyze the negative subpattern of DecimalFormat and set/update values 272151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as necessary. 272251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 272351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void checkNegativeNumberExpression() { 272451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((numberFormat instanceof DecimalFormat) && 272551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski !numberFormat.equals(originalNumberFormat)) { 272651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String numberPattern = ((DecimalFormat)numberFormat).toPattern(); 272751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!numberPattern.equals(originalNumberPattern)) { 272851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hasFollowingMinusSign = false; 272951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 273051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int separatorIndex = numberPattern.indexOf(';'); 273151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // If the negative subpattern is not absent, we have to analayze 273251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // it in order to check if it has a following minus sign. 273351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (separatorIndex > -1) { 273451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int minusIndex = numberPattern.indexOf('-', separatorIndex); 273551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((minusIndex > numberPattern.lastIndexOf('0')) && 273651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (minusIndex > numberPattern.lastIndexOf('#'))) { 273751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hasFollowingMinusSign = true; 273851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski minusSign = ((DecimalFormat)numberFormat).getDecimalFormatSymbols().getMinusSign(); 273951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 274051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 274151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski originalNumberPattern = numberPattern; 274251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 274351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski originalNumberFormat = numberFormat; 274451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 274551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 274651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 274751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 2748