1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*******************************************************************************
3b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho* Copyright (C) 1997-2011, International Business Machines Corporation and    *
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* others. All Rights Reserved.                                                *
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*******************************************************************************
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* File SMPDTFMT.CPP
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Modification History:
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Date        Name        Description
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   02/19/97    aliu        Converted from java.
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   03/31/97    aliu        Modified extensively to work with 50 locales.
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   04/01/97    aliu        Added support for centuries.
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   07/09/97    helena      Made ParsePosition into a class.
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   07/21/98    stephen     Added initializeDefaultCentury.
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*                             Removed getZoneIndex (added in DateFormatSymbols)
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*                             Removed subParseLong
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*                             Removed chk
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*  02/22/99     stephen     Removed character literals for EBCDIC safety
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   10/14/99    aliu        Updated 2-digit year parsing so that only "00" thru
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*                           "99" are recognized. {j28 4182066}
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   11/15/99    weiv        Added support for week of year/day of week format
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************************
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ZID_KEY_MAX 128
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h"
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/smpdtfmt.h"
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/dtfmtsym.h"
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ures.h"
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/msgfmt.h"
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/calendar.h"
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/gregocal.h"
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/timezone.h"
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/decimfmt.h"
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/dcfmtsym.h"
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/uchar.h"
43b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/uniset.h"
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ustring.h"
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/basictz.h"
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/simpletz.h"
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/rbtz.h"
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/vtzone.h"
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "olsontz.h"
50b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "patternprops.h"
5150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "fphdlimp.h"
5250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "gregoimp.h"
5350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "hebrwcal.h"
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cstring.h"
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uassert.h"
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "umutex.h"
58b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "tzfmt.h"
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <float.h>
60b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "smpdtfst.h"
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <stdio.h>
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// *****************************************************************************
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// class SimpleDateFormat
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// *****************************************************************************
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
7285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const UChar PATTERN_CHAR_BASE = 0x40;
7385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Last-resort string to use for "GMT" when constructing time zone strings.
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// For time zones that have no names, use strings GMT+minutes and
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// GMT-minutes. For instance, in France the time zone is GMT+60.
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Also accepted are GMT+H:MM or GMT-H:MM.
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gGmt[]      = {0x0047, 0x004D, 0x0054, 0x0000};         // "GMT"
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gGmtPlus[]  = {0x0047, 0x004D, 0x0054, 0x002B, 0x0000}; // "GMT+"
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gGmtMinus[] = {0x0047, 0x004D, 0x0054, 0x002D, 0x0000}; // "GMT-"
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar gDefGmtPat[]       = {0x0047, 0x004D, 0x0054, 0x007B, 0x0030, 0x007D, 0x0000}; /* GMT{0} */
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar gDefGmtNegHmsPat[] = {0x002D, 0x0048, 0x0048, 0x003A, 0x006D, 0x006D, 0x003A, 0x0073, 0x0073, 0x0000}; /* -HH:mm:ss */
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar gDefGmtNegHmPat[]  = {0x002D, 0x0048, 0x0048, 0x003A, 0x006D, 0x006D, 0x0000}; /* -HH:mm */
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar gDefGmtPosHmsPat[] = {0x002B, 0x0048, 0x0048, 0x003A, 0x006D, 0x006D, 0x003A, 0x0073, 0x0073, 0x0000}; /* +HH:mm:ss */
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar gDefGmtPosHmPat[]  = {0x002B, 0x0048, 0x0048, 0x003A, 0x006D, 0x006D, 0x0000}; /* +HH:mm */
8885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const UChar gUt[]       = {0x0055, 0x0054, 0x0000};  // "UT"
8985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const UChar gUtc[]      = {0x0055, 0x0054, 0x0043, 0x0000};  // "UT"
9085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef enum GmtPatSize {
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    kGmtLen = 3,
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    kGmtPatLen = 6,
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    kNegHmsLen = 9,
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    kNegHmLen = 6,
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    kPosHmsLen = 9,
9785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    kPosHmLen = 6,
9885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    kUtLen = 2,
9985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    kUtcLen = 3
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} GmtPatSize;
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
10285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// Stuff needed for numbering system overrides
10385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
10485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hotypedef enum OvrStrType {
10585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    kOvrStrDate = 0,
10685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    kOvrStrTime = 1,
10785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    kOvrStrBoth = 2
10885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} OvrStrType;
10985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
11085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const UDateFormatField kDateFields[] = {
11185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_YEAR_FIELD,
11285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_MONTH_FIELD,
11385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_DATE_FIELD,
11485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_DAY_OF_YEAR_FIELD,
11585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_DAY_OF_WEEK_IN_MONTH_FIELD,
11685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_WEEK_OF_YEAR_FIELD,
11785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_WEEK_OF_MONTH_FIELD,
11885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_YEAR_WOY_FIELD,
11985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_EXTENDED_YEAR_FIELD,
12085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_JULIAN_DAY_FIELD,
12185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_STANDALONE_DAY_FIELD,
12285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_STANDALONE_MONTH_FIELD,
12385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_QUARTER_FIELD,
12485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_STANDALONE_QUARTER_FIELD };
12585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const int8_t kDateFieldsCount = 13;
12685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
12785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const UDateFormatField kTimeFields[] = {
12885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_HOUR_OF_DAY1_FIELD,
12927f654740f2a26ad62a5c155af9199af9e69b889claireho    UDAT_HOUR_OF_DAY0_FIELD,
13085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_MINUTE_FIELD,
13185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_SECOND_FIELD,
13285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_FRACTIONAL_SECOND_FIELD,
13385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_HOUR1_FIELD,
13485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_HOUR0_FIELD,
13585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_MILLISECONDS_IN_DAY_FIELD,
13685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_TIMEZONE_RFC_FIELD };
13785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const int8_t kTimeFieldsCount = 9;
13885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
13985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// This is a pattern-of-last-resort used when we can't load a usable pattern out
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// of a resource.
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gDefaultPattern[] =
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x79, 0x79, 0x79, 0x79, 0x4D, 0x4D, 0x64, 0x64, 0x20, 0x68, 0x68, 0x3A, 0x6D, 0x6D, 0x20, 0x61, 0
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};  /* "yyyyMMdd hh:mm a" */
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// This prefix is designed to NEVER MATCH real text, in order to
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// suppress the parsing of negative numbers.  Adjust as needed (if
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// this becomes valid Unicode).
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar SUPPRESS_NEGATIVE_PREFIX[] = {0xAB00, 0};
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * These are the tags we expect to see in normal resource bundle files associated
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * with a locale.
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char gDateTimePatternsTag[]="DateTimePatterns";
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar gEtcUTC[] = {0x45, 0x74, 0x63, 0x2F, 0x55, 0x54, 0x43, 0x00}; // "Etc/UTC"
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar QUOTE = 0x27; // Single quote
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * The field range check bias for each UDateFormatField.
163b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * The bias is added to the minimum and maximum values
164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * before they are compared to the parsed number.
165b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * For example, the calendar stores zero-based month numbers
166b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * but the parsed month numbers start at 1, so the bias is 1.
167b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *
168b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * A value of -1 means that the value is not checked.
169b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
170b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const int32_t gFieldRangeBias[] = {
171b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'G' - UDAT_ERA_FIELD
172b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'y' - UDAT_YEAR_FIELD
173b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho     1,  // 'M' - UDAT_MONTH_FIELD
174b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho     0,  // 'd' - UDAT_DATE_FIELD
175b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'k' - UDAT_HOUR_OF_DAY1_FIELD
176b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'H' - UDAT_HOUR_OF_DAY0_FIELD
177b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho     0,  // 'm' - UDAT_MINUTE_FIELD
178b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho     0,  // 's' - UDAT_SEOND_FIELD
179b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'S' - UDAT_FRACTIONAL_SECOND_FIELD (0-999?)
180b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'E' - UDAT_DAY_OF_WEEK_FIELD (1-7?)
181b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'D' - UDAT_DAY_OF_YEAR_FIELD (1 - 366?)
182b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'F' - UDAT_DAY_OF_WEEK_IN_MONTH_FIELD (1-5?)
183b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'w' - UDAT_WEEK_OF_YEAR_FIELD (1-52?)
184b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'W' - UDAT_WEEK_OF_MONTH_FIELD (1-5?)
185b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'a' - UDAT_AM_PM_FIELD
186b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'h' - UDAT_HOUR1_FIELD
187b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'K' - UDAT_HOUR0_FIELD
188b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'z' - UDAT_TIMEZONE_FIELD
189b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'Y' - UDAT_YEAR_WOY_FIELD
190b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'e' - UDAT_DOW_LOCAL_FIELD
191b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'u' - UDAT_EXTENDED_YEAR_FIELD
192b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'g' - UDAT_JULIAN_DAY_FIELD
193b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'A' - UDAT_MILLISECONDS_IN_DAY_FIELD
194b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'Z' - UDAT_TIMEZONE_RFC_FIELD
195b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'v' - UDAT_TIMEZONE_GENERIC_FIELD
196b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho     0,  // 'c' - UDAT_STANDALONE_DAY_FIELD
197b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho     1,  // 'L' - UDAT_STANDALONE_MONTH_FIELD
198b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'Q' - UDAT_QUARTER_FIELD (1-4?)
199b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1,  // 'q' - UDAT_STANDALONE_QUARTER_FIELD
200b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    -1   // 'V' - UDAT_TIMEZONE_SPECIAL_FIELD
201b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
202b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UMTX LOCK;
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleDateFormat)
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::~SimpleDateFormat()
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete fSymbols;
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fGMTFormatters) {
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (int32_t i = 0; i < kNumGMTFormatters; i++) {
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (fGMTFormatters[i]) {
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                delete fGMTFormatters[i];
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(fGMTFormatters);
21985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
22085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
22185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (fNumberFormatters) {
22285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_free(fNumberFormatters);
22385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
224b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fTimeZoneFormat) {
225b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fTimeZoneFormat;
226b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
22785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
22885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    while (fOverrideList) {
22985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        NSOverride *cur = fOverrideList;
23085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fOverrideList = cur->next;
23185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        delete cur->nf;
23285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_free(cur);
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::SimpleDateFormat(UErrorCode& status)
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  :   fLocale(Locale::getDefault()),
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      fSymbols(NULL),
241b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      fTimeZoneFormat(NULL),
24285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho      fGMTFormatters(NULL),
24385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho      fNumberFormatters(NULL),
24485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho      fOverrideList(NULL)
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    construct(kShort, (EStyle) (kShort + kDateOffset), fLocale, status);
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeDefaultCentury();
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   UErrorCode &status)
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru:   fPattern(pattern),
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fLocale(Locale::getDefault()),
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols(NULL),
257b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fTimeZoneFormat(NULL),
25885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
25985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
26085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
26285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fDateOverride.setToBogus();
26385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fTimeOverride.setToBogus();
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initialize(fLocale, status);
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeDefaultCentury();
26785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
26885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
26985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
27085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
27185bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
27285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                   const UnicodeString& override,
27385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                   UErrorCode &status)
27485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho:   fPattern(pattern),
27585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fLocale(Locale::getDefault()),
27685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fSymbols(NULL),
277b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fTimeZoneFormat(NULL),
27885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
27985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
28085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
28185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho{
28285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fDateOverride.setTo(override);
28385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fTimeOverride.setToBogus();
28485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
28585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    initialize(fLocale, status);
28685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    initializeDefaultCentury();
28785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
28885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    processOverrideString(fLocale,override,kOvrStrBoth,status);
28985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   const Locale& locale,
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   UErrorCode& status)
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru:   fPattern(pattern),
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fLocale(locale),
299b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fTimeZoneFormat(NULL),
30085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
30185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
30285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
30485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
30585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fDateOverride.setToBogus();
30685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fTimeOverride.setToBogus();
30785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initialize(fLocale, status);
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeDefaultCentury();
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
31685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                   const UnicodeString& override,
31785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                   const Locale& locale,
31885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                   UErrorCode& status)
31985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho:   fPattern(pattern),
32085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fLocale(locale),
321b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fTimeZoneFormat(NULL),
32285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
32385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
32485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
32585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho{
32685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
32785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fDateOverride.setTo(override);
32885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fTimeOverride.setToBogus();
32985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
33085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
33185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    initialize(fLocale, status);
33285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    initializeDefaultCentury();
33385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
33485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    processOverrideString(locale,override,kOvrStrBoth,status);
33585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
33685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
33785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
33885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
33985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
34085bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   DateFormatSymbols* symbolsToAdopt,
342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   UErrorCode& status)
343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru:   fPattern(pattern),
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fLocale(Locale::getDefault()),
345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols(symbolsToAdopt),
346b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fTimeZoneFormat(NULL),
34785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
34885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
34985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
35185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
35285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fDateOverride.setToBogus();
35385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fTimeOverride.setToBogus();
35485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeCalendar(NULL,fLocale,status);
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initialize(fLocale, status);
357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeDefaultCentury();
358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   const DateFormatSymbols& symbols,
364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   UErrorCode& status)
365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru:   fPattern(pattern),
366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fLocale(Locale::getDefault()),
367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols(new DateFormatSymbols(symbols)),
368b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fTimeZoneFormat(NULL),
36985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
37085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
37185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
37385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
37485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fDateOverride.setToBogus();
37585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fTimeOverride.setToBogus();
37685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeCalendar(NULL, fLocale, status);
378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initialize(fLocale, status);
379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeDefaultCentury();
380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Not for public consumption; used by DateFormat
385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::SimpleDateFormat(EStyle timeStyle,
386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   EStyle dateStyle,
387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   const Locale& locale,
388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   UErrorCode& status)
389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru:   fLocale(locale),
390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols(NULL),
391b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fTimeZoneFormat(NULL),
39285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
39385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
39485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    construct(timeStyle, dateStyle, fLocale, status);
397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_SUCCESS(status)) {
398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      initializeDefaultCentury();
399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Not for public consumption; used by DateFormat.  This constructor
406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * never fails.  If the resource data is not available, it uses the
407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the last resort symbols.
408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::SimpleDateFormat(const Locale& locale,
410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   UErrorCode& status)
411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru:   fPattern(gDefaultPattern),
412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fLocale(locale),
413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols(NULL),
414b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fTimeZoneFormat(NULL),
41585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
41685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
41785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) return;
420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeSymbols(fLocale, initializeCalendar(NULL, fLocale, status),status);
421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status))
422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_ZERO_ERROR;
424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete fSymbols;
425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // This constructor doesn't fail; it uses last resort data
426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fSymbols = new DateFormatSymbols(status);
427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* test for NULL */
428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (fSymbols == 0) {
429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            status = U_MEMORY_ALLOCATION_ERROR;
430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return;
431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
43485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fDateOverride.setToBogus();
43585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fTimeOverride.setToBogus();
43685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initialize(fLocale, status);
438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_SUCCESS(status)) {
439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      initializeDefaultCentury();
440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::SimpleDateFormat(const SimpleDateFormat& other)
446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru:   DateFormat(other),
447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols(NULL),
448b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fTimeZoneFormat(NULL),
44985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
45085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
45185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *this = other;
454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat& SimpleDateFormat::operator=(const SimpleDateFormat& other)
459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (this == &other) {
461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return *this;
462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DateFormat::operator=(other);
464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete fSymbols;
466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols = NULL;
467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (other.fSymbols)
469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fSymbols = new DateFormatSymbols(*other.fSymbols);
470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fDefaultCenturyStart         = other.fDefaultCenturyStart;
472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fDefaultCenturyStartYear     = other.fDefaultCenturyStartYear;
473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fHaveDefaultCentury          = other.fHaveDefaultCentury;
474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fPattern = other.fPattern;
476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
477b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // TimeZoneFormat in ICU4C only depends on a locale for now
478b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fLocale != other.fLocale) {
479b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fTimeZoneFormat;
480b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
481b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return *this;
483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruFormat*
488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::clone() const
489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return new SimpleDateFormat(*this);
491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::operator==(const Format& other) const
497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (DateFormat::operator==(other)) {
499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // DateFormat::operator== guarantees following cast is safe
500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        SimpleDateFormat* that = (SimpleDateFormat*)&other;
501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return (fPattern             == that->fPattern &&
502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                fSymbols             != NULL && // Check for pathological object
503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                that->fSymbols       != NULL && // Check for pathological object
504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *fSymbols            == *that->fSymbols &&
505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                fHaveDefaultCentury  == that->fHaveDefaultCentury &&
506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                fDefaultCenturyStart == that->fDefaultCenturyStart);
507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid SimpleDateFormat::construct(EStyle timeStyle,
514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                 EStyle dateStyle,
515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                 const Locale& locale,
516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                 UErrorCode& status)
517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // called by several constructors to load pattern data from the resources
519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) return;
520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // We will need the calendar to know what type of symbols to load.
522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeCalendar(NULL, locale, status);
523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) return;
524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    CalendarData calData(locale, fCalendar?fCalendar->getType():NULL, status);
526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UResourceBundle *dateTimePatterns = calData.getByKey(gDateTimePatternsTag, status);
52785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UResourceBundle *currentBundle;
52885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) return;
530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (ures_getSize(dateTimePatterns) <= kDateTime)
532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_INVALID_FORMAT_ERROR;
534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    setLocaleIDs(ures_getLocaleByType(dateTimePatterns, ULOC_VALID_LOCALE, &status),
538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 ures_getLocaleByType(dateTimePatterns, ULOC_ACTUAL_LOCALE, &status));
539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // create a symbols object from the locale
541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeSymbols(locale,fCalendar, status);
542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) return;
543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* test for NULL */
544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fSymbols == 0) {
545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
54985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    const UChar *resStr,*ovrStr;
55085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t resStrLen,ovrStrLen = 0;
55185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fDateOverride.setToBogus();
55285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fTimeOverride.setToBogus();
553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // if the pattern should include both date and time information, use the date/time
555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // pattern string as a guide to tell use how to glue together the appropriate date
556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // and time pattern strings.  The actual gluing-together is handled by a convenience
557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // method on MessageFormat.
558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if ((timeStyle != kNone) && (dateStyle != kNone))
559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Formattable timeDateArray[2];
561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // use Formattable::adoptString() so that we can use fastCopyFrom()
563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // instead of Formattable::setString()'s unaware, safe, deep string clone
564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // see Jitterbug 2296
56550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
56685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        currentBundle = ures_getByIndex(dateTimePatterns, (int32_t)timeStyle, NULL, &status);
56785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
56885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           status = U_INVALID_FORMAT_ERROR;
56985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           return;
57085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
57185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        switch (ures_getType(currentBundle)) {
57285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            case URES_STRING: {
57385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               resStr = ures_getString(currentBundle, &resStrLen, &status);
57485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               break;
57585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
57685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            case URES_ARRAY: {
57785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               resStr = ures_getStringByIndex(currentBundle, 0, &resStrLen, &status);
57885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               ovrStr = ures_getStringByIndex(currentBundle, 1, &ovrStrLen, &status);
57985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               fTimeOverride.setTo(TRUE, ovrStr, ovrStrLen);
58085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               break;
58185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
58285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            default: {
58385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               status = U_INVALID_FORMAT_ERROR;
58485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               ures_close(currentBundle);
58585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               return;
58685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
58750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
58885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ures_close(currentBundle);
58950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
59085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UnicodeString *tempus1 = new UnicodeString(TRUE, resStr, resStrLen);
59185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // NULL pointer check
59285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (tempus1 == NULL) {
59385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            status = U_MEMORY_ALLOCATION_ERROR;
59485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return;
59585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
59685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        timeDateArray[0].adoptString(tempus1);
59750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
59885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        currentBundle = ures_getByIndex(dateTimePatterns, (int32_t)dateStyle, NULL, &status);
59985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
60085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           status = U_INVALID_FORMAT_ERROR;
60185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           return;
60285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
60385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        switch (ures_getType(currentBundle)) {
60485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            case URES_STRING: {
60585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               resStr = ures_getString(currentBundle, &resStrLen, &status);
60650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho               break;
60785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
60885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            case URES_ARRAY: {
60985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               resStr = ures_getStringByIndex(currentBundle, 0, &resStrLen, &status);
61085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               ovrStr = ures_getStringByIndex(currentBundle, 1, &ovrStrLen, &status);
61185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               fDateOverride.setTo(TRUE, ovrStr, ovrStrLen);
61250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho               break;
61385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
61485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            default: {
61585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               status = U_INVALID_FORMAT_ERROR;
61685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               ures_close(currentBundle);
61785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               return;
61885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
61950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
62085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ures_close(currentBundle);
62185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
62285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UnicodeString *tempus2 = new UnicodeString(TRUE, resStr, resStrLen);
62385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // Null pointer check
62485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (tempus2 == NULL) {
62585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            status = U_MEMORY_ALLOCATION_ERROR;
62685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return;
62785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
62885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        timeDateArray[1].adoptString(tempus2);
629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
63085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        int32_t glueIndex = kDateTime;
63185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        int32_t patternsSize = ures_getSize(dateTimePatterns);
63285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (patternsSize >= (kDateTimeOffset + kShort + 1)) {
63385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Get proper date time format
63485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            glueIndex = (int32_t)(kDateTimeOffset + (dateStyle - kDateOffset));
63585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
63685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
63785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        resStr = ures_getStringByIndex(dateTimePatterns, glueIndex, &resStrLen, &status);
638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        MessageFormat::format(UnicodeString(TRUE, resStr, resStrLen), timeDateArray, 2, fPattern, status);
639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // if the pattern includes just time data or just date date, load the appropriate
641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // pattern string from the resources
642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // setTo() - see DateFormatSymbols::assignArray comments
643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else if (timeStyle != kNone) {
64485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        currentBundle = ures_getByIndex(dateTimePatterns, (int32_t)timeStyle, NULL, &status);
64585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
64685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           status = U_INVALID_FORMAT_ERROR;
64785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           return;
64885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
64985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        switch (ures_getType(currentBundle)) {
65085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            case URES_STRING: {
65185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               resStr = ures_getString(currentBundle, &resStrLen, &status);
65250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho               break;
65385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
65485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            case URES_ARRAY: {
65585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               resStr = ures_getStringByIndex(currentBundle, 0, &resStrLen, &status);
65685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               ovrStr = ures_getStringByIndex(currentBundle, 1, &ovrStrLen, &status);
65785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               fDateOverride.setTo(TRUE, ovrStr, ovrStrLen);
65850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho               break;
65985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
66085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            default: {
66185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               status = U_INVALID_FORMAT_ERROR;
66285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                ures_close(currentBundle);
66385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               return;
66485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
66550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
666ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fPattern.setTo(TRUE, resStr, resStrLen);
66785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ures_close(currentBundle);
668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else if (dateStyle != kNone) {
67085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        currentBundle = ures_getByIndex(dateTimePatterns, (int32_t)dateStyle, NULL, &status);
67185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
67285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           status = U_INVALID_FORMAT_ERROR;
67385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           return;
67485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
67585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        switch (ures_getType(currentBundle)) {
67685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            case URES_STRING: {
67785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               resStr = ures_getString(currentBundle, &resStrLen, &status);
67850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho               break;
67985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
68085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            case URES_ARRAY: {
68185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               resStr = ures_getStringByIndex(currentBundle, 0, &resStrLen, &status);
68285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               ovrStr = ures_getStringByIndex(currentBundle, 1, &ovrStrLen, &status);
68385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               fDateOverride.setTo(TRUE, ovrStr, ovrStrLen);
68450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho               break;
68585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
68685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            default: {
68785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               status = U_INVALID_FORMAT_ERROR;
68885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               ures_close(currentBundle);
68985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               return;
69085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
69150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fPattern.setTo(TRUE, resStr, resStrLen);
69385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ures_close(currentBundle);
694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
69550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // and if it includes _neither_, that's an error
697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else
698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_INVALID_FORMAT_ERROR;
699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // finally, finish initializing by creating a Calendar and a NumberFormat
701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initialize(locale, status);
702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendar*
707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::initializeCalendar(TimeZone* adoptZone, const Locale& locale, UErrorCode& status)
708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(!U_FAILURE(status)) {
710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fCalendar = Calendar::createInstance(adoptZone?adoptZone:TimeZone::createDefault(), locale, status);
711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status) && fCalendar == NULL) {
713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return fCalendar;
716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::initializeSymbols(const Locale& locale, Calendar* calendar, UErrorCode& status)
720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  if(U_FAILURE(status)) {
722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols = NULL;
723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  } else {
724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // pass in calendar type - use NULL (default) if no calendar set (or err).
725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols = new DateFormatSymbols(locale, calendar?calendar->getType() :NULL , status);
72685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // Null pointer check
72785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (fSymbols == NULL) {
728b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_MEMORY_ALLOCATION_ERROR;
729b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
73085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
731ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  }
732ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
733ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
734ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::initialize(const Locale& locale,
736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             UErrorCode& status)
737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
738ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) return;
739ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
740ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // We don't need to check that the row count is >= 1, since all 2d arrays have at
741ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // least one row
742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fNumberFormat = NumberFormat::createInstance(locale, status);
743ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fNumberFormat != NULL && U_SUCCESS(status))
744ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // no matter what the locale's default number format looked like, we want
746ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // to modify it so that it doesn't use thousands separators, doesn't always
747ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // show the decimal point, and recognizes integers only when parsing
748ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
749ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fNumberFormat->setGroupingUsed(FALSE);
75027f654740f2a26ad62a5c155af9199af9e69b889claireho        DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(fNumberFormat);
75127f654740f2a26ad62a5c155af9199af9e69b889claireho        if (decfmt != NULL) {
75227f654740f2a26ad62a5c155af9199af9e69b889claireho            decfmt->setDecimalSeparatorAlwaysShown(FALSE);
75327f654740f2a26ad62a5c155af9199af9e69b889claireho        }
754ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fNumberFormat->setParseIntegerOnly(TRUE);
755ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fNumberFormat->setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
75685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
757b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        //fNumberFormat->setLenient(TRUE); // Java uses a custom DateNumberFormat to format/parse
758b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
75985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        initNumberFormatters(locale,status);
76050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else if (U_SUCCESS(status))
763ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
764ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_MISSING_RESOURCE_ERROR;
765ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
766ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
767ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
768ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Initialize the fields we use to disambiguate ambiguous years. Separate
769ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * so we can call it from readObject().
770ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
77150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid SimpleDateFormat::initializeDefaultCentury()
772ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
773ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  if(fCalendar) {
774ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fHaveDefaultCentury = fCalendar->haveDefaultCentury();
775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(fHaveDefaultCentury) {
776ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      fDefaultCenturyStart = fCalendar->defaultCenturyStart();
777ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      fDefaultCenturyStartYear = fCalendar->defaultCenturyStartYear();
778ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      fDefaultCenturyStart = DBL_MIN;
780ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      fDefaultCenturyStartYear = -1;
781ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  }
783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Define one-century window into which to disambiguate dates using
786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * two-digit years. Make public in JDK 1.2.
787ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
78850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid SimpleDateFormat::parseAmbiguousDatesAsAfter(UDate startDate, UErrorCode& status)
789ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
790ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(status)) {
791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(!fCalendar) {
794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      status = U_ILLEGAL_ARGUMENT_ERROR;
795ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      return;
796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
79750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fCalendar->setTime(startDate, status);
799ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_SUCCESS(status)) {
800ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fHaveDefaultCentury = TRUE;
801ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fDefaultCenturyStart = startDate;
802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fDefaultCenturyStartYear = fCalendar->get(UCAL_YEAR, status);
803ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
804ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
80550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
808ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::format(Calendar& cal, UnicodeString& appendTo, FieldPosition& pos) const
810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
81150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  UErrorCode status = U_ZERO_ERROR;
81250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  FieldPositionOnlyHandler handler(pos);
81350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  return _format(cal, appendTo, handler, status);
81450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
81550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
81650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho//----------------------------------------------------------------------
81750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
81850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString&
81950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSimpleDateFormat::format(Calendar& cal, UnicodeString& appendTo,
82050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                         FieldPositionIterator* posIter, UErrorCode& status) const
82150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{
82250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  FieldPositionIteratorHandler handler(posIter, status);
82350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  return _format(cal, appendTo, handler, status);
82450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
82550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
82650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho//----------------------------------------------------------------------
827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
82850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString&
82950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo, FieldPositionHandler& handler,
83050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                          UErrorCode& status) const
83150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{
83285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    Calendar *workCal = &cal;
83385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    TimeZone *backupTZ = NULL;
83485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (&cal != fCalendar && uprv_strcmp(cal.getType(), fCalendar->getType()) != 0) {
83585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // Different calendar type
83685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // We use the time and time zone from the input calendar, but
83785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // do not use the input calendar for field calculation.
83885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UDate t = cal.getTime(status);
83985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fCalendar->setTime(t, status);
84085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        backupTZ = fCalendar->getTimeZone().clone();
84185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fCalendar->setTimeZone(cal.getTimeZone());
84285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        workCal = fCalendar;
84385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
84485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool inQuote = FALSE;
846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar prevCh = 0;
847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t count = 0;
84850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
849ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // loop through the pattern string character by character
850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (int32_t i = 0; i < fPattern.length() && U_SUCCESS(status); ++i) {
851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar ch = fPattern[i];
85250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
853ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Use subFormat() to format a repeated pattern character
854ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // when a different pattern or non-pattern character is seen
855ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (ch != prevCh && count > 0) {
85650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            subFormat(appendTo, prevCh, count, handler, *workCal, status);
857ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            count = 0;
858ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
859ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (ch == QUOTE) {
860ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Consecutive single quotes are a single quote literal,
861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // either outside of quotes or between quotes
862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((i+1) < fPattern.length() && fPattern[i+1] == QUOTE) {
863ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                appendTo += (UChar)QUOTE;
864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++i;
865ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                inQuote = ! inQuote;
867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
86850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
86950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else if ( ! inQuote && ((ch >= 0x0061 /*'a'*/ && ch <= 0x007A /*'z'*/)
870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    || (ch >= 0x0041 /*'A'*/ && ch <= 0x005A /*'Z'*/))) {
871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // ch is a date-time pattern character to be interpreted
872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // by subFormat(); count the number of times it is repeated
873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            prevCh = ch;
874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ++count;
875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
876ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else {
877ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Append quoted characters and unquoted non-pattern characters
878ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            appendTo += ch;
879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
881ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
882ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Format the last item in the pattern, if any
883ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (count > 0) {
88450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        subFormat(appendTo, prevCh, count, handler, *workCal, status);
88585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
88685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
88785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (backupTZ != NULL) {
88885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // Restore the original time zone
88985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fCalendar->adoptTimeZone(backupTZ);
890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return appendTo;
893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
89785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/* Map calendar field into calendar field level.
89885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * the larger the level, the smaller the field unit.
89985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * For example, UCAL_ERA level is 0, UCAL_YEAR level is 10,
90085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * UCAL_MONTH level is 20.
90185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * NOTE: if new fields adds in, the table needs to update.
90285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */
90385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoconst int32_t
90485bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::fgCalendarFieldToLevel[] =
90585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho{
90685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*GyM*/ 0, 10, 20,
90785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*wW*/ 20, 30,
90885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*dDEF*/ 30, 20, 30, 30,
90985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*ahHm*/ 40, 50, 50, 60,
91050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /*sS..*/ 70, 80,
91150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /*z?Y*/ 0, 0, 10,
91285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*eug*/ 30, 10, 0,
91350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /*A*/ 40
91485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho};
91585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
91685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
91785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/* Map calendar field LETTER into calendar field level.
91885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * the larger the level, the smaller the field unit.
91985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * NOTE: if new fields adds in, the table needs to update.
92085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */
92185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoconst int32_t
92285bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::fgPatternCharToLevel[] = {
92385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
924b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        -1, 40, -1, -1, 20, 30, 30,  0, 50, -1, -1, 50, 20, 20, -1, -1,
92585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    //   P   Q   R   S   T   U   V   W   X   Y   Z
926b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        -1, 20, -1, 80, -1, -1,  0, 30, -1, 10,  0, -1, -1, -1, -1, -1,
92785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
928b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        -1, 40, -1, 30, 30, 30, -1,  0, 50, -1, -1, 50, -1, 60, -1, -1,
92985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    //   p   q   r   s   t   u   v   w   x   y   z
930b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        -1, 20, -1, 70, -1, 10,  0, 20, -1, 10,  0, -1, -1, -1, -1, -1
93185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho};
93285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
93385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Map index into pattern character string to Calendar field number.
935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst UCalendarDateFields
936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::fgPatternIndexToCalendarField[] =
937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*GyM*/ UCAL_ERA, UCAL_YEAR, UCAL_MONTH,
939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*dkH*/ UCAL_DATE, UCAL_HOUR_OF_DAY, UCAL_HOUR_OF_DAY,
940ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*msS*/ UCAL_MINUTE, UCAL_SECOND, UCAL_MILLISECOND,
941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*EDF*/ UCAL_DAY_OF_WEEK, UCAL_DAY_OF_YEAR, UCAL_DAY_OF_WEEK_IN_MONTH,
942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*wWa*/ UCAL_WEEK_OF_YEAR, UCAL_WEEK_OF_MONTH, UCAL_AM_PM,
943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*hKz*/ UCAL_HOUR, UCAL_HOUR, UCAL_ZONE_OFFSET,
944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*Yeu*/ UCAL_YEAR_WOY, UCAL_DOW_LOCAL, UCAL_EXTENDED_YEAR,
945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*gAZ*/ UCAL_JULIAN_DAY, UCAL_MILLISECONDS_IN_DAY, UCAL_ZONE_OFFSET,
946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*v*/   UCAL_ZONE_OFFSET,
94785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*c*/   UCAL_DOW_LOCAL,
948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*L*/   UCAL_MONTH,
949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*Q*/   UCAL_MONTH,
950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*q*/   UCAL_MONTH,
951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*V*/   UCAL_ZONE_OFFSET,
952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Map index into pattern character string to DateFormat field number
955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst UDateFormatField
956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::fgPatternIndexToDateFormatField[] = {
957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*GyM*/ UDAT_ERA_FIELD, UDAT_YEAR_FIELD, UDAT_MONTH_FIELD,
958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*dkH*/ UDAT_DATE_FIELD, UDAT_HOUR_OF_DAY1_FIELD, UDAT_HOUR_OF_DAY0_FIELD,
959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*msS*/ UDAT_MINUTE_FIELD, UDAT_SECOND_FIELD, UDAT_FRACTIONAL_SECOND_FIELD,
960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*EDF*/ UDAT_DAY_OF_WEEK_FIELD, UDAT_DAY_OF_YEAR_FIELD, UDAT_DAY_OF_WEEK_IN_MONTH_FIELD,
961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*wWa*/ UDAT_WEEK_OF_YEAR_FIELD, UDAT_WEEK_OF_MONTH_FIELD, UDAT_AM_PM_FIELD,
962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*hKz*/ UDAT_HOUR1_FIELD, UDAT_HOUR0_FIELD, UDAT_TIMEZONE_FIELD,
963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*Yeu*/ UDAT_YEAR_WOY_FIELD, UDAT_DOW_LOCAL_FIELD, UDAT_EXTENDED_YEAR_FIELD,
964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*gAZ*/ UDAT_JULIAN_DAY_FIELD, UDAT_MILLISECONDS_IN_DAY_FIELD, UDAT_TIMEZONE_RFC_FIELD,
965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*v*/   UDAT_TIMEZONE_GENERIC_FIELD,
966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*c*/   UDAT_STANDALONE_DAY_FIELD,
967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*L*/   UDAT_STANDALONE_MONTH_FIELD,
968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*Q*/   UDAT_QUARTER_FIELD,
969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*q*/   UDAT_STANDALONE_QUARTER_FIELD,
970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*V*/   UDAT_TIMEZONE_SPECIAL_FIELD,
971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Append symbols[value] to dst.  Make sure the array index is not out
977ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * of bounds.
978ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic inline void
980ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru_appendSymbol(UnicodeString& dst,
981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              int32_t value,
982ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              const UnicodeString* symbols,
983ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              int32_t symbolsCount) {
984ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    U_ASSERT(0 <= value && value < symbolsCount);
985ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (0 <= value && value < symbolsCount) {
986ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        dst += symbols[value];
987ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
988ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
989ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//---------------------------------------------------------------------
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
99285bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::appendGMT(NumberFormat *currentNumberFormat,UnicodeString &appendTo, Calendar& cal, UErrorCode& status) const{
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offset = cal.get(UCAL_ZONE_OFFSET, status) + cal.get(UCAL_DST_OFFSET, status);
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
997b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (offset == 0) {
998b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // use GMT zero format
999b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        appendTo += fSymbols->fGmtZero;
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1001b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (isDefaultGMTFormat()) {
1002b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            formatGMTDefault(currentNumberFormat,appendTo, offset);
1003b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1004b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ((SimpleDateFormat*)this)->initGMTFormatters(status);
1005b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_SUCCESS(status)) {
1006b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                int32_t type;
1007b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (offset < 0) {
1008b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    offset = -offset;
1009b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    type = (offset % U_MILLIS_PER_MINUTE) == 0 ? kGMTNegativeHM : kGMTNegativeHMS;
1010b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                } else {
1011b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    type = (offset % U_MILLIS_PER_MINUTE) == 0 ? kGMTPositiveHM : kGMTPositiveHMS;
1012b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
1013b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                Formattable param(offset, Formattable::kIsDate);
1014b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                FieldPosition fpos(0);
1015b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                fGMTFormatters[type]->format(&param, 1, appendTo, fpos, status);
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleDateFormat::parseGMT(const UnicodeString &text, ParsePosition &pos) const {
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (!isDefaultGMTFormat()) {
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t start = pos.getIndex();
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Quick check
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UBool prefixMatch = FALSE;
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t prefixLen = fSymbols->fGmtFormat.indexOf((UChar)0x007B /* '{' */);
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (prefixLen > 0 && text.compare(start, prefixLen, fSymbols->fGmtFormat, 0, prefixLen) == 0) {
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            prefixMatch = TRUE;
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (prefixMatch) {
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Prefix matched
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UErrorCode status = U_ZERO_ERROR;
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ((SimpleDateFormat*)this)->initGMTFormatters(status);
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_SUCCESS(status)) {
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                Formattable parsed;
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                int32_t parsedCount;
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Try negative Hms
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fGMTFormatters[kGMTNegativeHMS]->parseObject(text, parsed, pos);
104285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (pos.getErrorIndex() == -1 &&
104385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    (pos.getIndex() - start) >= fGMTFormatHmsMinLen[kGMTNegativeHMSMinLenIdx]) {
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    parsed.getArray(parsedCount);
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (parsedCount == 1 && parsed[0].getType() == Formattable::kDate) {
104685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        return (int32_t)(-1 * (int64_t)parsed[0].getDate());
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Reset ParsePosition
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setIndex(start);
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setErrorIndex(-1);
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Try positive Hms
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fGMTFormatters[kGMTPositiveHMS]->parseObject(text, parsed, pos);
105685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (pos.getErrorIndex() == -1 &&
105785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    (pos.getIndex() - start) >= fGMTFormatHmsMinLen[kGMTPositiveHMSMinLenIdx]) {
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    parsed.getArray(parsedCount);
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (parsedCount == 1 && parsed[0].getType() == Formattable::kDate) {
106085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        return (int32_t)((int64_t)parsed[0].getDate());
1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Reset ParsePosition
1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setIndex(start);
1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setErrorIndex(-1);
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Try negative Hm
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fGMTFormatters[kGMTNegativeHM]->parseObject(text, parsed, pos);
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (pos.getErrorIndex() == -1 && pos.getIndex() > start) {
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    parsed.getArray(parsedCount);
1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (parsedCount == 1 && parsed[0].getType() == Formattable::kDate) {
107385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        return (int32_t)(-1 * (int64_t)parsed[0].getDate());
1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Reset ParsePosition
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setIndex(start);
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setErrorIndex(-1);
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Try positive Hm
1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fGMTFormatters[kGMTPositiveHM]->parseObject(text, parsed, pos);
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (pos.getErrorIndex() == -1 && pos.getIndex() > start) {
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    parsed.getArray(parsedCount);
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (parsedCount == 1 && parsed[0].getType() == Formattable::kDate) {
108685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        return (int32_t)((int64_t)parsed[0].getDate());
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Reset ParsePosition
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setIndex(start);
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setErrorIndex(-1);
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // fall through to the default GMT parsing method
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return parseGMTDefault(text, pos);
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1099ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
110185bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::formatGMTDefault(NumberFormat *currentNumberFormat,UnicodeString &appendTo, int32_t offset) const {
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (offset < 0) {
1103b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        appendTo.append(gGmtMinus, 4);
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset = -offset; // suppress the '-' sign for text display.
1105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }else{
1106b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        appendTo.append(gGmtPlus, 4);
1107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    offset /= U_MILLIS_PER_SECOND; // now in seconds
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t sec = offset % 60;
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    offset /= 60;
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t min = offset % 60;
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t hour = offset / 60;
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
111685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    zeroPaddingNumber(currentNumberFormat,appendTo, hour, 2, 2);
1117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    appendTo += (UChar)0x003A /*':'*/;
111885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    zeroPaddingNumber(currentNumberFormat,appendTo, min, 2, 2);
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (sec != 0) {
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        appendTo += (UChar)0x003A /*':'*/;
112185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        zeroPaddingNumber(currentNumberFormat,appendTo, sec, 2, 2);
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleDateFormat::parseGMTDefault(const UnicodeString &text, ParsePosition &pos) const {
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t start = pos.getIndex();
112827f654740f2a26ad62a5c155af9199af9e69b889claireho    NumberFormat *currentNumberFormat = getNumberFormatByIndex(UDAT_TIMEZONE_RFC_FIELD);
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
113085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (start + kUtLen + 1 >= text.length()) {
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos.setErrorIndex(start);
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t cur = start;
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // "GMT"
113785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (text.compare(start, kGmtLen, gGmt) == 0) {
113885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        cur += kGmtLen;
113985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    } else if (text.compare(start, kUtLen, gUt) == 0) {
114085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        cur += kUtLen;
114185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    } else {
1142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos.setErrorIndex(start);
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Sign
1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool negative = FALSE;
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (text.charAt(cur) == (UChar)0x002D /* minus */) {
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        negative = TRUE;
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (text.charAt(cur) != (UChar)0x002B /* plus */) {
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos.setErrorIndex(cur);
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cur++;
1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Numbers
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t numLen;
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pos.setIndex(cur);
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Formattable number;
116085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    parseInt(text, number, 6, pos, FALSE,currentNumberFormat);
1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    numLen = pos.getIndex() - cur;
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (numLen <= 0) {
1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos.setIndex(start);
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos.setErrorIndex(cur);
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t numVal = number.getLong();
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t hour = 0;
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t min = 0;
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t sec = 0;
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (numLen <= 2) {
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // H[H][:mm[:ss]]
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        hour = numVal;
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        cur += numLen;
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (cur + 2 < text.length() && text.charAt(cur) == (UChar)0x003A /* colon */) {
1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            cur++;
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pos.setIndex(cur);
118285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            parseInt(text, number, 2, pos, FALSE,currentNumberFormat);
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            numLen = pos.getIndex() - cur;
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (numLen == 2) {
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // got minute field
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                min = number.getLong();
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                cur += numLen;
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (cur + 2 < text.length() && text.charAt(cur) == (UChar)0x003A /* colon */) {
1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    cur++;
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    pos.setIndex(cur);
119185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    parseInt(text, number, 2, pos, FALSE,currentNumberFormat);
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    numLen = pos.getIndex() - cur;
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (numLen == 2) {
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // got second field
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        sec = number.getLong();
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else {
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // reset position
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        pos.setIndex(cur - 1);
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        pos.setErrorIndex(-1);
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // reset postion
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setIndex(cur - 1);
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setErrorIndex(-1);
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (numLen == 3 || numLen == 4) {
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Hmm or HHmm
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        hour = numVal / 100;
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        min = numVal % 100;
1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (numLen == 5 || numLen == 6) {
1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Hmmss or HHmmss
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        hour = numVal / 10000;
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        min = (numVal % 10000) / 100;
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        sec = numVal % 100;
1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // HHmmss followed by bogus numbers
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos.setIndex(cur + 6);
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t shift = numLen - 6;
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (shift > 0) {
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            numVal /= 10;
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            shift--;
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        hour = numVal / 10000;
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        min = (numVal % 10000) / 100;
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        sec = numVal % 100;
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offset = ((hour*60 + min)*60 + sec)*1000;
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (negative) {
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset = -offset;
1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return offset;
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleDateFormat::isDefaultGMTFormat() const {
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // GMT pattern
1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fSymbols->fGmtFormat.length() == 0) {
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // No GMT pattern is set
1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (fSymbols->fGmtFormat.compare(gDefGmtPat, kGmtPatLen) != 0) {
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Hour patterns
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fSymbols->fGmtHourFormats == NULL || fSymbols->fGmtHourFormatsCount != DateFormatSymbols::GMT_HOUR_COUNT) {
1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // No Hour pattern is set
1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if ((fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_NEGATIVE_HMS].compare(gDefGmtNegHmsPat, kNegHmsLen) != 0)
1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || (fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_NEGATIVE_HM].compare(gDefGmtNegHmPat, kNegHmLen) != 0)
1253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || (fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_POSITIVE_HMS].compare(gDefGmtPosHmsPat, kPosHmsLen) != 0)
1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || (fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_POSITIVE_HM].compare(gDefGmtPosHmPat, kPosHmLen) != 0)) {
1255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleDateFormat::formatRFC822TZ(UnicodeString &appendTo, int32_t offset) const {
1262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar sign = 0x002B /* '+' */;
1263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (offset < 0) {
1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset = -offset;
1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        sign = 0x002D /* '-' */;
1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    appendTo.append(sign);
1268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offsetH = offset / U_MILLIS_PER_HOUR;
1270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    offset = offset % U_MILLIS_PER_HOUR;
1271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offsetM = offset / U_MILLIS_PER_MINUTE;
1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    offset = offset % U_MILLIS_PER_MINUTE;
1273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offsetS = offset / U_MILLIS_PER_SECOND;
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t num = 0, denom = 0;
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (offsetS == 0) {
1277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset = offsetH*100 + offsetM; // HHmm
1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        num = offset % 10000;
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        denom = 1000;
1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset = offsetH*10000 + offsetM*100 + offsetS; // HHmmss
1282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        num = offset % 1000000;
1283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        denom = 100000;
1284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (denom >= 1) {
1286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UChar digit = (UChar)0x0030 + (num / denom);
1287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        appendTo.append(digit);
1288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        num = num % denom;
1289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        denom /= 10;
1290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleDateFormat::initGMTFormatters(UErrorCode &status) {
1295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
1296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_lock(&LOCK);
1299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fGMTFormatters == NULL) {
1300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fGMTFormatters = (MessageFormat**)uprv_malloc(kNumGMTFormatters * sizeof(MessageFormat*));
1301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (fGMTFormatters) {
1302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for (int32_t i = 0; i < kNumGMTFormatters; i++) {
130385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                const UnicodeString *hourPattern = NULL; //initialized it to avoid warning
1304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                switch (i) {
1305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case kGMTNegativeHMS:
1306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        hourPattern = &(fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_NEGATIVE_HMS]);
1307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
1308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case kGMTNegativeHM:
1309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        hourPattern = &(fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_NEGATIVE_HM]);
1310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
1311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case kGMTPositiveHMS:
1312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        hourPattern = &(fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_POSITIVE_HMS]);
1313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
1314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case kGMTPositiveHM:
1315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        hourPattern = &(fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_POSITIVE_HM]);
1316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
1317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fGMTFormatters[i] = new MessageFormat(fSymbols->fGmtFormat, status);
131985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                GregorianCalendar *gcal = new GregorianCalendar(TimeZone::createTimeZone(UnicodeString(gEtcUTC)), status);
1320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (U_FAILURE(status)) {
1321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
1322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                SimpleDateFormat *sdf = (SimpleDateFormat*)this->clone();
132485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                sdf->adoptCalendar(gcal);
1325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                sdf->applyPattern(*hourPattern);
1326b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1327b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // This prevents an hours format pattern like "-HH:mm:ss" from matching
1328b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // in a string like "GMT-07:00 10:08:11 PM"
1329b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                sdf->setLenient(FALSE);
1330b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fGMTFormatters[i]->adoptFormat(0, sdf);
133285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
133385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                // For parsing, we only allow Hms patterns to be equal or longer
133485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                // than its length with fixed minutes/seconds digits.
133585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                // See #6880
133685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (i == kGMTNegativeHMS || i == kGMTPositiveHMS) {
133785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    UnicodeString tmp;
133885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    Formattable tmpParam(60*60*1000, Formattable::kIsDate);
133985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    FieldPosition fpos(0);
134085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    fGMTFormatters[i]->format(&tmpParam, 1, tmp, fpos, status);
134185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    if (U_FAILURE(status)) {
134285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        break;
134385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    }
134485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    if (i == kGMTNegativeHMS) {
134585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        fGMTFormatHmsMinLen[kGMTNegativeHMSMinLenIdx] = tmp.length();
134685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    } else {
134785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        fGMTFormatHmsMinLen[kGMTPositiveHMSMinLenIdx] = tmp.length();
134885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    }
134985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
1350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            status = U_MEMORY_ALLOCATION_ERROR;
1353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_unlock(&LOCK);
1356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
135885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hovoid
135985bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::initNumberFormatters(const Locale &locale,UErrorCode &status) {
136085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (U_FAILURE(status)) {
136185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return;
136285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
136385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if ( fDateOverride.isBogus() && fTimeOverride.isBogus() ) {
136485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return;
136585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
136685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    umtx_lock(&LOCK);
136785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (fNumberFormatters == NULL) {
136885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fNumberFormatters = (NumberFormat**)uprv_malloc(UDAT_FIELD_COUNT * sizeof(NumberFormat*));
136985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (fNumberFormatters) {
137085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            for (int32_t i = 0; i < UDAT_FIELD_COUNT; i++) {
137185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                fNumberFormatters[i] = fNumberFormat;
137285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
137385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else {
137485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            status = U_MEMORY_ALLOCATION_ERROR;
137585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
137685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
137785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    umtx_unlock(&LOCK);
137850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
137985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    processOverrideString(locale,fDateOverride,kOvrStrDate,status);
138085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    processOverrideString(locale,fTimeOverride,kOvrStrTime,status);
138185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
138285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
138385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
138485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hovoid
138585bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::processOverrideString(const Locale &locale, const UnicodeString &str, int8_t type, UErrorCode &status) {
138685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (str.isBogus()) {
138785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return;
138885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
138985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t start = 0;
139085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t len;
139185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UnicodeString nsName;
139285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UnicodeString ovrField;
139385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UBool moreToProcess = TRUE;
139485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
139585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    while (moreToProcess) {
1396b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t delimiterPosition = str.indexOf((UChar)ULOC_KEYWORD_ITEM_SEPARATOR_UNICODE,start);
139785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (delimiterPosition == -1) {
139885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            moreToProcess = FALSE;
139985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            len = str.length() - start;
140085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else {
140185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            len = delimiterPosition - start;
140285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
140385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UnicodeString currentString(str,start,len);
1404b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t equalSignPosition = currentString.indexOf((UChar)ULOC_KEYWORD_ASSIGN_UNICODE,0);
140585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (equalSignPosition == -1) { // Simple override string such as "hebrew"
140685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            nsName.setTo(currentString);
140785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ovrField.setToBogus();
140885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else { // Field specific override string such as "y=hebrew"
140985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            nsName.setTo(currentString,equalSignPosition+1);
141085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ovrField.setTo(currentString,0,1); // We just need the first character.
141185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
141285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
141385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        int32_t nsNameHash = nsName.hashCode();
141485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // See if the numbering system is in the override list, if not, then add it.
141585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        NSOverride *cur = fOverrideList;
141685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        NumberFormat *nf = NULL;
141785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UBool found = FALSE;
141885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        while ( cur && !found ) {
141985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if ( cur->hash == nsNameHash ) {
142085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                nf = cur->nf;
142185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                found = TRUE;
142285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
142385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            cur = cur->next;
142485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
142585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
142685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (!found) {
142785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           cur = (NSOverride *)uprv_malloc(sizeof(NSOverride));
142885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           if (cur) {
142985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               char kw[ULOC_KEYWORD_AND_VALUES_CAPACITY];
143085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               uprv_strcpy(kw,"numbers=");
143185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               nsName.extract(0,len,kw+8,ULOC_KEYWORD_AND_VALUES_CAPACITY-8,US_INV);
143285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
143385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               Locale ovrLoc(locale.getLanguage(),locale.getCountry(),locale.getVariant(),kw);
143485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               nf = NumberFormat::createInstance(ovrLoc,status);
143585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
143685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               // no matter what the locale's default number format looked like, we want
143785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               // to modify it so that it doesn't use thousands separators, doesn't always
143885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               // show the decimal point, and recognizes integers only when parsing
143985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
144085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               if (U_SUCCESS(status)) {
144185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   nf->setGroupingUsed(FALSE);
144227f654740f2a26ad62a5c155af9199af9e69b889claireho                   DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(nf);
144327f654740f2a26ad62a5c155af9199af9e69b889claireho                   if (decfmt != NULL) {
144427f654740f2a26ad62a5c155af9199af9e69b889claireho                       decfmt->setDecimalSeparatorAlwaysShown(FALSE);
144527f654740f2a26ad62a5c155af9199af9e69b889claireho                   }
144685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   nf->setParseIntegerOnly(TRUE);
144785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   nf->setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
144885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
144985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   cur->nf = nf;
145085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   cur->hash = nsNameHash;
145185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   cur->next = fOverrideList;
145285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   fOverrideList = cur;
145385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               }
145485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               else {
145585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   // clean up before returning
145685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   if (cur != NULL) {
145785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                       uprv_free(cur);
145885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   }
145985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                  return;
146085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               }
146185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
146285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           } else {
146385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               status = U_MEMORY_ALLOCATION_ERROR;
146485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               return;
146585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           }
146685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
146750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
146885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // Now that we have an appropriate number formatter, fill in the appropriate spaces in the
146985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // number formatters table.
147085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
147185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (ovrField.isBogus()) {
147285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            switch (type) {
147385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case kOvrStrDate:
147485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case kOvrStrBoth: {
147585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    for ( int8_t i=0 ; i<kDateFieldsCount; i++ ) {
147685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        fNumberFormatters[kDateFields[i]] = nf;
147785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    }
147885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    if (type==kOvrStrDate) {
147985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        break;
148085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    }
148185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
148285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case kOvrStrTime : {
148385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    for ( int8_t i=0 ; i<kTimeFieldsCount; i++ ) {
148485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        fNumberFormatters[kTimeFields[i]] = nf;
148585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    }
148685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
148785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
148885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
148985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else {
149085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           UChar ch = ovrField.charAt(0);
149185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           UChar *patternCharPtr = u_strchr(DateFormatSymbols::getPatternUChars(), ch);
149285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           UDateFormatField patternCharIndex;
149385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
149485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           // if the pattern character is unrecognized, signal an error and bail out
149585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           if (patternCharPtr == NULL) {
149685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               status = U_INVALID_FORMAT_ERROR;
149785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               return;
149885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           }
149985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           patternCharIndex = (UDateFormatField)(patternCharPtr - DateFormatSymbols::getPatternUChars());
150085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
150185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           // Set the number formatter in the table
150285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           fNumberFormatters[patternCharIndex] = nf;
150385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
150485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
150585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        start = delimiterPosition + 1;
150685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
150750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
1508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//---------------------------------------------------------------------
1509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::subFormat(UnicodeString &appendTo,
1511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            UChar ch,
1512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            int32_t count,
151350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            FieldPositionHandler& handler,
1514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            Calendar& cal,
1515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            UErrorCode& status) const
1516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
1518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // this function gets called by format() to produce the appropriate substitution
1522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // text for an individual pattern symbol (e.g., "HH" or "yyyy")
1523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar *patternCharPtr = u_strchr(DateFormatSymbols::getPatternUChars(), ch);
1525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UDateFormatField patternCharIndex;
1526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const int32_t maxIntCount = 10;
1527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t beginOffset = appendTo.length();
152885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    NumberFormat *currentNumberFormat;
1529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
153050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UBool isHebrewCalendar = !strcmp(cal.getType(),"hebrew");
153150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
1532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // if the pattern character is unrecognized, signal an error and dump out
1533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (patternCharPtr == NULL)
1534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
1535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_INVALID_FORMAT_ERROR;
1536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    patternCharIndex = (UDateFormatField)(patternCharPtr - DateFormatSymbols::getPatternUChars());
1540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UCalendarDateFields field = fgPatternIndexToCalendarField[patternCharIndex];
1541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t value = cal.get(field, status);
1542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
1543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
154627f654740f2a26ad62a5c155af9199af9e69b889claireho    currentNumberFormat = getNumberFormatByIndex(patternCharIndex);
1547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    switch (patternCharIndex) {
154850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
1549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for any "G" symbol, write out the appropriate era string
155085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // "GGGG" is wide era name, "GGGGG" is narrow era name, anything else is abbreviated name
1551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_ERA_FIELD:
155285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (count == 5)
155385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           _appendSymbol(appendTo, value, fSymbols->fNarrowEras, fSymbols->fNarrowErasCount);
155485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        else if (count == 4)
1555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru           _appendSymbol(appendTo, value, fSymbols->fEraNames, fSymbols->fEraNamesCount);
1556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else
1557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru           _appendSymbol(appendTo, value, fSymbols->fEras, fSymbols->fErasCount);
1558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
156085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // OLD: for "yyyy", write out the whole year; for "yy", write out the last 2 digits
156185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // NEW: UTS#35:
1562b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//Year         y     yy     yyy     yyyy     yyyyy
1563b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//AD 1         1     01     001     0001     00001
1564b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//AD 12       12     12     012     0012     00012
1565b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//AD 123     123     23     123     0123     00123
1566b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//AD 1234   1234     34    1234     1234     01234
1567b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//AD 12345 12345     45   12345    12345     12345
1568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_YEAR_FIELD:
1569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_YEAR_WOY_FIELD:
157085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(count == 2)
157150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            zeroPaddingNumber(currentNumberFormat, appendTo, value, 2, 2);
157250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else
157350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            zeroPaddingNumber(currentNumberFormat, appendTo, value, count, maxIntCount);
157450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        break;
1575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "MMMM", write out the whole month name, for "MMM", write out the month
1577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // abbreviation, for "M" or "MM", write out the month as a number with the
1578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // appropriate number of digits
1579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "MMMMM", use the narrow form
1580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_MONTH_FIELD:
158150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if ( isHebrewCalendar ) {
158250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho           HebrewCalendar *hc = (HebrewCalendar*)&cal;
158350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho           if (hc->isLeapYear(hc->get(UCAL_YEAR,status)) && value == 6 && count >= 3 )
158450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho               value = 13; // Show alternate form for Adar II in leap years in Hebrew calendar.
158550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho           if (!hc->isLeapYear(hc->get(UCAL_YEAR,status)) && value >= 6 && count < 3 )
158650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho               value--; // Adjust the month number down 1 in Hebrew non-leap years, i.e. Adar is 6, not 7.
158750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
158850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (count == 5)
1589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fNarrowMonths,
1590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fNarrowMonthsCount);
159150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else if (count == 4)
1592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fMonths,
1593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fMonthsCount);
159450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else if (count == 3)
1595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fShortMonths,
1596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fShortMonthsCount);
159750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else
159885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, value + 1, count, maxIntCount);
1599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "LLLL", write out the whole month name, for "LLL", write out the month
1602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // abbreviation, for "L" or "LL", write out the month as a number with the
1603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // appropriate number of digits
1604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "LLLLL", use the narrow form
1605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_STANDALONE_MONTH_FIELD:
160650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (count == 5)
1607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fStandaloneNarrowMonths,
1608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fStandaloneNarrowMonthsCount);
160950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else if (count == 4)
1610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fStandaloneMonths,
1611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fStandaloneMonthsCount);
161250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else if (count == 3)
1613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fStandaloneShortMonths,
1614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fStandaloneShortMonthsCount);
161550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else
161685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, value + 1, count, maxIntCount);
1617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "k" and "kk", write out the hour, adjusting midnight to appear as "24"
1620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_HOUR_OF_DAY1_FIELD:
162150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (value == 0)
162285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, cal.getMaximum(UCAL_HOUR_OF_DAY) + 1, count, maxIntCount);
162350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else
162485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, value, count, maxIntCount);
1625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_FRACTIONAL_SECOND_FIELD:
1628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Fractional seconds left-justify
1629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
163085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            currentNumberFormat->setMinimumIntegerDigits((count > 3) ? 3 : count);
163185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            currentNumberFormat->setMaximumIntegerDigits(maxIntCount);
1632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (count == 1) {
163327f654740f2a26ad62a5c155af9199af9e69b889claireho                value /= 100;
1634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if (count == 2) {
163527f654740f2a26ad62a5c155af9199af9e69b889claireho                value /= 10;
1636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            FieldPosition p(0);
163885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            currentNumberFormat->format(value, appendTo, p);
1639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (count > 3) {
164085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                currentNumberFormat->setMinimumIntegerDigits(count - 3);
164185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                currentNumberFormat->format((int32_t)0, appendTo, p);
1642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1645ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
164685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // for "ee" or "e", use local numeric day-of-the-week
164785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // for "EEEEE" or "eeeee", write out the narrow day-of-the-week name
164885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // for "EEEE" or "eeee", write out the wide day-of-the-week name
164985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // for "EEE" or "EE" or "E" or "eee", write out the abbreviated day-of-the-week name
165085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    case UDAT_DOW_LOCAL_FIELD:
165185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if ( count < 3 ) {
165285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, value, count, maxIntCount);
165385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            break;
165485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
165585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // fall through to EEEEE-EEE handling, but for that we don't want local day-of-week,
165685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // we want standard day-of-week, so first fix value to work for EEEEE-EEE.
165785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        value = cal.get(UCAL_DAY_OF_WEEK, status);
165885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
165985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return;
166085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
166185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // fall through, do not break here
1662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_DAY_OF_WEEK_FIELD:
166350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (count == 5)
1664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fNarrowWeekdays,
1665ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fNarrowWeekdaysCount);
166650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else if (count == 4)
1667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fWeekdays,
1668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fWeekdaysCount);
1669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else
1670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fShortWeekdays,
1671ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fShortWeekdaysCount);
1672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "ccc", write out the abbreviated day-of-the-week name
1675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "cccc", write out the wide day-of-the-week name
1676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "ccccc", use the narrow day-of-the-week name
1677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_STANDALONE_DAY_FIELD:
167885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if ( count < 3 ) {
167985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, value, 1, maxIntCount);
168085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            break;
168185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
168285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // fall through to alpha DOW handling, but for that we don't want local day-of-week,
168385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // we want standard day-of-week, so first fix value.
168485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        value = cal.get(UCAL_DAY_OF_WEEK, status);
168585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
168685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return;
168785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
168850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (count == 5)
1689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fStandaloneNarrowWeekdays,
1690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fStandaloneNarrowWeekdaysCount);
169150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else if (count == 4)
1692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fStandaloneWeekdays,
1693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fStandaloneWeekdaysCount);
169485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        else // count == 3
1695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fStandaloneShortWeekdays,
1696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fStandaloneShortWeekdaysCount);
1697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for and "a" symbol, write out the whole AM/PM string
1700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_AM_PM_FIELD:
1701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        _appendSymbol(appendTo, value, fSymbols->fAmPms,
1702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                      fSymbols->fAmPmsCount);
1703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "h" and "hh", write out the hour, adjusting noon and midnight to show up
1706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // as "12"
1707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_HOUR1_FIELD:
170850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (value == 0)
170985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, cal.getLeastMaximum(UCAL_HOUR) + 1, count, maxIntCount);
171050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else
171185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, value, count, maxIntCount);
1712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for the "z" symbols, we have to check our time zone data first.  If we have a
1715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // localized name for the time zone, then "zzzz" / "zzz" indicate whether
1716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // daylight time is in effect (long/short) and "zz" / "z" do not (long/short).
1717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // If we don't have a localized time zone name,
1718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // then the time zone shows up as "GMT+hh:mm" or "GMT-hh:mm" (where "hh:mm" is the
1719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // offset from GMT) regardless of how many z's were in the pattern symbol
172050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case UDAT_TIMEZONE_FIELD:
1721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case UDAT_TIMEZONE_GENERIC_FIELD:
172250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case UDAT_TIMEZONE_SPECIAL_FIELD:
1723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UnicodeString zoneString;
1725b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const TimeZone& tz = cal.getTimeZone();
1726b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UDate date = cal.getTime(status);
1727b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_SUCCESS(status)) {
1728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (patternCharIndex == UDAT_TIMEZONE_FIELD) {
1729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (count < 4) {
1730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // "z", "zz", "zzz"
1731b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        tzFormat()->format(UTZFMT_STYLE_SPECIFIC_SHORT_COMMONLY_USED, tz, date, zoneString);
1732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else {
1733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // "zzzz"
1734b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        tzFormat()->format(UTZFMT_STYLE_SPECIFIC_LONG, tz, date, zoneString);
1735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else if (patternCharIndex == UDAT_TIMEZONE_GENERIC_FIELD) {
1737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (count == 1) {
1738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // "v"
1739b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        tzFormat()->format(UTZFMT_STYLE_GENERIC_SHORT, tz, date, zoneString);
1740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else if (count == 4) {
1741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // "vvvv"
1742b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        tzFormat()->format(UTZFMT_STYLE_GENERIC_LONG, tz, date, zoneString);
1743ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else { // patternCharIndex == UDAT_TIMEZONE_SPECIAL_FIELD
1745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (count == 1) {
1746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // "V"
1747b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        tzFormat()->format(UTZFMT_STYLE_SPECIFIC_SHORT, tz, date, zoneString);
1748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else if (count == 4) {
1749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // "VVVV"
1750b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        tzFormat()->format(UTZFMT_STYLE_LOCATION, tz, date, zoneString);
1751ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1752ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1753ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (zoneString.isEmpty()) {
175585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                appendGMT(currentNumberFormat,appendTo, cal, status);
1756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
1757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                appendTo += zoneString;
1758ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1759ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
1761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case UDAT_TIMEZONE_RFC_FIELD: // 'Z' - TIMEZONE_RFC
1763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (count < 4) {
1764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // RFC822 format, must use ASCII digits
1765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            value = (cal.get(UCAL_ZONE_OFFSET, status) + cal.get(UCAL_DST_OFFSET, status));
1766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            formatRFC822TZ(appendTo, value);
1767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // long form, localized GMT pattern
176985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            appendGMT(currentNumberFormat,appendTo, cal, status);
1770ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1771ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1772ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1773ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_QUARTER_FIELD:
177450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (count >= 4)
1775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value/3, fSymbols->fQuarters,
1776ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fQuartersCount);
177750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else if (count == 3)
1778ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value/3, fSymbols->fShortQuarters,
1779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fShortQuartersCount);
178050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else
178185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, (value/3) + 1, count, maxIntCount);
1782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_STANDALONE_QUARTER_FIELD:
178550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (count >= 4)
1786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value/3, fSymbols->fStandaloneQuarters,
1787ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fStandaloneQuartersCount);
178850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else if (count == 3)
1789ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value/3, fSymbols->fStandaloneShortQuarters,
1790ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fStandaloneShortQuartersCount);
179150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else
179285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, (value/3) + 1, count, maxIntCount);
1793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1795ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // all of the other pattern symbols can be formatted as simple numbers with
1797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // appropriate zero padding
1798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    default:
179985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        zeroPaddingNumber(currentNumberFormat,appendTo, value, count, maxIntCount);
1800ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1801ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
180350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    handler.addAttribute(fgPatternIndexToDateFormatField[patternCharIndex], beginOffset, appendTo.length());
1804ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
180550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
180685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
180785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
180885bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoNumberFormat *
180927f654740f2a26ad62a5c155af9199af9e69b889clairehoSimpleDateFormat::getNumberFormatByIndex(UDateFormatField index) const {
181085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (fNumberFormatters != NULL) {
181185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return fNumberFormatters[index];
181285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    } else {
181385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return fNumberFormat;
181485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
181585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
1816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
1818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
181950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSimpleDateFormat::zeroPaddingNumber(NumberFormat *currentNumberFormat,UnicodeString &appendTo,
182050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                    int32_t value, int32_t minDigits, int32_t maxDigits) const
1821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
182285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (currentNumberFormat!=NULL) {
182385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        FieldPosition pos(0);
1824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
182585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        currentNumberFormat->setMinimumIntegerDigits(minDigits);
182685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        currentNumberFormat->setMaximumIntegerDigits(maxDigits);
182785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        currentNumberFormat->format(value, appendTo, pos);  // 3rd arg is there to speed up processing
182885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
1829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
1832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
1834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Format characters that indicate numeric fields.  The character
1835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * at index 0 is treated specially.
1836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
183785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const UChar NUMERIC_FORMAT_CHARS[] = {0x4D, 0x59, 0x79, 0x75, 0x64, 0x65, 0x68, 0x48, 0x6D, 0x73, 0x53, 0x44, 0x46, 0x77, 0x57, 0x6B, 0x4B, 0x00}; /* "MYyudehHmsSDFwWkK" */
1838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
1840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Return true if the given format character, occuring count
1841ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * times, represents a numeric field.
1842ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
1843ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool SimpleDateFormat::isNumeric(UChar formatChar, int32_t count) {
1844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString s(NUMERIC_FORMAT_CHARS);
1845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i = s.indexOf(formatChar);
1846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (i > 0 || (i == 0 && count < 3));
1847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1848ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1849ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition& parsePos) const
1851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
185285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UErrorCode status = U_ZERO_ERROR;
1853ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t pos = parsePos.getIndex();
1854ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t start = pos;
185585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
1856ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool ambiguousYear[] = { FALSE };
185750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t saveHebrewMonth = -1;
1858ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t count = 0;
1859ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1860b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UBool lenient = isLenient();
1861b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // hack, reset tztype, cast away const
1863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ((SimpleDateFormat*)this)->tztype = TZTYPE_UNK;
1864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1865ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // For parsing abutting numeric fields. 'abutPat' is the
1866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // offset into 'pattern' of the first of 2 or more abutting
1867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // numeric fields.  'abutStart' is the offset into 'text'
1868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // where parsing the fields begins. 'abutPass' starts off as 0
1869ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // and increments each time we try to parse the fields.
1870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t abutPat = -1; // If >=0, we are in a run of abutting numeric fields
1871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t abutStart = 0;
1872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t abutPass = 0;
1873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool inQuote = FALSE;
1874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UnicodeString numericFormatChars(NUMERIC_FORMAT_CHARS);
1876ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
187785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    TimeZone *backupTZ = NULL;
187885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    Calendar *workCal = &cal;
187985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (&cal != fCalendar && uprv_strcmp(cal.getType(), fCalendar->getType()) != 0) {
188085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // Different calendar type
188185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // We use the time/zone from the input calendar, but
188285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // do not use the input calendar for field calculation.
188385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fCalendar->setTime(cal.getTime(status),status);
188485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
188585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            goto ExitParse;
188685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
188785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        backupTZ = fCalendar->getTimeZone().clone();
188885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fCalendar->setTimeZone(cal.getTimeZone());
188985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        workCal = fCalendar;
189085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
189185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
1892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (int32_t i=0; i<fPattern.length(); ++i) {
1893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar ch = fPattern.charAt(i);
1894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Handle alphabetic field characters.
1896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (!inQuote && ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A))) { // [A-Za-z]
1897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t fieldPat = i;
1898ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1899ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Count the length of this field specifier
1900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            count = 1;
1901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while ((i+1)<fPattern.length() &&
1902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                   fPattern.charAt(i+1) == ch) {
1903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++count;
1904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++i;
1905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (isNumeric(ch, count)) {
1908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (abutPat < 0) {
1909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // Determine if there is an abutting numeric field.  For
1910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // most fields we can just look at the next characters,
1911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // but the 'm' field is either numeric or text,
1912ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // depending on the count, so we have to look ahead for
1913ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // that field.
1914ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if ((i+1)<fPattern.length()) {
1915ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        UBool abutting;
1916ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        UChar nextCh = fPattern.charAt(i+1);
1917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        int32_t k = numericFormatChars.indexOf(nextCh);
1918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        if (k == 0) {
1919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            int32_t j = i+2;
1920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            while (j<fPattern.length() &&
1921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   fPattern.charAt(j) == nextCh) {
1922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                ++j;
1923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            }
1924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            abutting = (j-i) < 4; // nextCount < 3
1925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        } else {
1926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            abutting = k > 0;
1927ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        }
1928ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        // Record the start of a set of abutting numeric
1930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        // fields.
1931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        if (abutting) {
1932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            abutPat = fieldPat;
1933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            abutStart = pos;
1934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            abutPass = 0;
1935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        }
1936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
1939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                abutPat = -1; // End of any abutting fields
1940ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Handle fields within a run of abutting numeric fields.  Take
1943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // the pattern "HHmmss" as an example. We will try to parse
1944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // 2/2/2 characters of the input text, then if that fails,
1945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // 1/2/2.  We only adjust the width of the leftmost field; the
1946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // others remain fixed.  This allows "123456" => 12:34:56, but
1947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // "12345" => 1:23:45.  Likewise, for the pattern "yyyyMMdd" we
1948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // try 4/2/2, 3/2/2, 2/2/2, and finally 1/2/2.
1949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (abutPat >= 0) {
1950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // If we are at the start of a run of abutting fields, then
1951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // shorten this field in each pass.  If we can't shorten
1952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // this field any more, then the parse of this set of
1953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // abutting numeric fields has failed.
1954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (fieldPat == abutPat) {
1955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    count -= abutPass++;
1956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (count == 0) {
195785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        status = U_PARSE_ERROR;
195885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        goto ExitParse;
1959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                pos = subParse(text, pos, ch, count,
196350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                               TRUE, FALSE, ambiguousYear, saveHebrewMonth, *workCal, i);
1964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // If the parse fails anywhere in the run, back up to the
1966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // start of the run and retry.
1967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (pos < 0) {
1968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    i = abutPat - 1;
1969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    pos = abutStart;
1970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    continue;
1971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Handle non-numeric fields and non-abutting numeric
1975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // fields.
1976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            else {
197785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                int32_t s = subParse(text, pos, ch, count,
197850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                               FALSE, TRUE, ambiguousYear, saveHebrewMonth, *workCal, i);
1979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
198027f654740f2a26ad62a5c155af9199af9e69b889claireho                if (s == -pos-1) {
198127f654740f2a26ad62a5c155af9199af9e69b889claireho                    // era not present, in special cases allow this to continue
198227f654740f2a26ad62a5c155af9199af9e69b889claireho                    s++;
198327f654740f2a26ad62a5c155af9199af9e69b889claireho
198427f654740f2a26ad62a5c155af9199af9e69b889claireho                    if (i+1 < fPattern.length()) {
198527f654740f2a26ad62a5c155af9199af9e69b889claireho                        // move to next pattern character
198627f654740f2a26ad62a5c155af9199af9e69b889claireho                        UChar ch = fPattern.charAt(i+1);
198727f654740f2a26ad62a5c155af9199af9e69b889claireho
198827f654740f2a26ad62a5c155af9199af9e69b889claireho                        // check for whitespace
1989b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        if (PatternProps::isWhiteSpace(ch)) {
199027f654740f2a26ad62a5c155af9199af9e69b889claireho                            i++;
199127f654740f2a26ad62a5c155af9199af9e69b889claireho                            // Advance over run in pattern
199227f654740f2a26ad62a5c155af9199af9e69b889claireho                            while ((i+1)<fPattern.length() &&
1993b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                   PatternProps::isWhiteSpace(fPattern.charAt(i+1))) {
199427f654740f2a26ad62a5c155af9199af9e69b889claireho                                ++i;
199527f654740f2a26ad62a5c155af9199af9e69b889claireho                            }
199627f654740f2a26ad62a5c155af9199af9e69b889claireho                        }
199727f654740f2a26ad62a5c155af9199af9e69b889claireho                    }
199827f654740f2a26ad62a5c155af9199af9e69b889claireho                }
1999b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                else if (s <= 0) {
200085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    status = U_PARSE_ERROR;
200185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    goto ExitParse;
2002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
200385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                pos = s;
2004ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2005ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2006ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2007ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Handle literal pattern characters.  These are any
2008ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // quoted characters and non-alphabetic unquoted
2009ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // characters.
2010ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else {
201150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2012ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            abutPat = -1; // End of any abutting fields
2013b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2014b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (! matchLiterals(fPattern, i, text, pos, lenient)) {
2015b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                status = U_PARSE_ERROR;
2016b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                goto ExitParse;
2017ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2018ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2019ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2020ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2021ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // At this point the fields of Calendar have been set.  Calendar
2022ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // will fill in default values for missing fields when the time
2023ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // is computed.
2024ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2025ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    parsePos.setIndex(pos);
2026ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2027ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // This part is a problem:  When we call parsedDate.after, we compute the time.
2028ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Take the date April 3 2004 at 2:30 am.  When this is first set up, the year
2029ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // will be wrong if we're parsing a 2-digit year pattern.  It will be 1904.
2030ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // April 3 1904 is a Sunday (unlike 2004) so it is the DST onset day.  2:30 am
2031ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // is therefore an "impossible" time, since the time goes from 1:59 to 3:00 am
2032ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // on that day.  It is therefore parsed out to fields as 3:30 am.  Then we
2033ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // add 100 years, and get April 3 2004 at 3:30 am.  Note that April 3 2004 is
2034ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // a Saturday, so it can have a 2:30 am -- and it should. [LIU]
2035ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
2036ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UDate parsedDate = calendar.getTime();
2037ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if( ambiguousYear[0] && !parsedDate.after(fDefaultCenturyStart) ) {
2038ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            calendar.add(Calendar.YEAR, 100);
2039ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            parsedDate = calendar.getTime();
2040ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2041ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
2042ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Because of the above condition, save off the fields in case we need to readjust.
2043ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // The procedure we use here is not particularly efficient, but there is no other
2044ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // way to do this given the API restrictions present in Calendar.  We minimize
2045ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // inefficiency by only performing this computation when it might apply, that is,
2046ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // when the two-digit year is equal to the start year, and thus might fall at the
2047ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // front or the back of the default century.  This only works because we adjust
2048ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // the year correctly to start with in other cases -- see subParse().
2049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (ambiguousYear[0] || tztype != TZTYPE_UNK) // If this is true then the two-digit year == the default start year
2050ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
2051ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // We need a copy of the fields, and we need to avoid triggering a call to
2052ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // complete(), which will recalculate the fields.  Since we can't access
2053ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // the fields[] array in Calendar, we clone the entire object.  This will
2054ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // stop working if Calendar.clone() is ever rewritten to call complete().
2055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Calendar *copy;
2056ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (ambiguousYear[0]) {
2057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            copy = cal.clone();
205885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Check for failed cloning.
205985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (copy == NULL) {
2060b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                status = U_MEMORY_ALLOCATION_ERROR;
2061b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                goto ExitParse;
206285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
2063ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UDate parsedDate = copy->getTime(status);
2064ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // {sfb} check internalGetDefaultCenturyStart
2065ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (fHaveDefaultCentury && (parsedDate < fDefaultCenturyStart)) {
2066ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // We can't use add here because that does a complete() first.
2067ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cal.set(UCAL_YEAR, fDefaultCenturyStartYear + 100);
2068ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete copy;
2070ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2071ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (tztype != TZTYPE_UNK) {
2073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            copy = cal.clone();
207485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Check for failed cloning.
207585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (copy == NULL) {
2076b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                status = U_MEMORY_ALLOCATION_ERROR;
2077b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                goto ExitParse;
207885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
2079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const TimeZone & tz = cal.getTimeZone();
2080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            BasicTimeZone *btz = NULL;
2081ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
208227f654740f2a26ad62a5c155af9199af9e69b889claireho            if (dynamic_cast<const OlsonTimeZone *>(&tz) != NULL
208327f654740f2a26ad62a5c155af9199af9e69b889claireho                || dynamic_cast<const SimpleTimeZone *>(&tz) != NULL
208427f654740f2a26ad62a5c155af9199af9e69b889claireho                || dynamic_cast<const RuleBasedTimeZone *>(&tz) != NULL
208527f654740f2a26ad62a5c155af9199af9e69b889claireho                || dynamic_cast<const VTimeZone *>(&tz) != NULL) {
2086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                btz = (BasicTimeZone*)&tz;
2087ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2088ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Get local millis
2090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            copy->set(UCAL_ZONE_OFFSET, 0);
2091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            copy->set(UCAL_DST_OFFSET, 0);
2092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UDate localMillis = copy->getTime(status);
2093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Make sure parsed time zone type (Standard or Daylight)
2095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // matches the rule used by the parsed time zone.
2096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t raw, dst;
2097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (btz != NULL) {
2098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (tztype == TZTYPE_STD) {
2099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    btz->getOffsetFromLocal(localMillis,
2100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        BasicTimeZone::kStandard, BasicTimeZone::kStandard, raw, dst, status);
2101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
2102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    btz->getOffsetFromLocal(localMillis,
2103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        BasicTimeZone::kDaylight, BasicTimeZone::kDaylight, raw, dst, status);
2104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
2106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // No good way to resolve ambiguous time at transition,
2107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // but following code work in most case.
2108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                tz.getOffset(localMillis, TRUE, raw, dst, status);
2109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Now, compare the results with parsed type, either standard or daylight saving time
2112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t resolvedSavings = dst;
2113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (tztype == TZTYPE_STD) {
2114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (dst != 0) {
2115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // Override DST_OFFSET = 0 in the result calendar
2116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    resolvedSavings = 0;
2117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else { // tztype == TZTYPE_DST
2119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (dst == 0) {
2120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (btz != NULL) {
2121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        UDate time = localMillis + raw;
2122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // We use the nearest daylight saving time rule.
2123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        TimeZoneTransition beforeTrs, afterTrs;
2124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        UDate beforeT = time, afterT = time;
2125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        int32_t beforeSav = 0, afterSav = 0;
2126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        UBool beforeTrsAvail, afterTrsAvail;
2127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // Search for DST rule before or on the time
2129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        while (TRUE) {
2130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            beforeTrsAvail = btz->getPreviousTransition(beforeT, TRUE, beforeTrs);
2131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            if (!beforeTrsAvail) {
2132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                break;
2133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            }
2134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            beforeT = beforeTrs.getTime() - 1;
2135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            beforeSav = beforeTrs.getFrom()->getDSTSavings();
2136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            if (beforeSav != 0) {
2137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                break;
2138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            }
2139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
2140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // Search for DST rule after the time
2142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        while (TRUE) {
2143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            afterTrsAvail = btz->getNextTransition(afterT, FALSE, afterTrs);
2144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            if (!afterTrsAvail) {
2145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                break;
2146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            }
2147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            afterT = afterTrs.getTime();
2148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            afterSav = afterTrs.getTo()->getDSTSavings();
2149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            if (afterSav != 0) {
2150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                break;
2151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            }
2152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
2153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if (beforeTrsAvail && afterTrsAvail) {
2155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            if (time - beforeT > afterT - time) {
2156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                resolvedSavings = afterSav;
2157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            } else {
2158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                resolvedSavings = beforeSav;
2159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            }
2160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        } else if (beforeTrsAvail && beforeSav != 0) {
2161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            resolvedSavings = beforeSav;
2162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        } else if (afterTrsAvail && afterSav != 0) {
2163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            resolvedSavings = afterSav;
2164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        } else {
2165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            resolvedSavings = btz->getDSTSavings();
2166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
2167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else {
2168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        resolvedSavings = tz.getDSTSavings();
2169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
2170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (resolvedSavings == 0) {
2171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // final fallback
2172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        resolvedSavings = U_MILLIS_PER_HOUR;
2173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
2174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            cal.set(UCAL_ZONE_OFFSET, raw);
2177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            cal.set(UCAL_DST_OFFSET, resolvedSavings);
2178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete copy;
2179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
218185bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoExitParse:
218285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // Set the parsed result if local calendar is used
218385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // instead of the input calendar
218485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (U_SUCCESS(status) && workCal != &cal) {
218585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        cal.setTimeZone(workCal->getTimeZone());
218685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        cal.setTime(workCal->getTime(status), status);
218785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
218885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
218985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // Restore the original time zone if required
219085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (backupTZ != NULL) {
219185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fCalendar->adoptTimeZone(backupTZ);
219285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
2193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // If any Calendar calls failed, we pretend that we
2195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // couldn't parse the string, when in reality this isn't quite accurate--
2196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // we did parse it; the Calendar calls just failed.
219750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if (U_FAILURE(status)) {
2198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        parsePos.setErrorIndex(pos);
219985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        parsePos.setIndex(start);
2200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate
2204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::parse( const UnicodeString& text,
2205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         ParsePosition& pos) const {
2206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // redefined here because the other parse() function hides this function's
2207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // cunterpart on DateFormat
2208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return DateFormat::parse(text, pos);
2209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate
2212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::parse(const UnicodeString& text, UErrorCode& status) const
2213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // redefined here because the other parse() function hides this function's
2215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // counterpart on DateFormat
2216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return DateFormat::parse(text, status);
2217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
2219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t SimpleDateFormat::matchQuarterString(const UnicodeString& text,
2221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              int32_t start,
2222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UCalendarDateFields field,
2223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              const UnicodeString* data,
2224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              int32_t dataCount,
2225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              Calendar& cal) const
2226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i = 0;
2228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t count = dataCount;
2229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // There may be multiple strings in the data[] array which begin with
2231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // the same prefix (e.g., Cerven and Cervenec (June and July) in Czech).
2232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // We keep track of the longest match, and return that.  Note that this
2233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // unfortunately requires us to test all array elements.
2234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t bestMatchLength = 0, bestMatch = -1;
2235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // {sfb} kludge to support case-insensitive comparison
2237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // {markus 2002oct11} do not just use caseCompareBetween because we do not know
2238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // the length of the match after case folding
2239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // {alan 20040607} don't case change the whole string, since the length
2240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // can change
2241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // TODO we need a case-insensitive startsWith function
2242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString lcase, lcaseText;
2243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    text.extract(start, INT32_MAX, lcaseText);
2244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lcaseText.foldCase();
2245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (; i < count; ++i)
2247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
2248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Always compare if we have no match yet; otherwise only compare
2249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // against potentially better matches (longer strings).
2250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        lcase.fastCopyFrom(data[i]).foldCase();
2252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t length = lcase.length();
225350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (length > bestMatchLength &&
2255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            lcaseText.compareBetween(0, length, lcase, 0, length) == 0)
2256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            bestMatch = i;
2258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            bestMatchLength = length;
2259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (bestMatch >= 0)
2262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
2263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cal.set(field, bestMatch * 3);
2264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Once we have a match, we have to determine the length of the
2266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // original source string.  This will usually be == the length of
2267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // the case folded string, but it may differ (e.g. sharp s).
2268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        lcase.fastCopyFrom(data[bestMatch]).foldCase();
2269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Most of the time, the length will be the same as the length
2271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // of the string from the locale data.  Sometimes it will be
2272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // different, in which case we will have to figure it out by
2273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // adding a character at a time, until we have a match.  We do
2274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // this all in one loop, where we try 'len' first (at index
2275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // i==0).
2276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t len = data[bestMatch].length(); // 99+% of the time
2277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t n = text.length() - start;
2278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (i=0; i<=n; ++i) {
2279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t j=i;
2280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (i == 0) {
2281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                j = len;
2282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if (i == len) {
2283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                continue; // already tried this when i was 0
2284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            text.extract(start, j, lcaseText);
2286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            lcaseText.foldCase();
2287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (lcase == lcaseText) {
2288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return start + j;
2289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
229250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return -start;
2294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
2297b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern,
2298b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                      int32_t &patternOffset,
2299b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                      const UnicodeString &text,
2300b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                      int32_t &textOffset,
2301b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                      UBool lenient)
2302b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho{
2303b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UBool inQuote = FALSE;
2304b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString literal;
2305b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t i = patternOffset;
2306b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2307b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // scan pattern looking for contiguous literal characters
2308b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for ( ; i < pattern.length(); i += 1) {
2309b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UChar ch = pattern.charAt(i);
2310b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2311b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (!inQuote && ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A))) { // unquoted [A-Za-z]
2312b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
2313b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
2314b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2315b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (ch == QUOTE) {
2316b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Match a quote literal ('') inside OR outside of quotes
2317b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if ((i + 1) < pattern.length() && pattern.charAt(i + 1) == QUOTE) {
2318b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                i += 1;
2319b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
2320b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                inQuote = !inQuote;
2321b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                continue;
2322b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
2323b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
2324b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2325b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        literal += ch;
2326b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
2327b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2328b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // at this point, literal contains the literal text
2329b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // and i is the index of the next non-literal pattern character.
2330b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t p;
2331b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t t = textOffset;
2332b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2333b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (lenient) {
2334b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // trim leading, trailing whitespace from
2335b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // the literal text
2336b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        literal.trim();
2337b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2338b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // ignore any leading whitespace in the text
2339b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        while (t < text.length() && u_isWhitespace(text.charAt(t))) {
2340b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            t += 1;
2341b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
2342b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
2343b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2344b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (p = 0; p < literal.length() && t < text.length(); p += 1, t += 1) {
2345b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UBool needWhitespace = FALSE;
2346b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2347b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        while (p < literal.length() && PatternProps::isWhiteSpace(literal.charAt(p))) {
2348b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            needWhitespace = TRUE;
2349b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            p += 1;
2350b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
2351b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2352b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (needWhitespace) {
2353b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t tStart = t;
2354b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2355b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            while (t < text.length()) {
2356b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                UChar tch = text.charAt(t);
2357b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2358b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (!u_isUWhiteSpace(tch) && !PatternProps::isWhiteSpace(tch)) {
2359b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    break;
2360b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
2361b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2362b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                t += 1;
2363b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
2364b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2365b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // TODO: should we require internal spaces
2366b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // in lenient mode? (There won't be any
2367b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // leading or trailing spaces)
2368b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (!lenient && t == tStart) {
2369b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // didn't find matching whitespace:
2370b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // an error in strict mode
2371b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return FALSE;
2372b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
2373b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2374b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // In strict mode, this run of whitespace
2375b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // may have been at the end.
2376b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (p >= literal.length()) {
2377b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;
2378b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
2379b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
2380b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2381b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (t >= text.length() || literal.charAt(p) != text.charAt(t)) {
2382b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Ran out of text, or found a non-matching character:
2383b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // OK in lenient mode, an error in strict mode.
2384b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (lenient) {
2385b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;
2386b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
2387b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2388b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return FALSE;
2389b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
2390b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
2391b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2392b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // At this point if we're in strict mode we have a complete match.
2393b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // If we're in lenient mode we may have a partial match, or no
2394b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // match at all.
2395b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (p <= 0) {
2396b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // no match. Pretend it matched a run of whitespace
2397b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // and ignorables in the text.
2398b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const  UnicodeSet *ignorables = NULL;
2399b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UChar *patternCharPtr = u_strchr(DateFormatSymbols::getPatternUChars(), pattern.charAt(i));
2400b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2401b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (patternCharPtr != NULL) {
2402b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UDateFormatField patternCharIndex = (UDateFormatField) (patternCharPtr - DateFormatSymbols::getPatternUChars());
2403b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2404b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ignorables = SimpleDateFormatStaticSets::getIgnorables(patternCharIndex);
2405b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
2406b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2407b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (t = textOffset; t < text.length(); t += 1) {
2408b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UChar ch = text.charAt(t);
2409b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2410b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (ignorables == NULL || !ignorables->contains(ch)) {
2411b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;
2412b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
2413b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
2414b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
2415b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2416b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // if we get here, we've got a complete match.
2417b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    patternOffset = i - 1;
2418b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    textOffset = t;
2419b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2420b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TRUE;
2421b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
2422b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2423b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//----------------------------------------------------------------------
2424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t SimpleDateFormat::matchString(const UnicodeString& text,
2426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              int32_t start,
2427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UCalendarDateFields field,
2428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              const UnicodeString* data,
2429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              int32_t dataCount,
2430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              Calendar& cal) const
2431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i = 0;
2433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t count = dataCount;
2434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (field == UCAL_DAY_OF_WEEK) i = 1;
2436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // There may be multiple strings in the data[] array which begin with
2438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // the same prefix (e.g., Cerven and Cervenec (June and July) in Czech).
2439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // We keep track of the longest match, and return that.  Note that this
2440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // unfortunately requires us to test all array elements.
2441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t bestMatchLength = 0, bestMatch = -1;
2442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // {sfb} kludge to support case-insensitive comparison
2444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // {markus 2002oct11} do not just use caseCompareBetween because we do not know
2445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // the length of the match after case folding
2446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // {alan 20040607} don't case change the whole string, since the length
2447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // can change
2448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // TODO we need a case-insensitive startsWith function
2449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString lcase, lcaseText;
2450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    text.extract(start, INT32_MAX, lcaseText);
2451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lcaseText.foldCase();
2452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (; i < count; ++i)
2454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
2455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Always compare if we have no match yet; otherwise only compare
2456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // against potentially better matches (longer strings).
2457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        lcase.fastCopyFrom(data[i]).foldCase();
2459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t length = lcase.length();
246050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (length > bestMatchLength &&
2462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            lcaseText.compareBetween(0, length, lcase, 0, length) == 0)
2463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            bestMatch = i;
2465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            bestMatchLength = length;
2466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (bestMatch >= 0)
2469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
247050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        // Adjustment for Hebrew Calendar month Adar II
247150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (!strcmp(cal.getType(),"hebrew") && field==UCAL_MONTH && bestMatch==13) {
247250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            cal.set(field,6);
247350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
247450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else {
247550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            cal.set(field, bestMatch);
247650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
2477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Once we have a match, we have to determine the length of the
2479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // original source string.  This will usually be == the length of
2480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // the case folded string, but it may differ (e.g. sharp s).
2481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        lcase.fastCopyFrom(data[bestMatch]).foldCase();
2482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Most of the time, the length will be the same as the length
2484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // of the string from the locale data.  Sometimes it will be
2485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // different, in which case we will have to figure it out by
2486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // adding a character at a time, until we have a match.  We do
2487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // this all in one loop, where we try 'len' first (at index
2488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // i==0).
2489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t len = data[bestMatch].length(); // 99+% of the time
2490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t n = text.length() - start;
2491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (i=0; i<=n; ++i) {
2492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t j=i;
2493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (i == 0) {
2494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                j = len;
2495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if (i == len) {
2496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                continue; // already tried this when i was 0
2497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            text.extract(start, j, lcaseText);
2499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            lcaseText.foldCase();
2500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (lcase == lcaseText) {
2501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return start + j;
2502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
250550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return -start;
2507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
2510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
2512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::set2DigitYearStart(UDate d, UErrorCode& status)
2513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    parseAmbiguousDatesAsAfter(d, status);
2515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
2518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Private member function that converts the parsed date strings into
2519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * timeFields. Returns -start (for ParsePosition) if failed.
2520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param text the time text to be parsed.
2521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param start where to start parsing.
2522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param ch the pattern character for the date field text to be parsed.
2523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param count the count of a pattern character.
2524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return the new start position if matching succeeded; a negative number
2525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * indicating matching failure, otherwise.
2526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
2527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UChar ch, int32_t count,
252850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                           UBool obeyCount, UBool allowNegative, UBool ambiguousYear[], int32_t& saveHebrewMonth, Calendar& cal,
252985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                           int32_t patLoc) const
2530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Formattable number;
2532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t value = 0;
2533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i;
253427f654740f2a26ad62a5c155af9199af9e69b889claireho    int32_t ps = 0;
2535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ParsePosition pos(0);
253685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDateFormatField patternCharIndex;
253785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    NumberFormat *currentNumberFormat;
2538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString temp;
2539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar *patternCharPtr = u_strchr(DateFormatSymbols::getPatternUChars(), ch);
2540b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UBool lenient = isLenient();
2541b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UBool gotNumber = FALSE;
2542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if defined (U_DEBUG_CAL)
2544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //fprintf(stderr, "%s:%d - [%c]  st=%d \n", __FILE__, __LINE__, (char) ch, start);
2545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
2546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (patternCharPtr == NULL) {
2548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return -start;
2549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    patternCharIndex = (UDateFormatField)(patternCharPtr - DateFormatSymbols::getPatternUChars());
255227f654740f2a26ad62a5c155af9199af9e69b889claireho    currentNumberFormat = getNumberFormatByIndex(patternCharIndex);
2553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UCalendarDateFields field = fgPatternIndexToCalendarField[patternCharIndex];
2554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // If there are any spaces here, skip over them.  If we hit the end
2556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // of the string, then fail.
2557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (;;) {
2558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (start >= text.length()) {
2559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return -start;
2560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar32 c = text.char32At(start);
2562b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (!u_isUWhiteSpace(c) /*||*/ && !PatternProps::isWhiteSpace(c)) {
2563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
2564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        start += UTF_CHAR_LENGTH(c);
2566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pos.setIndex(start);
2568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // We handle a few special cases here where we need to parse
2570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // a number value.  We handle further, more generic cases below.  We need
2571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // to handle some of them here because some fields require extra processing on
2572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // the parsed value.
2573b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (patternCharIndex == UDAT_HOUR_OF_DAY1_FIELD ||                       // k
2574b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        patternCharIndex == UDAT_HOUR_OF_DAY0_FIELD ||                       // H
2575b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        patternCharIndex == UDAT_HOUR1_FIELD ||                              // h
2576b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        patternCharIndex == UDAT_HOUR0_FIELD ||                              // K
2577b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        (patternCharIndex == UDAT_DOW_LOCAL_FIELD && count <= 2) ||          // e
2578b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        (patternCharIndex == UDAT_STANDALONE_DAY_FIELD && count <= 2) ||     // c
2579b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        (patternCharIndex == UDAT_MONTH_FIELD && count <= 2) ||              // M
2580b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        (patternCharIndex == UDAT_STANDALONE_MONTH_FIELD && count <= 2) ||   // L
2581b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        (patternCharIndex == UDAT_QUARTER_FIELD && count <= 2) ||            // Q
2582b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        (patternCharIndex == UDAT_STANDALONE_QUARTER_FIELD && count <= 2) || // q
2583b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        patternCharIndex == UDAT_YEAR_FIELD ||                               // y
2584b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        patternCharIndex == UDAT_YEAR_WOY_FIELD ||                           // Y
2585b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        patternCharIndex == UDAT_FRACTIONAL_SECOND_FIELD)                    // S
2586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
2587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t parseStart = pos.getIndex();
2588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // It would be good to unify this with the obeyCount logic below,
2589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // but that's going to be difficult.
2590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const UnicodeString* src;
2591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (obeyCount) {
2593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((start+count) > text.length()) {
2594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return -start;
2595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            text.extractBetween(0, start + count, temp);
2598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            src = &temp;
2599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
2600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            src = &text;
2601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
260385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        parseInt(*src, number, pos, allowNegative,currentNumberFormat);
2604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
260585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        int32_t txtLoc = pos.getIndex();
2606b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2607b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (txtLoc > parseStart) {
2608b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            value = number.getLong();
2609b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            gotNumber = TRUE;
2610b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2611b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // suffix processing
2612b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (value < 0 ) {
2613b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                txtLoc = checkIntSuffix(text, txtLoc, patLoc+1, TRUE);
2614b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (txtLoc != pos.getIndex()) {
2615b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    value *= -1;
2616b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
2617b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
2618b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            else {
2619b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                txtLoc = checkIntSuffix(text, txtLoc, patLoc+1, FALSE);
262085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
262185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
2622b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (!lenient) {
2623b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // Check the range of the value
2624b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                int32_t bias = gFieldRangeBias[patternCharIndex];
2625b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (bias >= 0 && (value > cal.getMaximum(field) + bias || value < cal.getMinimum(field) + bias)) {
2626b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    return -start;
2627b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
2628b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
2629b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2630b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            pos.setIndex(txtLoc);
2631b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
2632b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
2633b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2634b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Make sure that we got a number if
2635b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // we want one, and didn't get one
2636b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // if we don't want one.
2637b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    switch (patternCharIndex) {
2638b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UDAT_HOUR_OF_DAY1_FIELD:
2639b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UDAT_HOUR_OF_DAY0_FIELD:
2640b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UDAT_HOUR1_FIELD:
2641b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UDAT_HOUR0_FIELD:
2642b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // special range check for hours:
2643b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (value < 0 || value > 24) {
2644b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return -start;
2645b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
2646b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2647b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // fall through to gotNumber check
2648b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2649b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UDAT_YEAR_FIELD:
2650b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UDAT_YEAR_WOY_FIELD:
2651b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UDAT_FRACTIONAL_SECOND_FIELD:
2652b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // these must be a number
2653b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (! gotNumber) {
2654b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return -start;
2655b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
2656b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2657b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
2658b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2659b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        default:
2660b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // we check the rest of the fields below.
2661b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
2662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    switch (patternCharIndex) {
2665ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_ERA_FIELD:
266685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (count == 5) {
266727f654740f2a26ad62a5c155af9199af9e69b889claireho            ps = matchString(text, start, UCAL_ERA, fSymbols->fNarrowEras, fSymbols->fNarrowErasCount, cal);
2668b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if (count == 4) {
266927f654740f2a26ad62a5c155af9199af9e69b889claireho            ps = matchString(text, start, UCAL_ERA, fSymbols->fEraNames, fSymbols->fEraNamesCount, cal);
2670b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
267127f654740f2a26ad62a5c155af9199af9e69b889claireho            ps = matchString(text, start, UCAL_ERA, fSymbols->fEras, fSymbols->fErasCount, cal);
267227f654740f2a26ad62a5c155af9199af9e69b889claireho        }
267327f654740f2a26ad62a5c155af9199af9e69b889claireho
267427f654740f2a26ad62a5c155af9199af9e69b889claireho        // check return position, if it equals -start, then matchString error
267527f654740f2a26ad62a5c155af9199af9e69b889claireho        // special case the return code so we don't necessarily fail out until we
267627f654740f2a26ad62a5c155af9199af9e69b889claireho        // verify no year information also
267727f654740f2a26ad62a5c155af9199af9e69b889claireho        if (ps == -start)
267827f654740f2a26ad62a5c155af9199af9e69b889claireho            ps--;
2679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
268027f654740f2a26ad62a5c155af9199af9e69b889claireho        return ps;
2681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_YEAR_FIELD:
2683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // If there are 3 or more YEAR pattern characters, this indicates
2684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // that the year value is to be treated literally, without any
2685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // two-digit year adjustments (e.g., from "01" to 2001).  Otherwise
2686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // we made adjustments to place the 2-digit year in the proper
2687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // century, for parsed strings from "00" to "99".  Any other string
2688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // is treated literally:  "2250", "-1", "1", "002".
2689b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if ((pos.getIndex() - start) == 2
2690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            && u_isdigit(text.charAt(start))
2691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            && u_isdigit(text.charAt(start+1)))
2692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Assume for example that the defaultCenturyStart is 6/18/1903.
2694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // This means that two-digit years will be forced into the range
2695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // 6/18/1903 to 6/17/2003.  As a result, years 00, 01, and 02
2696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // correspond to 2000, 2001, and 2002.  Years 04, 05, etc. correspond
2697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // to 1904, 1905, etc.  If the year is 03, then it is 2003 if the
2698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // other fields specify a date before 6/18, or 1903 if they specify a
2699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // date afterwards.  As a result, 03 is an ambiguous year.  All other
2700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // two-digit years are unambiguous.
2701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          if(fHaveDefaultCentury) { // check if this formatter even has a pivot year
2702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              int32_t ambiguousTwoDigitYear = fDefaultCenturyStartYear % 100;
2703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              ambiguousYear[0] = (value == ambiguousTwoDigitYear);
2704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              value += (fDefaultCenturyStartYear/100)*100 +
2705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                (value < ambiguousTwoDigitYear ? 100 : 0);
2706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cal.set(UCAL_YEAR, value);
270950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
271050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        // Delayed checking for adjustment of Hebrew month numbers in non-leap years.
271150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (saveHebrewMonth >= 0) {
271250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            HebrewCalendar *hc = (HebrewCalendar*)&cal;
271350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if (!hc->isLeapYear(value) && saveHebrewMonth >= 6) {
271450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho               cal.set(UCAL_MONTH,saveHebrewMonth);
271550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            } else {
271650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho               cal.set(UCAL_MONTH,saveHebrewMonth-1);
271750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
271850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            saveHebrewMonth = -1;
271950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
2720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return pos.getIndex();
2721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_YEAR_WOY_FIELD:
2723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Comment is the same as for UDAT_Year_FIELDs - look above
2724b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if ((pos.getIndex() - start) == 2
2725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            && u_isdigit(text.charAt(start))
2726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            && u_isdigit(text.charAt(start+1))
2727ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            && fHaveDefaultCentury )
2728ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2729ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t ambiguousTwoDigitYear = fDefaultCenturyStartYear % 100;
2730ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ambiguousYear[0] = (value == ambiguousTwoDigitYear);
2731ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            value += (fDefaultCenturyStartYear/100)*100 +
2732ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                (value < ambiguousTwoDigitYear ? 100 : 0);
2733ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2734ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cal.set(UCAL_YEAR_WOY, value);
2735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return pos.getIndex();
2736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_MONTH_FIELD:
2738b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (gotNumber) // i.e., M or MM.
2739ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
274050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            // When parsing month numbers from the Hebrew Calendar, we might need to adjust the month depending on whether
274150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            // or not it was a leap year.  We may or may not yet know what year it is, so might have to delay checking until
274250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            // the year is parsed.
274350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if (!strcmp(cal.getType(),"hebrew")) {
274450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                HebrewCalendar *hc = (HebrewCalendar*)&cal;
274550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                if (cal.isSet(UCAL_YEAR)) {
274650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                   UErrorCode status = U_ZERO_ERROR;
274750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                   if (!hc->isLeapYear(hc->get(UCAL_YEAR,status)) && value >= 6) {
274850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                       cal.set(UCAL_MONTH, value);
274950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                   } else {
275050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                       cal.set(UCAL_MONTH, value - 1);
275150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                   }
275250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                } else {
275350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    saveHebrewMonth = value;
275450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
275550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            } else {
275650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                // Don't want to parse the month if it is a string
275750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                // while pattern uses numeric style: M or MM.
275850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                // [We computed 'value' above.]
275950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                cal.set(UCAL_MONTH, value - 1);
276050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
2761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return pos.getIndex();
2762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
2763ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // count >= 3 // i.e., MMM or MMMM
2764ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Want to be able to parse both short and long forms.
2765ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Try count == 4 first:
2766ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t newStart = 0;
2767ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2768b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if ((newStart = matchString(text, start, UCAL_MONTH, // try MMMM
2769ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                      fSymbols->fMonths, fSymbols->fMonthsCount, cal)) > 0)
2770ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return newStart;
2771b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            else if ((newStart = matchString(text, start, UCAL_MONTH, // try MMM
2772b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                          fSymbols->fShortMonths, fSymbols->fShortMonthsCount, cal)) > 0)
2773b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return newStart;
2774b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            else if (!lenient) // currently we do not try to parse MMMMM: #8860
2775b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return newStart;
2776b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // else we allowing parsing as number, below
2777ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2778b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
2779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2780ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_STANDALONE_MONTH_FIELD:
2781b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (gotNumber) // i.e., L or LL.
2782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Don't want to parse the month if it is a string
2784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // while pattern uses numeric style: M or MM.
2785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // [We computed 'value' above.]
2786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cal.set(UCAL_MONTH, value - 1);
2787ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return pos.getIndex();
2788ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
2789ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // count >= 3 // i.e., LLL or LLLL
2790ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Want to be able to parse both short and long forms.
2791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Try count == 4 first:
2792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t newStart = 0;
2793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((newStart = matchString(text, start, UCAL_MONTH,
2795ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                      fSymbols->fStandaloneMonths, fSymbols->fStandaloneMonthsCount, cal)) > 0)
2796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return newStart;
2797b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            else if ((newStart = matchString(text, start, UCAL_MONTH,
2798b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                          fSymbols->fStandaloneShortMonths, fSymbols->fStandaloneShortMonthsCount, cal)) > 0)
2799b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return newStart;
2800b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            else if (!lenient) // currently we do not try to parse LLLLL: #8860
2801b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return newStart;
2802b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // else we allowing parsing as number, below
2803ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2804b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
2805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_HOUR_OF_DAY1_FIELD:
2807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // [We computed 'value' above.]
280850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (value == cal.getMaximum(UCAL_HOUR_OF_DAY) + 1)
2809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            value = 0;
2810b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2811b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // fall through to set field
2812b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2813b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case UDAT_HOUR_OF_DAY0_FIELD:
2814ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cal.set(UCAL_HOUR_OF_DAY, value);
2815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return pos.getIndex();
2816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_FRACTIONAL_SECOND_FIELD:
2818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Fractional seconds left-justify
2819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        i = pos.getIndex() - start;
2820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (i < 3) {
2821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while (i < 3) {
2822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                value *= 10;
2823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                i++;
2824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
2826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t a = 1;
2827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while (i > 3) {
2828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                a *= 10;
2829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                i--;
2830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            value = (value + (a>>1)) / a;
2832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cal.set(UCAL_MILLISECOND, value);
2834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return pos.getIndex();
2835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
283685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    case UDAT_DOW_LOCAL_FIELD:
2837b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (gotNumber) // i.e., e or ee
283885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {
283985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // [We computed 'value' above.]
284085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            cal.set(UCAL_DOW_LOCAL, value);
284185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return pos.getIndex();
284285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
284385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // else for eee-eeeee fall through to handling of EEE-EEEEE
284485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // fall through, do not break here
2845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_DAY_OF_WEEK_FIELD:
2846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Want to be able to parse both short and long forms.
284885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Try count == 4 (EEEE) first:
2849ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t newStart = 0;
2850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
2851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                      fSymbols->fWeekdays, fSymbols->fWeekdaysCount, cal)) > 0)
2852ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return newStart;
285385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // EEEE failed, now try EEE
285485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            else if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
285585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                   fSymbols->fShortWeekdays, fSymbols->fShortWeekdaysCount, cal)) > 0)
285685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return newStart;
285785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // EEE failed, now try EEEEE
2858b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            else if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
2859b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                   fSymbols->fNarrowWeekdays, fSymbols->fNarrowWeekdaysCount, cal)) > 0)
2860b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return newStart;
2861b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            else if (!lenient || patternCharIndex == UDAT_DAY_OF_WEEK_FIELD)
2862b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return newStart;
2863b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // else we allowing parsing as number, below
2864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2865b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
2866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_STANDALONE_DAY_FIELD:
2868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2869b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (gotNumber) // c or cc
287085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            {
287185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                // [We computed 'value' above.]
287285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                cal.set(UCAL_DOW_LOCAL, value);
287385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return pos.getIndex();
287485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
2875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Want to be able to parse both short and long forms.
287685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Try count == 4 (cccc) first:
2877ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t newStart = 0;
2878ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
2879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                      fSymbols->fStandaloneWeekdays, fSymbols->fStandaloneWeekdaysCount, cal)) > 0)
2880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return newStart;
2881b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            else if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
2882b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                          fSymbols->fStandaloneShortWeekdays, fSymbols->fStandaloneShortWeekdaysCount, cal)) > 0)
2883b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return newStart;
2884b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            else if (!lenient)
2885b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return newStart;
2886b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // else we allowing parsing as number, below
2887ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2888b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
2889ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_AM_PM_FIELD:
2891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return matchString(text, start, UCAL_AM_PM, fSymbols->fAmPms, fSymbols->fAmPmsCount, cal);
2892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_HOUR1_FIELD:
2894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // [We computed 'value' above.]
289550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (value == cal.getLeastMaximum(UCAL_HOUR)+1)
2896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            value = 0;
2897b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2898b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // fall through to set field
2899b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2900b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case UDAT_HOUR0_FIELD:
2901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cal.set(UCAL_HOUR, value);
2902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return pos.getIndex();
2903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_QUARTER_FIELD:
2905b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (gotNumber) // i.e., Q or QQ.
2906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Don't want to parse the month if it is a string
2908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // while pattern uses numeric style: Q or QQ.
2909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // [We computed 'value' above.]
2910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cal.set(UCAL_MONTH, (value - 1) * 3);
2911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return pos.getIndex();
2912ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
2913ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // count >= 3 // i.e., QQQ or QQQQ
2914ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Want to be able to parse both short and long forms.
2915ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Try count == 4 first:
2916ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t newStart = 0;
2917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((newStart = matchQuarterString(text, start, UCAL_MONTH,
2919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                      fSymbols->fQuarters, fSymbols->fQuartersCount, cal)) > 0)
2920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return newStart;
2921b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            else if ((newStart = matchQuarterString(text, start, UCAL_MONTH,
2922b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                          fSymbols->fShortQuarters, fSymbols->fShortQuartersCount, cal)) > 0)
2923b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return newStart;
2924b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            else if (!lenient)
2925b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return newStart;
2926b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // else we allowing parsing as number, below
2927ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2928b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
2929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_STANDALONE_QUARTER_FIELD:
2931b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (gotNumber) // i.e., q or qq.
2932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Don't want to parse the month if it is a string
2934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // while pattern uses numeric style: q or q.
2935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // [We computed 'value' above.]
2936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cal.set(UCAL_MONTH, (value - 1) * 3);
2937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return pos.getIndex();
2938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
2939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // count >= 3 // i.e., qqq or qqqq
2940ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Want to be able to parse both short and long forms.
2941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Try count == 4 first:
2942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t newStart = 0;
2943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((newStart = matchQuarterString(text, start, UCAL_MONTH,
2945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                      fSymbols->fStandaloneQuarters, fSymbols->fStandaloneQuartersCount, cal)) > 0)
2946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return newStart;
2947b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            else if ((newStart = matchQuarterString(text, start, UCAL_MONTH,
2948b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                          fSymbols->fStandaloneShortQuarters, fSymbols->fStandaloneShortQuartersCount, cal)) > 0)
2949b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return newStart;
2950b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            else if (!lenient)
2951b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return newStart;
2952b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // else we allowing parsing as number, below
2953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2954b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
2955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_TIMEZONE_FIELD:
2957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_TIMEZONE_RFC_FIELD:
2958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_TIMEZONE_GENERIC_FIELD:
2959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case UDAT_TIMEZONE_SPECIAL_FIELD:
2960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t offset = 0;
2962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UBool parsed = FALSE;
2963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Step 1
2965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Check if this is a long GMT offset string (either localized or default)
2966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            offset = parseGMT(text, pos);
2967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (pos.getIndex() - start > 0) {
2968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                parsed = TRUE;
2969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (!parsed) {
2971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Step 2
2972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Check if this is an RFC822 time zone offset.
2973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // ICU supports the standard RFC822 format [+|-]HHmm
2974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // and its extended form [+|-]HHmmSS.
2975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                do {
2976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    int32_t sign = 0;
2977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    UChar signChar = text.charAt(start);
2978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (signChar == (UChar)0x002B /* '+' */) {
2979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        sign = 1;
2980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else if (signChar == (UChar)0x002D /* '-' */) {
2981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        sign = -1;
2982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else {
2983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // Not an RFC822 offset string
2984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
2985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
2986ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // Parse digits
2988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    int32_t orgPos = start + 1;
2989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    pos.setIndex(orgPos);
299085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    parseInt(text, number, 6, pos, FALSE,currentNumberFormat);
2991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    int32_t numLen = pos.getIndex() - orgPos;
2992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (numLen <= 0) {
2993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
2994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
2995ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // Followings are possible format (excluding sign char)
2997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // HHmmSS
2998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // HmmSS
2999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // HHmm
3000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // Hmm
3001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // HH
3002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // H
3003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    int32_t val = number.getLong();
3004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    int32_t hour = 0, min = 0, sec = 0;
3005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    switch(numLen) {
3006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case 1: // H
3007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case 2: // HH
3008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        hour = val;
3009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
3010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case 3: // Hmm
3011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case 4: // HHmm
3012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        hour = val / 100;
3013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        min = val % 100;
3014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
3015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case 5: // Hmmss
3016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case 6: // HHmmss
3017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        hour = val / 10000;
3018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        min = (val % 10000) / 100;
3019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        sec = val % 100;
3020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
3021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
3022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (hour > 23 || min > 59 || sec > 59) {
3023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // Invalid value range
3024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
3025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
3026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    offset = (((hour * 60) + min) * 60 + sec) * 1000 * sign;
3027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    parsed = TRUE;
3028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } while (FALSE);
3029ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (!parsed) {
3031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // Failed to parse.  Reset the position.
3032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    pos.setIndex(start);
3033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
3034ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
3035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
3036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (parsed) {
3037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // offset was successfully parsed as either a long GMT string or RFC822 zone offset
3038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // string.  Create normalized zone ID for the offset.
303950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
3040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UnicodeString tzID(gGmt);
3041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                formatRFC822TZ(tzID, offset);
3042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                //TimeZone *customTZ = TimeZone::createTimeZone(tzID);
3043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                TimeZone *customTZ = new SimpleTimeZone(offset, tzID);    // faster than TimeZone::createTimeZone
3044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                cal.adoptTimeZone(customTZ);
3045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
3046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return pos.getIndex();
3047ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
3048ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Step 3
3050b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Is this standalone Localized GMT zero or GMT/UT/UTC?
3051b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t gmtLen = 0;
3052b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (text.compare(start, fSymbols->fGmtZero.length(), fSymbols->fGmtZero) == 0) {
3053b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                gmtLen = fSymbols->fGmtZero.length();
3054b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else if (text.compare(start, kGmtLen, gGmt) == 0) {
3055b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                gmtLen = kGmtLen;
3056b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else if (text.compare(start, kUtcLen, gUtc) == 0) {
3057b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                gmtLen = kUtcLen;
3058b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else if (text.compare(start, kUtLen, gUt) == 0) {
3059b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                gmtLen = kUtLen;
3060b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
3061b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // If we parse the string to the end, we can exit here.
3062b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // If any characters follow, we still need to proceed to the
3063b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // next step. Otherwise, all time zone names starting with GMT/UT/UTC
3064b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // (for example, "UTT") will fail.
3065b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (gmtLen > 0 && ((text.length() - start) == gmtLen)) {
3066b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                TimeZone *tz = TimeZone::createTimeZone(UNICODE_STRING("Etc/GMT", 7));
3067b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                cal.adoptTimeZone(tz);
3068b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return start + gmtLen;
3069b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
3070b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
3071b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Step 4
3072ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // At this point, check for named time zones by looking through
3073b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // the locale data.
3074b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (patternCharIndex != UDAT_TIMEZONE_RFC_FIELD) {
3075b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                UTimeZoneTimeType parsedTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
3076b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                ParsePosition tmpPos(start);
3077b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                UnicodeString parsedID;
3078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
3079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                switch (patternCharIndex) {
3080b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                case UDAT_TIMEZONE_FIELD:
3081b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (count < 4) {
3082b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        tzFormat()->parse(UTZFMT_STYLE_SPECIFIC_SHORT_COMMONLY_USED, text, tmpPos, parsedID, &parsedTimeType);
3083b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    } else {
3084b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        tzFormat()->parse(UTZFMT_STYLE_SPECIFIC_LONG, text, tmpPos, parsedID, &parsedTimeType);
3085b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
3086b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    break;
3087b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                case UDAT_TIMEZONE_GENERIC_FIELD:
3088b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (count < 4) {
3089b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        tzFormat()->parse(UTZFMT_STYLE_GENERIC_SHORT, text, tmpPos, parsedID, &parsedTimeType);
3090b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    } else {
3091b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        tzFormat()->parse(UTZFMT_STYLE_GENERIC_LONG, text, tmpPos, parsedID, &parsedTimeType);
3092b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
3093b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    break;
3094b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                case UDAT_TIMEZONE_SPECIAL_FIELD:
3095b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (count < 4) {
3096b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        tzFormat()->parse(UTZFMT_STYLE_SPECIFIC_SHORT, text, tmpPos, parsedID, &parsedTimeType);
3097b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    } else {
3098b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        tzFormat()->parse(UTZFMT_STYLE_LOCATION, text, tmpPos, parsedID, &parsedTimeType);
3099b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
3100b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    break;
3101b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                default:
3102b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    break;
3103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
3104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (tmpPos.getErrorIndex() < 0) {
3105b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (parsedTimeType == UTZFMT_TIME_TYPE_STANDARD) {
3106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        ((SimpleDateFormat*)this)->tztype = TZTYPE_STD;
3107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    } else if (parsedTimeType == UTZFMT_TIME_TYPE_DAYLIGHT) {
3108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        ((SimpleDateFormat*)this)->tztype = TZTYPE_DST;
3109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
3110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
3111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    UnicodeString current;
3112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    cal.getTimeZone().getID(current);
3113b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (parsedID != current) {
3114b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        TimeZone *tz = TimeZone::createTimeZone(parsedID);
3115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        cal.adoptTimeZone(tz);
3116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
3117b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    return tmpPos.getIndex();
3118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
3119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
3120b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Step 5
3121b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // If we saw standalone GMT zero pattern, then use GMT.
312285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (gmtLen > 0) {
3123b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                TimeZone *tz = TimeZone::createTimeZone(UNICODE_STRING("Etc/GMT", 7));
312485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                cal.adoptTimeZone(tz);
312585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return start + gmtLen;
312685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
312785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
3128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // complete failure
3129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return -start;
3130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
3131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    default:
3133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Handle "generic" fields
3134b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // this is now handled below, outside the switch block
3135b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
3136b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
3137b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Handle "generic" fields:
3138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // switch default case now handled here (outside switch block) to allow
3139b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // parsing of some string fields as digits for lenient case
3140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
3141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t parseStart = pos.getIndex();
3142b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UnicodeString* src;
3143b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (obeyCount) {
3144b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if ((start+count) > text.length()) {
3145b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return -start;
3146b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
3147b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        text.extractBetween(0, start + count, temp);
3148b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        src = &temp;
3149b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
3150b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        src = &text;
3151b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
3152b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    parseInt(*src, number, pos, allowNegative,currentNumberFormat);
3153b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (pos.getIndex() != parseStart) {
3154b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t value = number.getLong();
3155b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
3156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Don't need suffix processing here (as in number processing at the beginning of the function);
3157b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // the new fields being handled as numeric values (month, weekdays, quarters) should not have suffixes.
3158b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
3159b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (!lenient) {
3160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Check the range of the value
3161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t bias = gFieldRangeBias[patternCharIndex];
3162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (bias >= 0 && (value > cal.getMaximum(field) + bias || value < cal.getMinimum(field) + bias)) {
3163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return -start;
3164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
3165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
3166b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
3167b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // For the following, need to repeat some of the "if (gotNumber)" code above:
3168b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // UDAT_[STANDALONE_]MONTH_FIELD, UDAT_DOW_LOCAL_FIELD, UDAT_STANDALONE_DAY_FIELD,
3169b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // UDAT_[STANDALONE_]QUARTER_FIELD
3170b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        switch (patternCharIndex) {
3171b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UDAT_MONTH_FIELD:
3172b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // See notes under UDAT_MONTH_FIELD case above
3173b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (!strcmp(cal.getType(),"hebrew")) {
3174b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                HebrewCalendar *hc = (HebrewCalendar*)&cal;
3175b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (cal.isSet(UCAL_YEAR)) {
3176b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                   UErrorCode status = U_ZERO_ERROR;
3177b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                   if (!hc->isLeapYear(hc->get(UCAL_YEAR,status)) && value >= 6) {
3178b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                       cal.set(UCAL_MONTH, value);
3179b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                   } else {
3180b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                       cal.set(UCAL_MONTH, value - 1);
3181b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                   }
3182b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                } else {
3183b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    saveHebrewMonth = value;
3184b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
3185b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
3186b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                cal.set(UCAL_MONTH, value - 1);
3187b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
3188b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
3189b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UDAT_STANDALONE_MONTH_FIELD:
3190b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            cal.set(UCAL_MONTH, value - 1);
3191b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
3192b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UDAT_DOW_LOCAL_FIELD:
3193b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UDAT_STANDALONE_DAY_FIELD:
3194b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            cal.set(UCAL_DOW_LOCAL, value);
3195b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
3196b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UDAT_QUARTER_FIELD:
3197b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UDAT_STANDALONE_QUARTER_FIELD:
3198b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho             cal.set(UCAL_MONTH, (value - 1) * 3);
3199b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho             break;
3200b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        default:
3201b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            cal.set(field, value);
3202b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
3203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
3204b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return pos.getIndex();
3205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
3206b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return -start;
3207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
3208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
3210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Parse an integer using fNumberFormat.  This method is semantically
3211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * const, but actually may modify fNumberFormat.
3212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
3213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid SimpleDateFormat::parseInt(const UnicodeString& text,
3214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                Formattable& number,
3215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                ParsePosition& pos,
321685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                UBool allowNegative,
321785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                NumberFormat *fmt) const {
321885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    parseInt(text, number, -1, pos, allowNegative,fmt);
3219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
3220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
3221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
3222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Parse an integer using fNumberFormat up to maxDigits.
3223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
3224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid SimpleDateFormat::parseInt(const UnicodeString& text,
3225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                Formattable& number,
3226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                int32_t maxDigits,
3227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                ParsePosition& pos,
322885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                UBool allowNegative,
322985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                NumberFormat *fmt) const {
3230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString oldPrefix;
3231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DecimalFormat* df = NULL;
323227f654740f2a26ad62a5c155af9199af9e69b889claireho    if (!allowNegative && (df = dynamic_cast<DecimalFormat*>(fmt)) != NULL) {
3233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        df->getNegativePrefix(oldPrefix);
3234b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        df->setNegativePrefix(UnicodeString(TRUE, SUPPRESS_NEGATIVE_PREFIX, -1));
3235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
3236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t oldPos = pos.getIndex();
323785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fmt->parse(text, number, pos);
3238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (df != NULL) {
3239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        df->setNegativePrefix(oldPrefix);
3240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
3241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
3242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (maxDigits > 0) {
3243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // adjust the result to fit into
3244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // the maxDigits and move the position back
3245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t nDigits = pos.getIndex() - oldPos;
3246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (nDigits > maxDigits) {
3247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t val = number.getLong();
3248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            nDigits -= maxDigits;
3249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while (nDigits > 0) {
3250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                val /= 10;
3251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                nDigits--;
3252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
3253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pos.setIndex(oldPos + maxDigits);
3254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            number.setLong(val);
3255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
3256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
3257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
3258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
3260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid SimpleDateFormat::translatePattern(const UnicodeString& originalPattern,
3262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                        UnicodeString& translatedPattern,
3263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                        const UnicodeString& from,
3264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                        const UnicodeString& to,
3265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                        UErrorCode& status)
3266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
3267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // run through the pattern and convert any pattern symbols from the version
3268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // in "from" to the corresponding character ion "to".  This code takes
3269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // quoted strings into account (it doesn't try to translate them), and it signals
3270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // an error if a particular "pattern character" doesn't appear in "from".
3271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // Depending on the values of "from" and "to" this can convert from generic
3272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // to localized patterns or localized to generic.
327350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  if (U_FAILURE(status))
3274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return;
327550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
3276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  translatedPattern.remove();
3277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  UBool inQuote = FALSE;
3278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  for (int32_t i = 0; i < originalPattern.length(); ++i) {
3279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar c = originalPattern[i];
3280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (inQuote) {
328150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      if (c == QUOTE)
3282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inQuote = FALSE;
3283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
3284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else {
328550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      if (c == QUOTE)
3286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inQuote = TRUE;
328750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      else if ((c >= 0x0061 /*'a'*/ && c <= 0x007A) /*'z'*/
3288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru           || (c >= 0x0041 /*'A'*/ && c <= 0x005A /*'Z'*/)) {
3289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t ci = from.indexOf(c);
3290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (ci == -1) {
3291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      status = U_INVALID_FORMAT_ERROR;
3292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      return;
3293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
3294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    c = to[ci];
3295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      }
3296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
3297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    translatedPattern += c;
3298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  }
3299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  if (inQuote) {
3300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    status = U_INVALID_FORMAT_ERROR;
3301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return;
3302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  }
3303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
3304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
3306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
3308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::toPattern(UnicodeString& result) const
3309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
3310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result = fPattern;
3311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
3312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
3313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
3315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
3317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::toLocalizedPattern(UnicodeString& result,
3318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                     UErrorCode& status) const
3319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
3320b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    translatePattern(fPattern, result,
3321b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                     UnicodeString(DateFormatSymbols::getPatternUChars()),
3322b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                     fSymbols->fLocalPatternChars, status);
3323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
3324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
3325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
3327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
3329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::applyPattern(const UnicodeString& pattern)
3330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
3331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fPattern = pattern;
3332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
3333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
3335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
3337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::applyLocalizedPattern(const UnicodeString& pattern,
3338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                        UErrorCode &status)
3339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
3340b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    translatePattern(pattern, fPattern,
3341b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                     fSymbols->fLocalPatternChars,
3342b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                     UnicodeString(DateFormatSymbols::getPatternUChars()), status);
3343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
3344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
3346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst DateFormatSymbols*
3348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::getDateFormatSymbols() const
3349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
3350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return fSymbols;
3351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
3352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
3354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
3356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::adoptDateFormatSymbols(DateFormatSymbols* newFormatSymbols)
3357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
3358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete fSymbols;
3359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols = newFormatSymbols;
3360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
3361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
3363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
3364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::setDateFormatSymbols(const DateFormatSymbols& newFormatSymbols)
3365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
3366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete fSymbols;
3367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols = new DateFormatSymbols(newFormatSymbols);
3368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
3369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
3372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid SimpleDateFormat::adoptCalendar(Calendar* calendarToAdopt)
3375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
3376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  UErrorCode status = U_ZERO_ERROR;
3377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  DateFormat::adoptCalendar(calendarToAdopt);
337850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  delete fSymbols;
3379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  fSymbols=NULL;
3380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  initializeSymbols(fLocale, fCalendar, status);  // we need new symbols
3381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  initializeDefaultCentury();  // we need a new century (possibly)
3382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
3383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
338485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
338585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
338685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
338785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
338885bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoUBool
338985bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::isFieldUnitIgnored(UCalendarDateFields field) const {
339085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return isFieldUnitIgnored(fPattern, field);
339185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
339285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
339385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
339485bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoUBool
339550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSimpleDateFormat::isFieldUnitIgnored(const UnicodeString& pattern,
339685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                     UCalendarDateFields field) {
339785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t fieldLevel = fgCalendarFieldToLevel[field];
339885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t level;
339985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UChar ch;
340085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UBool inQuote = FALSE;
340185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UChar prevCh = 0;
340285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t count = 0;
340385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
340485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    for (int32_t i = 0; i < pattern.length(); ++i) {
340585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ch = pattern[i];
340685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (ch != prevCh && count > 0) {
340785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            level = fgPatternCharToLevel[prevCh - PATTERN_CHAR_BASE];
340885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // the larger the level, the smaller the field unit.
340985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if ( fieldLevel <= level ) {
341085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return FALSE;
341185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
341285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            count = 0;
341385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
341485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (ch == QUOTE) {
341585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if ((i+1) < pattern.length() && pattern[i+1] == QUOTE) {
341685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                ++i;
341785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            } else {
341885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                inQuote = ! inQuote;
341985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
342050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
342150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        else if ( ! inQuote && ((ch >= 0x0061 /*'a'*/ && ch <= 0x007A /*'z'*/)
342285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    || (ch >= 0x0041 /*'A'*/ && ch <= 0x005A /*'Z'*/))) {
342385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            prevCh = ch;
342485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ++count;
342585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
342685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
342785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if ( count > 0 ) {
342885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // last item
342985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        level = fgPatternCharToLevel[prevCh - PATTERN_CHAR_BASE];
343085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if ( fieldLevel <= level ) {
343185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return FALSE;
343285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
343385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
343485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return TRUE;
343585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
343685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
343785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
343885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
343985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoconst Locale&
344085bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::getSmpFmtLocale(void) const {
344185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return fLocale;
344285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
344385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
344485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
344585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
344650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoint32_t
344785bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::checkIntSuffix(const UnicodeString& text, int32_t start,
344885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                 int32_t patLoc, UBool isNegative) const {
344985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // local variables
345085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UnicodeString suf;
345185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t patternMatch;
345285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t textPreMatch;
345385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t textPostMatch;
345485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
345585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // check that we are still in range
345685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if ( (start > text.length()) ||
345785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         (start < 0) ||
345885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         (patLoc < 0) ||
345985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         (patLoc > fPattern.length())) {
346085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // out of range, don't advance location in text
346185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return start;
346285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
346385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
346485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // get the suffix
346527f654740f2a26ad62a5c155af9199af9e69b889claireho    DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(fNumberFormat);
346627f654740f2a26ad62a5c155af9199af9e69b889claireho    if (decfmt != NULL) {
346785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (isNegative) {
346827f654740f2a26ad62a5c155af9199af9e69b889claireho            suf = decfmt->getNegativeSuffix(suf);
346985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
347085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        else {
347127f654740f2a26ad62a5c155af9199af9e69b889claireho            suf = decfmt->getPositiveSuffix(suf);
347285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
347385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
347450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
347585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // check for suffix
347685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (suf.length() <= 0) {
347785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return start;
347885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
347985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
348085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // check suffix will be encountered in the pattern
348185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    patternMatch = compareSimpleAffix(suf,fPattern,patLoc);
348285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
348385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // check if a suffix will be encountered in the text
348485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    textPreMatch = compareSimpleAffix(suf,text,start);
348585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
348685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // check if a suffix was encountered in the text
348785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    textPostMatch = compareSimpleAffix(suf,text,start-suf.length());
348885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
348985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // check for suffix match
349085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if ((textPreMatch >= 0) && (patternMatch >= 0) && (textPreMatch == patternMatch)) {
349185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return start;
349285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
349385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    else if ((textPostMatch >= 0) && (patternMatch >= 0) && (textPostMatch == patternMatch)) {
349485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return  start - suf.length();
349585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
349685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
349785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // should not get here
349885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return start;
349985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
350085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
350185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
350285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
350385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoint32_t
350450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSimpleDateFormat::compareSimpleAffix(const UnicodeString& affix,
350550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                   const UnicodeString& input,
350685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   int32_t pos) const {
350785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t start = pos;
350885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    for (int32_t i=0; i<affix.length(); ) {
350985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UChar32 c = affix.char32At(i);
351085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        int32_t len = U16_LENGTH(c);
3511b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (PatternProps::isWhiteSpace(c)) {
351285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // We may have a pattern like: \u200F \u0020
351385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            //        and input text like: \u200F \u0020
3514b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Note that U+200F and U+0020 are Pattern_White_Space but only
351585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // U+0020 is UWhiteSpace.  So we have to first do a direct
3516b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // match of the run of Pattern_White_Space in the pattern,
351785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // then match any extra characters.
351885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UBool literalMatch = FALSE;
351985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            while (pos < input.length() &&
352085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   input.char32At(pos) == c) {
352185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                literalMatch = TRUE;
352285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                i += len;
352385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                pos += len;
352485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (i == affix.length()) {
352585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
352685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
352785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                c = affix.char32At(i);
352885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                len = U16_LENGTH(c);
3529b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (!PatternProps::isWhiteSpace(c)) {
353085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
353185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
353285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
353385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
353485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Advance over run in pattern
3535b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            i = skipPatternWhiteSpace(affix, i);
353685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
353785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Advance over run in input text
353885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Must see at least one white space char in input,
353985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // unless we've already matched some characters literally.
354085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            int32_t s = pos;
354185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            pos = skipUWhiteSpace(input, pos);
354285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (pos == s && !literalMatch) {
354385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return -1;
354485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
354585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
354685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // If we skip UWhiteSpace in the input text, we need to skip it in the pattern.
354785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Otherwise, the previous lines may have skipped over text (such as U+00A0) that
354885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // is also in the affix.
354985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            i = skipUWhiteSpace(affix, i);
355085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else {
355185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (pos < input.length() &&
355285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                input.char32At(pos) == c) {
355385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                i += len;
355485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                pos += len;
355585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            } else {
355685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return -1;
355785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
355885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
355985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
356085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return pos - start;
356185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
356285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
356385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
356485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
356550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoint32_t
3566b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoSimpleDateFormat::skipPatternWhiteSpace(const UnicodeString& text, int32_t pos) const {
3567b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar* s = text.getBuffer();
3568b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return (int32_t)(PatternProps::skipWhiteSpace(s + pos, text.length() - pos) - s);
356985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
357085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
357185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
357285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
357350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoint32_t
357485bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::skipUWhiteSpace(const UnicodeString& text, int32_t pos) const {
357585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    while (pos < text.length()) {
357685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UChar32 c = text.char32At(pos);
357785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (!u_isUWhiteSpace(c)) {
357885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            break;
357985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
358085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pos += U16_LENGTH(c);
358185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
358285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return pos;
358385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
358485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
3585b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//----------------------------------------------------------------------
3586b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
3587b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Lazy TimeZoneFormat instantiation, semantically const.
3588b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneFormat *
3589b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoSimpleDateFormat::tzFormat() const {
3590b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fTimeZoneFormat == NULL) {
3591b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        umtx_lock(&LOCK);
3592b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        {
3593b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (fTimeZoneFormat == NULL) {
3594b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                UErrorCode status = U_ZERO_ERROR;
3595b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                TimeZoneFormat *tzfmt = TimeZoneFormat::createInstance(fLocale, status);
3596b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                U_ASSERT(U_SUCCESS(status));
3597b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
3598b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                const_cast<SimpleDateFormat *>(this)->fTimeZoneFormat = tzfmt;
3599b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
3600b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
3601b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        umtx_unlock(&LOCK);
3602b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
3603b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return fTimeZoneFormat;
3604b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
3605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END
3606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
3608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//eof
3610