smpdtfmt.cpp revision 85bf2e2fbc60a9f938064abc8127d61da7d19882
1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*******************************************************************************
385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho* Copyright (C) 1997-2009, 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"
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ustring.h"
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/basictz.h"
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/simpletz.h"
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/rbtz.h"
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/vtzone.h"
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "olsontz.h"
497c971b21cb09c84a9bd948bdf2918b727d46992cJean-Baptiste Queru#include "../common/util.h"
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "gregoimp.h"
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cstring.h"
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uassert.h"
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "zstrfmt.h"
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "umutex.h"
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <float.h>
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <stdio.h>
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// *****************************************************************************
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// class SimpleDateFormat
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// *****************************************************************************
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
6885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const UChar PATTERN_CHAR_BASE = 0x40;
6985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Last-resort string to use for "GMT" when constructing time zone strings.
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// For time zones that have no names, use strings GMT+minutes and
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// GMT-minutes. For instance, in France the time zone is GMT+60.
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Also accepted are GMT+H:MM or GMT-H:MM.
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gGmt[]      = {0x0047, 0x004D, 0x0054, 0x0000};         // "GMT"
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gGmtPlus[]  = {0x0047, 0x004D, 0x0054, 0x002B, 0x0000}; // "GMT+"
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gGmtMinus[] = {0x0047, 0x004D, 0x0054, 0x002D, 0x0000}; // "GMT-"
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar gDefGmtPat[]       = {0x0047, 0x004D, 0x0054, 0x007B, 0x0030, 0x007D, 0x0000}; /* GMT{0} */
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar gDefGmtNegHmsPat[] = {0x002D, 0x0048, 0x0048, 0x003A, 0x006D, 0x006D, 0x003A, 0x0073, 0x0073, 0x0000}; /* -HH:mm:ss */
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar gDefGmtNegHmPat[]  = {0x002D, 0x0048, 0x0048, 0x003A, 0x006D, 0x006D, 0x0000}; /* -HH:mm */
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar gDefGmtPosHmsPat[] = {0x002B, 0x0048, 0x0048, 0x003A, 0x006D, 0x006D, 0x003A, 0x0073, 0x0073, 0x0000}; /* +HH:mm:ss */
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar gDefGmtPosHmPat[]  = {0x002B, 0x0048, 0x0048, 0x003A, 0x006D, 0x006D, 0x0000}; /* +HH:mm */
8485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const UChar gUt[]       = {0x0055, 0x0054, 0x0000};  // "UT"
8585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const UChar gUtc[]      = {0x0055, 0x0054, 0x0043, 0x0000};  // "UT"
8685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef enum GmtPatSize {
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    kGmtLen = 3,
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    kGmtPatLen = 6,
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    kNegHmsLen = 9,
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    kNegHmLen = 6,
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    kPosHmsLen = 9,
9385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    kPosHmLen = 6,
9485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    kUtLen = 2,
9585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    kUtcLen = 3
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} GmtPatSize;
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
9885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// Stuff needed for numbering system overrides
9985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
10085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hotypedef enum OvrStrType {
10185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    kOvrStrDate = 0,
10285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    kOvrStrTime = 1,
10385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    kOvrStrBoth = 2
10485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} OvrStrType;
10585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
10685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const UDateFormatField kDateFields[] = {
10785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_YEAR_FIELD,
10885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_MONTH_FIELD,
10985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_DATE_FIELD,
11085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_DAY_OF_YEAR_FIELD,
11185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_DAY_OF_WEEK_IN_MONTH_FIELD,
11285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_WEEK_OF_YEAR_FIELD,
11385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_WEEK_OF_MONTH_FIELD,
11485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_YEAR_WOY_FIELD,
11585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_EXTENDED_YEAR_FIELD,
11685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_JULIAN_DAY_FIELD,
11785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_STANDALONE_DAY_FIELD,
11885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_STANDALONE_MONTH_FIELD,
11985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_QUARTER_FIELD,
12085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_STANDALONE_QUARTER_FIELD };
12185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const int8_t kDateFieldsCount = 13;
12285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
12385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const UDateFormatField kTimeFields[] = {
12485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_HOUR_OF_DAY1_FIELD,
12585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_HOUR_OF_DAY1_FIELD,
12685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_MINUTE_FIELD,
12785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_SECOND_FIELD,
12885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_FRACTIONAL_SECOND_FIELD,
12985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_HOUR1_FIELD,
13085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_HOUR0_FIELD,
13185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_MILLISECONDS_IN_DAY_FIELD,
13285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDAT_TIMEZONE_RFC_FIELD };
13385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const int8_t kTimeFieldsCount = 9;
13485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
13585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// This is a pattern-of-last-resort used when we can't load a usable pattern out
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// of a resource.
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gDefaultPattern[] =
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x79, 0x79, 0x79, 0x79, 0x4D, 0x4D, 0x64, 0x64, 0x20, 0x68, 0x68, 0x3A, 0x6D, 0x6D, 0x20, 0x61, 0
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};  /* "yyyyMMdd hh:mm a" */
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// This prefix is designed to NEVER MATCH real text, in order to
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// suppress the parsing of negative numbers.  Adjust as needed (if
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// this becomes valid Unicode).
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar SUPPRESS_NEGATIVE_PREFIX[] = {0xAB00, 0};
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * These are the tags we expect to see in normal resource bundle files associated
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * with a locale.
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char gDateTimePatternsTag[]="DateTimePatterns";
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar gEtcUTC[] = {0x45, 0x74, 0x63, 0x2F, 0x55, 0x54, 0x43, 0x00}; // "Etc/UTC"
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar QUOTE = 0x27; // Single quote
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UMTX LOCK;
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleDateFormat)
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::~SimpleDateFormat()
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete fSymbols;
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fGMTFormatters) {
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (int32_t i = 0; i < kNumGMTFormatters; i++) {
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (fGMTFormatters[i]) {
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                delete fGMTFormatters[i];
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(fGMTFormatters);
17385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
17485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
17585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (fNumberFormatters) {
17685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_free(fNumberFormatters);
17785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
17885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
17985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    while (fOverrideList) {
18085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        NSOverride *cur = fOverrideList;
18185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fOverrideList = cur->next;
18285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        delete cur->nf;
18385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_free(cur);
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::SimpleDateFormat(UErrorCode& status)
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  :   fLocale(Locale::getDefault()),
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      fSymbols(NULL),
19285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho      fGMTFormatters(NULL),
19385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho      fNumberFormatters(NULL),
19485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho      fOverrideList(NULL)
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    construct(kShort, (EStyle) (kShort + kDateOffset), fLocale, status);
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeDefaultCentury();
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   UErrorCode &status)
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru:   fPattern(pattern),
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fLocale(Locale::getDefault()),
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols(NULL),
20785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
20885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
20985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
21185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fDateOverride.setToBogus();
21285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fTimeOverride.setToBogus();
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initialize(fLocale, status);
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeDefaultCentury();
21685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
21785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
21885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
21985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
22085bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
22185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                   const UnicodeString& override,
22285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                   UErrorCode &status)
22385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho:   fPattern(pattern),
22485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fLocale(Locale::getDefault()),
22585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fSymbols(NULL),
22685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
22785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
22885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
22985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho{
23085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fDateOverride.setTo(override);
23185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fTimeOverride.setToBogus();
23285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
23385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    initialize(fLocale, status);
23485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    initializeDefaultCentury();
23585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
23685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    processOverrideString(fLocale,override,kOvrStrBoth,status);
23785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   const Locale& locale,
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   UErrorCode& status)
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru:   fPattern(pattern),
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fLocale(locale),
24785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
24885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
24985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
25185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
25285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fDateOverride.setToBogus();
25385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fTimeOverride.setToBogus();
25485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initialize(fLocale, status);
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeDefaultCentury();
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
26385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                   const UnicodeString& override,
26485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                   const Locale& locale,
26585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                   UErrorCode& status)
26685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho:   fPattern(pattern),
26785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fLocale(locale),
26885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
26985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
27085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
27185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho{
27285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
27385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fDateOverride.setTo(override);
27485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fTimeOverride.setToBogus();
27585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
27685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
27785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    initialize(fLocale, status);
27885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    initializeDefaultCentury();
27985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
28085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    processOverrideString(locale,override,kOvrStrBoth,status);
28185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
28285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
28385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
28485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
28585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
28685bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   DateFormatSymbols* symbolsToAdopt,
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   UErrorCode& status)
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru:   fPattern(pattern),
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fLocale(Locale::getDefault()),
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols(symbolsToAdopt),
29285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
29385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
29485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
29685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
29785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fDateOverride.setToBogus();
29885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fTimeOverride.setToBogus();
29985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeCalendar(NULL,fLocale,status);
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initialize(fLocale, status);
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeDefaultCentury();
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   const DateFormatSymbols& symbols,
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   UErrorCode& status)
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru:   fPattern(pattern),
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fLocale(Locale::getDefault()),
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols(new DateFormatSymbols(symbols)),
31385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
31485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
31585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
31785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
31885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fDateOverride.setToBogus();
31985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fTimeOverride.setToBogus();
32085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeCalendar(NULL, fLocale, status);
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initialize(fLocale, status);
323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeDefaultCentury();
324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Not for public consumption; used by DateFormat
329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::SimpleDateFormat(EStyle timeStyle,
330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   EStyle dateStyle,
331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   const Locale& locale,
332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   UErrorCode& status)
333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru:   fLocale(locale),
334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols(NULL),
33585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
33685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
33785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    construct(timeStyle, dateStyle, fLocale, status);
340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_SUCCESS(status)) {
341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      initializeDefaultCentury();
342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Not for public consumption; used by DateFormat.  This constructor
349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * never fails.  If the resource data is not available, it uses the
350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the last resort symbols.
351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::SimpleDateFormat(const Locale& locale,
353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   UErrorCode& status)
354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru:   fPattern(gDefaultPattern),
355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fLocale(locale),
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols(NULL),
35785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
35885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
35985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) return;
362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeSymbols(fLocale, initializeCalendar(NULL, fLocale, status),status);
363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status))
364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_ZERO_ERROR;
366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete fSymbols;
367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // This constructor doesn't fail; it uses last resort data
368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fSymbols = new DateFormatSymbols(status);
369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* test for NULL */
370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (fSymbols == 0) {
371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            status = U_MEMORY_ALLOCATION_ERROR;
372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return;
373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
37685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fDateOverride.setToBogus();
37785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fTimeOverride.setToBogus();
37885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initialize(fLocale, status);
380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_SUCCESS(status)) {
381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      initializeDefaultCentury();
382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::SimpleDateFormat(const SimpleDateFormat& other)
388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru:   DateFormat(other),
389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols(NULL),
39085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fGMTFormatters(NULL),
39185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fNumberFormatters(NULL),
39285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fOverrideList(NULL)
393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *this = other;
395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat& SimpleDateFormat::operator=(const SimpleDateFormat& other)
400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (this == &other) {
402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return *this;
403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DateFormat::operator=(other);
405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete fSymbols;
407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols = NULL;
408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (other.fSymbols)
410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fSymbols = new DateFormatSymbols(*other.fSymbols);
411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fDefaultCenturyStart         = other.fDefaultCenturyStart;
413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fDefaultCenturyStartYear     = other.fDefaultCenturyStartYear;
414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fHaveDefaultCentury          = other.fHaveDefaultCentury;
415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fPattern = other.fPattern;
417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return *this;
419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruFormat*
424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::clone() const
425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return new SimpleDateFormat(*this);
427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::operator==(const Format& other) const
433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (DateFormat::operator==(other)) {
435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // DateFormat::operator== guarantees following cast is safe
436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        SimpleDateFormat* that = (SimpleDateFormat*)&other;
437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return (fPattern             == that->fPattern &&
438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                fSymbols             != NULL && // Check for pathological object
439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                that->fSymbols       != NULL && // Check for pathological object
440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *fSymbols            == *that->fSymbols &&
441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                fHaveDefaultCentury  == that->fHaveDefaultCentury &&
442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                fDefaultCenturyStart == that->fDefaultCenturyStart);
443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid SimpleDateFormat::construct(EStyle timeStyle,
450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                 EStyle dateStyle,
451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                 const Locale& locale,
452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                 UErrorCode& status)
453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // called by several constructors to load pattern data from the resources
455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) return;
456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // We will need the calendar to know what type of symbols to load.
458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeCalendar(NULL, locale, status);
459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) return;
460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    CalendarData calData(locale, fCalendar?fCalendar->getType():NULL, status);
462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UResourceBundle *dateTimePatterns = calData.getByKey(gDateTimePatternsTag, status);
46385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UResourceBundle *currentBundle;
46485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) return;
466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (ures_getSize(dateTimePatterns) <= kDateTime)
468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_INVALID_FORMAT_ERROR;
470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    setLocaleIDs(ures_getLocaleByType(dateTimePatterns, ULOC_VALID_LOCALE, &status),
474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 ures_getLocaleByType(dateTimePatterns, ULOC_ACTUAL_LOCALE, &status));
475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // create a symbols object from the locale
477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initializeSymbols(locale,fCalendar, status);
478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) return;
479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* test for NULL */
480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fSymbols == 0) {
481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
48585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    const UChar *resStr,*ovrStr;
48685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t resStrLen,ovrStrLen = 0;
48785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fDateOverride.setToBogus();
48885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fTimeOverride.setToBogus();
489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // if the pattern should include both date and time information, use the date/time
491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // pattern string as a guide to tell use how to glue together the appropriate date
492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // and time pattern strings.  The actual gluing-together is handled by a convenience
493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // method on MessageFormat.
494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if ((timeStyle != kNone) && (dateStyle != kNone))
495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Formattable timeDateArray[2];
497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // use Formattable::adoptString() so that we can use fastCopyFrom()
499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // instead of Formattable::setString()'s unaware, safe, deep string clone
500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // see Jitterbug 2296
50185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
50285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        currentBundle = ures_getByIndex(dateTimePatterns, (int32_t)timeStyle, NULL, &status);
50385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
50485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           status = U_INVALID_FORMAT_ERROR;
50585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           return;
50685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
50785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        switch (ures_getType(currentBundle)) {
50885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            case URES_STRING: {
50985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               resStr = ures_getString(currentBundle, &resStrLen, &status);
51085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               break;
51185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
51285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            case URES_ARRAY: {
51385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               resStr = ures_getStringByIndex(currentBundle, 0, &resStrLen, &status);
51485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               ovrStr = ures_getStringByIndex(currentBundle, 1, &ovrStrLen, &status);
51585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               fTimeOverride.setTo(TRUE, ovrStr, ovrStrLen);
51685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               break;
51785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
51885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            default: {
51985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               status = U_INVALID_FORMAT_ERROR;
52085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               ures_close(currentBundle);
52185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               return;
52285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
52385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
52485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ures_close(currentBundle);
52585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
52685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UnicodeString *tempus1 = new UnicodeString(TRUE, resStr, resStrLen);
52785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // NULL pointer check
52885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (tempus1 == NULL) {
52985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            status = U_MEMORY_ALLOCATION_ERROR;
53085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return;
53185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
53285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        timeDateArray[0].adoptString(tempus1);
53385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
53485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        currentBundle = ures_getByIndex(dateTimePatterns, (int32_t)dateStyle, NULL, &status);
53585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
53685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           status = U_INVALID_FORMAT_ERROR;
53785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           return;
53885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
53985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        switch (ures_getType(currentBundle)) {
54085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            case URES_STRING: {
54185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               resStr = ures_getString(currentBundle, &resStrLen, &status);
54285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               break;
54385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
54485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            case URES_ARRAY: {
54585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               resStr = ures_getStringByIndex(currentBundle, 0, &resStrLen, &status);
54685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               ovrStr = ures_getStringByIndex(currentBundle, 1, &ovrStrLen, &status);
54785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               fDateOverride.setTo(TRUE, ovrStr, ovrStrLen);
54885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               break;
54985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
55085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            default: {
55185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               status = U_INVALID_FORMAT_ERROR;
55285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               ures_close(currentBundle);
55385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               return;
55485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
55585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
55685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ures_close(currentBundle);
55785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
55885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UnicodeString *tempus2 = new UnicodeString(TRUE, resStr, resStrLen);
55985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // Null pointer check
56085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (tempus2 == NULL) {
56185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            status = U_MEMORY_ALLOCATION_ERROR;
56285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return;
56385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
56485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        timeDateArray[1].adoptString(tempus2);
565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
56685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        int32_t glueIndex = kDateTime;
56785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        int32_t patternsSize = ures_getSize(dateTimePatterns);
56885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (patternsSize >= (kDateTimeOffset + kShort + 1)) {
56985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Get proper date time format
57085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            glueIndex = (int32_t)(kDateTimeOffset + (dateStyle - kDateOffset));
57185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
57285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
57385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        resStr = ures_getStringByIndex(dateTimePatterns, glueIndex, &resStrLen, &status);
574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        MessageFormat::format(UnicodeString(TRUE, resStr, resStrLen), timeDateArray, 2, fPattern, status);
575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // if the pattern includes just time data or just date date, load the appropriate
577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // pattern string from the resources
578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // setTo() - see DateFormatSymbols::assignArray comments
579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else if (timeStyle != kNone) {
58085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        currentBundle = ures_getByIndex(dateTimePatterns, (int32_t)timeStyle, NULL, &status);
58185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
58285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           status = U_INVALID_FORMAT_ERROR;
58385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           return;
58485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
58585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        switch (ures_getType(currentBundle)) {
58685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            case URES_STRING: {
58785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               resStr = ures_getString(currentBundle, &resStrLen, &status);
58885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               break;
58985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
59085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            case URES_ARRAY: {
59185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               resStr = ures_getStringByIndex(currentBundle, 0, &resStrLen, &status);
59285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               ovrStr = ures_getStringByIndex(currentBundle, 1, &ovrStrLen, &status);
59385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               fDateOverride.setTo(TRUE, ovrStr, ovrStrLen);
59485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               break;
59585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
59685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            default: {
59785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               status = U_INVALID_FORMAT_ERROR;
59885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                ures_close(currentBundle);
59985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               return;
60085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
60185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fPattern.setTo(TRUE, resStr, resStrLen);
60385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ures_close(currentBundle);
604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else if (dateStyle != kNone) {
60685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        currentBundle = ures_getByIndex(dateTimePatterns, (int32_t)dateStyle, NULL, &status);
60785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
60885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           status = U_INVALID_FORMAT_ERROR;
60985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           return;
61085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
61185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        switch (ures_getType(currentBundle)) {
61285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            case URES_STRING: {
61385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               resStr = ures_getString(currentBundle, &resStrLen, &status);
61485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               break;
61585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
61685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            case URES_ARRAY: {
61785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               resStr = ures_getStringByIndex(currentBundle, 0, &resStrLen, &status);
61885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               ovrStr = ures_getStringByIndex(currentBundle, 1, &ovrStrLen, &status);
61985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               fDateOverride.setTo(TRUE, ovrStr, ovrStrLen);
62085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               break;
62185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
62285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            default: {
62385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               status = U_INVALID_FORMAT_ERROR;
62485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               ures_close(currentBundle);
62585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               return;
62685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
62785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fPattern.setTo(TRUE, resStr, resStrLen);
62985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ures_close(currentBundle);
630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // and if it includes _neither_, that's an error
633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else
634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_INVALID_FORMAT_ERROR;
635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // finally, finish initializing by creating a Calendar and a NumberFormat
637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initialize(locale, status);
638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendar*
643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::initializeCalendar(TimeZone* adoptZone, const Locale& locale, UErrorCode& status)
644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
645ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(!U_FAILURE(status)) {
646ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fCalendar = Calendar::createInstance(adoptZone?adoptZone:TimeZone::createDefault(), locale, status);
647ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status) && fCalendar == NULL) {
649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return fCalendar;
652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
653ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::initializeSymbols(const Locale& locale, Calendar* calendar, UErrorCode& status)
656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  if(U_FAILURE(status)) {
658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols = NULL;
659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  } else {
660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // pass in calendar type - use NULL (default) if no calendar set (or err).
661ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols = new DateFormatSymbols(locale, calendar?calendar->getType() :NULL , status);
66285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // Null pointer check
66385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (fSymbols == NULL) {
66485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    	status = U_MEMORY_ALLOCATION_ERROR;
66585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    	return;
66685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  }
668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
671ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::initialize(const Locale& locale,
672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             UErrorCode& status)
673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) return;
675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // We don't need to check that the row count is >= 1, since all 2d arrays have at
677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // least one row
678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fNumberFormat = NumberFormat::createInstance(locale, status);
679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fNumberFormat != NULL && U_SUCCESS(status))
680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // no matter what the locale's default number format looked like, we want
682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // to modify it so that it doesn't use thousands separators, doesn't always
683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // show the decimal point, and recognizes integers only when parsing
684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fNumberFormat->setGroupingUsed(FALSE);
686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (fNumberFormat->getDynamicClassID() == DecimalFormat::getStaticClassID())
687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ((DecimalFormat*)fNumberFormat)->setDecimalSeparatorAlwaysShown(FALSE);
688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fNumberFormat->setParseIntegerOnly(TRUE);
689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fNumberFormat->setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
69085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
69185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        initNumberFormatters(locale,status);
69285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else if (U_SUCCESS(status))
695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_MISSING_RESOURCE_ERROR;
697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Initialize the fields we use to disambiguate ambiguous years. Separate
701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * so we can call it from readObject().
702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid SimpleDateFormat::initializeDefaultCentury()
704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  if(fCalendar) {
706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fHaveDefaultCentury = fCalendar->haveDefaultCentury();
707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(fHaveDefaultCentury) {
708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      fDefaultCenturyStart = fCalendar->defaultCenturyStart();
709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      fDefaultCenturyStartYear = fCalendar->defaultCenturyStartYear();
710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      fDefaultCenturyStart = DBL_MIN;
712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      fDefaultCenturyStartYear = -1;
713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  }
715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Define one-century window into which to disambiguate dates using
718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * two-digit years. Make public in JDK 1.2.
719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid SimpleDateFormat::parseAmbiguousDatesAsAfter(UDate startDate, UErrorCode& status)
721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(status)) {
723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(!fCalendar) {
726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      status = U_ILLEGAL_ARGUMENT_ERROR;
727ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      return;
728ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
729ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
730ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fCalendar->setTime(startDate, status);
731ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_SUCCESS(status)) {
732ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fHaveDefaultCentury = TRUE;
733ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fDefaultCenturyStart = startDate;
734ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fDefaultCenturyStartYear = fCalendar->get(UCAL_YEAR, status);
735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
738ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
739ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
740ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
741ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::format(Calendar& cal, UnicodeString& appendTo, FieldPosition& pos) const
742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
743ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
744ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pos.setBeginIndex(0);
745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pos.setEndIndex(0);
746ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
74785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    Calendar *workCal = &cal;
74885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    TimeZone *backupTZ = NULL;
74985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (&cal != fCalendar && uprv_strcmp(cal.getType(), fCalendar->getType()) != 0) {
75085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // Different calendar type
75185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // We use the time and time zone from the input calendar, but
75285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // do not use the input calendar for field calculation.
75385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UDate t = cal.getTime(status);
75485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fCalendar->setTime(t, status);
75585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        backupTZ = fCalendar->getTimeZone().clone();
75685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fCalendar->setTimeZone(cal.getTimeZone());
75785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        workCal = fCalendar;
75885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
75985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
760ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool inQuote = FALSE;
761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar prevCh = 0;
762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t count = 0;
763ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
764ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // loop through the pattern string character by character
765ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (int32_t i = 0; i < fPattern.length() && U_SUCCESS(status); ++i) {
766ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar ch = fPattern[i];
767ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
768ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Use subFormat() to format a repeated pattern character
769ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // when a different pattern or non-pattern character is seen
770ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (ch != prevCh && count > 0) {
77185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            subFormat(appendTo, prevCh, count, pos, *workCal, status);
772ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            count = 0;
773ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
774ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (ch == QUOTE) {
775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Consecutive single quotes are a single quote literal,
776ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // either outside of quotes or between quotes
777ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((i+1) < fPattern.length() && fPattern[i+1] == QUOTE) {
778ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                appendTo += (UChar)QUOTE;
779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++i;
780ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
781ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                inQuote = ! inQuote;
782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else if ( ! inQuote && ((ch >= 0x0061 /*'a'*/ && ch <= 0x007A /*'z'*/)
785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    || (ch >= 0x0041 /*'A'*/ && ch <= 0x005A /*'Z'*/))) {
786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // ch is a date-time pattern character to be interpreted
787ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // by subFormat(); count the number of times it is repeated
788ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            prevCh = ch;
789ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ++count;
790ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else {
792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Append quoted characters and unquoted non-pattern characters
793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            appendTo += ch;
794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
795ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Format the last item in the pattern, if any
798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (count > 0) {
79985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        subFormat(appendTo, prevCh, count, pos, *workCal, status);
80085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
80185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
80285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (backupTZ != NULL) {
80385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // Restore the original time zone
80485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fCalendar->adoptTimeZone(backupTZ);
805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // and if something failed (e.g., an invalid format character), reset our FieldPosition
808ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // to (0, 0) to show that
809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // {sfb} look at this later- are these being set correctly?
810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
811ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pos.setBeginIndex(0);
812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pos.setEndIndex(0);
813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
814ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return appendTo;
816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::format(const Formattable& obj,
820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         UnicodeString& appendTo,
821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         FieldPosition& pos,
822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         UErrorCode& status) const
823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // this is just here to get around the hiding problem
825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // (the previous format() override would hide the version of
826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // format() on DateFormat that this function correspond to, so we
827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // have to redefine it here)
828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return DateFormat::format(obj, appendTo, pos, status);
829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
83385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/* Map calendar field into calendar field level.
83485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * the larger the level, the smaller the field unit.
83585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * For example, UCAL_ERA level is 0, UCAL_YEAR level is 10,
83685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * UCAL_MONTH level is 20.
83785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * NOTE: if new fields adds in, the table needs to update.
83885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */
83985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoconst int32_t
84085bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::fgCalendarFieldToLevel[] =
84185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho{
84285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*GyM*/ 0, 10, 20,
84385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*wW*/ 20, 30,
84485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*dDEF*/ 30, 20, 30, 30,
84585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*ahHm*/ 40, 50, 50, 60,
84685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*sS..*/ 70, 80,
84785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*z?Y*/ 0, 0, 10,
84885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*eug*/ 30, 10, 0,
84985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*A*/ 40
85085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho};
85185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
85285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
85385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/* Map calendar field LETTER into calendar field level.
85485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * the larger the level, the smaller the field unit.
85585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * NOTE: if new fields adds in, the table needs to update.
85685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */
85785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoconst int32_t
85885bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::fgPatternCharToLevel[] = {
85985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
86085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        -1, 40, -1, -1, 20,  30, 30,  0,  50, -1, -1, 50, 20,  20, -1, -1,
86185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    //   P   Q   R   S   T   U   V   W   X   Y   Z
86285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        -1, 20, -1,  80, -1, -1, 0, 30, -1, 10, 0, -1, -1, -1, -1, -1,
86385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
86485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        -1, 40, -1, 30,  30, 30, -1, 0, 50, -1, -1,  50, -1,  60, -1, -1,
86585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    //   p   q   r   s   t   u   v   w   x   y   z
86685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        -1, 20, -1,  70, -1, 10, 0, 20, -1,  10, 0, -1, -1, -1, -1, -1
86785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho};
86885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
86985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Map index into pattern character string to Calendar field number.
871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst UCalendarDateFields
872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::fgPatternIndexToCalendarField[] =
873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*GyM*/ UCAL_ERA, UCAL_YEAR, UCAL_MONTH,
875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*dkH*/ UCAL_DATE, UCAL_HOUR_OF_DAY, UCAL_HOUR_OF_DAY,
876ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*msS*/ UCAL_MINUTE, UCAL_SECOND, UCAL_MILLISECOND,
877ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*EDF*/ UCAL_DAY_OF_WEEK, UCAL_DAY_OF_YEAR, UCAL_DAY_OF_WEEK_IN_MONTH,
878ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*wWa*/ UCAL_WEEK_OF_YEAR, UCAL_WEEK_OF_MONTH, UCAL_AM_PM,
879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*hKz*/ UCAL_HOUR, UCAL_HOUR, UCAL_ZONE_OFFSET,
880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*Yeu*/ UCAL_YEAR_WOY, UCAL_DOW_LOCAL, UCAL_EXTENDED_YEAR,
881ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*gAZ*/ UCAL_JULIAN_DAY, UCAL_MILLISECONDS_IN_DAY, UCAL_ZONE_OFFSET,
882ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*v*/   UCAL_ZONE_OFFSET,
88385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*c*/   UCAL_DOW_LOCAL,
884ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*L*/   UCAL_MONTH,
885ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*Q*/   UCAL_MONTH,
886ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*q*/   UCAL_MONTH,
887ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*V*/   UCAL_ZONE_OFFSET,
888ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
889ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Map index into pattern character string to DateFormat field number
891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst UDateFormatField
892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::fgPatternIndexToDateFormatField[] = {
893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*GyM*/ UDAT_ERA_FIELD, UDAT_YEAR_FIELD, UDAT_MONTH_FIELD,
894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*dkH*/ UDAT_DATE_FIELD, UDAT_HOUR_OF_DAY1_FIELD, UDAT_HOUR_OF_DAY0_FIELD,
895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*msS*/ UDAT_MINUTE_FIELD, UDAT_SECOND_FIELD, UDAT_FRACTIONAL_SECOND_FIELD,
896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*EDF*/ UDAT_DAY_OF_WEEK_FIELD, UDAT_DAY_OF_YEAR_FIELD, UDAT_DAY_OF_WEEK_IN_MONTH_FIELD,
897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*wWa*/ UDAT_WEEK_OF_YEAR_FIELD, UDAT_WEEK_OF_MONTH_FIELD, UDAT_AM_PM_FIELD,
898ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*hKz*/ UDAT_HOUR1_FIELD, UDAT_HOUR0_FIELD, UDAT_TIMEZONE_FIELD,
899ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*Yeu*/ UDAT_YEAR_WOY_FIELD, UDAT_DOW_LOCAL_FIELD, UDAT_EXTENDED_YEAR_FIELD,
900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*gAZ*/ UDAT_JULIAN_DAY_FIELD, UDAT_MILLISECONDS_IN_DAY_FIELD, UDAT_TIMEZONE_RFC_FIELD,
901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*v*/   UDAT_TIMEZONE_GENERIC_FIELD,
902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*c*/   UDAT_STANDALONE_DAY_FIELD,
903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*L*/   UDAT_STANDALONE_MONTH_FIELD,
904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*Q*/   UDAT_QUARTER_FIELD,
905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*q*/   UDAT_STANDALONE_QUARTER_FIELD,
906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*V*/   UDAT_TIMEZONE_SPECIAL_FIELD,
907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
912ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Append symbols[value] to dst.  Make sure the array index is not out
913ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * of bounds.
914ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
915ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic inline void
916ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru_appendSymbol(UnicodeString& dst,
917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              int32_t value,
918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              const UnicodeString* symbols,
919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              int32_t symbolsCount) {
920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    U_ASSERT(0 <= value && value < symbolsCount);
921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (0 <= value && value < symbolsCount) {
922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        dst += symbols[value];
923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//---------------------------------------------------------------------
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
92885bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::appendGMT(NumberFormat *currentNumberFormat,UnicodeString &appendTo, Calendar& cal, UErrorCode& status) const{
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offset = cal.get(UCAL_ZONE_OFFSET, status) + cal.get(UCAL_DST_OFFSET, status);
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (isDefaultGMTFormat()) {
93485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        formatGMTDefault(currentNumberFormat,appendTo, offset);
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ((SimpleDateFormat*)this)->initGMTFormatters(status);
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_SUCCESS(status)) {
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t type;
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (offset < 0) {
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                offset = -offset;
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                type = (offset % U_MILLIS_PER_MINUTE) == 0 ? kGMTNegativeHM : kGMTNegativeHMS;
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                type = (offset % U_MILLIS_PER_MINUTE) == 0 ? kGMTPositiveHM : kGMTPositiveHMS;
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            Formattable param(offset, Formattable::kIsDate);
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            FieldPosition fpos(0);
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fGMTFormatters[type]->format(&param, 1, appendTo, fpos, status);
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleDateFormat::parseGMT(const UnicodeString &text, ParsePosition &pos) const {
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (!isDefaultGMTFormat()) {
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t start = pos.getIndex();
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Quick check
958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UBool prefixMatch = FALSE;
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t prefixLen = fSymbols->fGmtFormat.indexOf((UChar)0x007B /* '{' */);
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (prefixLen > 0 && text.compare(start, prefixLen, fSymbols->fGmtFormat, 0, prefixLen) == 0) {
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            prefixMatch = TRUE;
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (prefixMatch) {
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Prefix matched
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UErrorCode status = U_ZERO_ERROR;
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ((SimpleDateFormat*)this)->initGMTFormatters(status);
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_SUCCESS(status)) {
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                Formattable parsed;
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                int32_t parsedCount;
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Try negative Hms
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fGMTFormatters[kGMTNegativeHMS]->parseObject(text, parsed, pos);
97385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (pos.getErrorIndex() == -1 &&
97485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    (pos.getIndex() - start) >= fGMTFormatHmsMinLen[kGMTNegativeHMSMinLenIdx]) {
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    parsed.getArray(parsedCount);
976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (parsedCount == 1 && parsed[0].getType() == Formattable::kDate) {
97785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        return (int32_t)(-1 * (int64_t)parsed[0].getDate());
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Reset ParsePosition
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setIndex(start);
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setErrorIndex(-1);
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Try positive Hms
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fGMTFormatters[kGMTPositiveHMS]->parseObject(text, parsed, pos);
98785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (pos.getErrorIndex() == -1 &&
98885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    (pos.getIndex() - start) >= fGMTFormatHmsMinLen[kGMTPositiveHMSMinLenIdx]) {
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    parsed.getArray(parsedCount);
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (parsedCount == 1 && parsed[0].getType() == Formattable::kDate) {
99185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        return (int32_t)((int64_t)parsed[0].getDate());
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Reset ParsePosition
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setIndex(start);
997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setErrorIndex(-1);
998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Try negative Hm
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fGMTFormatters[kGMTNegativeHM]->parseObject(text, parsed, pos);
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (pos.getErrorIndex() == -1 && pos.getIndex() > start) {
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    parsed.getArray(parsedCount);
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (parsedCount == 1 && parsed[0].getType() == Formattable::kDate) {
100485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        return (int32_t)(-1 * (int64_t)parsed[0].getDate());
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Reset ParsePosition
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setIndex(start);
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setErrorIndex(-1);
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Try positive Hm
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fGMTFormatters[kGMTPositiveHM]->parseObject(text, parsed, pos);
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (pos.getErrorIndex() == -1 && pos.getIndex() > start) {
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    parsed.getArray(parsedCount);
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (parsedCount == 1 && parsed[0].getType() == Formattable::kDate) {
101785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        return (int32_t)((int64_t)parsed[0].getDate());
1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Reset ParsePosition
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setIndex(start);
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setErrorIndex(-1);
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // fall through to the default GMT parsing method
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return parseGMTDefault(text, pos);
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1030ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
103285bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::formatGMTDefault(NumberFormat *currentNumberFormat,UnicodeString &appendTo, int32_t offset) const {
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (offset < 0) {
1034ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        appendTo += gGmtMinus;
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset = -offset; // suppress the '-' sign for text display.
1036ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }else{
1037ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        appendTo += gGmtPlus;
1038ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1039ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    offset /= U_MILLIS_PER_SECOND; // now in seconds
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t sec = offset % 60;
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    offset /= 60;
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t min = offset % 60;
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t hour = offset / 60;
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
104785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    zeroPaddingNumber(currentNumberFormat,appendTo, hour, 2, 2);
1048ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    appendTo += (UChar)0x003A /*':'*/;
104985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    zeroPaddingNumber(currentNumberFormat,appendTo, min, 2, 2);
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (sec != 0) {
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        appendTo += (UChar)0x003A /*':'*/;
105285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        zeroPaddingNumber(currentNumberFormat,appendTo, sec, 2, 2);
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleDateFormat::parseGMTDefault(const UnicodeString &text, ParsePosition &pos) const {
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t start = pos.getIndex();
105985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    NumberFormat *currentNumberFormat = getNumberFormat(UDAT_TIMEZONE_RFC_FIELD);
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
106185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (start + kUtLen + 1 >= text.length()) {
1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos.setErrorIndex(start);
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t cur = start;
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // "GMT"
106885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (text.compare(start, kGmtLen, gGmt) == 0) {
106985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        cur += kGmtLen;
107085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    } else if (text.compare(start, kUtLen, gUt) == 0) {
107185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        cur += kUtLen;
107285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    } else {
1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos.setErrorIndex(start);
1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Sign
1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool negative = FALSE;
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (text.charAt(cur) == (UChar)0x002D /* minus */) {
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        negative = TRUE;
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (text.charAt(cur) != (UChar)0x002B /* plus */) {
1081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos.setErrorIndex(cur);
1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cur++;
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Numbers
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t numLen;
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pos.setIndex(cur);
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Formattable number;
109185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    parseInt(text, number, 6, pos, FALSE,currentNumberFormat);
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    numLen = pos.getIndex() - cur;
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (numLen <= 0) {
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos.setIndex(start);
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos.setErrorIndex(cur);
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t numVal = number.getLong();
1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t hour = 0;
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t min = 0;
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t sec = 0;
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (numLen <= 2) {
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // H[H][:mm[:ss]]
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        hour = numVal;
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        cur += numLen;
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (cur + 2 < text.length() && text.charAt(cur) == (UChar)0x003A /* colon */) {
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            cur++;
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pos.setIndex(cur);
111385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            parseInt(text, number, 2, pos, FALSE,currentNumberFormat);
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            numLen = pos.getIndex() - cur;
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (numLen == 2) {
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // got minute field
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                min = number.getLong();
1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                cur += numLen;
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (cur + 2 < text.length() && text.charAt(cur) == (UChar)0x003A /* colon */) {
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    cur++;
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    pos.setIndex(cur);
112285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    parseInt(text, number, 2, pos, FALSE,currentNumberFormat);
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    numLen = pos.getIndex() - cur;
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (numLen == 2) {
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // got second field
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        sec = number.getLong();
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else {
1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // reset position
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        pos.setIndex(cur - 1);
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        pos.setErrorIndex(-1);
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // reset postion
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setIndex(cur - 1);
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setErrorIndex(-1);
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (numLen == 3 || numLen == 4) {
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Hmm or HHmm
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        hour = numVal / 100;
1142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        min = numVal % 100;
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (numLen == 5 || numLen == 6) {
1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Hmmss or HHmmss
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        hour = numVal / 10000;
1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        min = (numVal % 10000) / 100;
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        sec = numVal % 100;
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // HHmmss followed by bogus numbers
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos.setIndex(cur + 6);
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t shift = numLen - 6;
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (shift > 0) {
1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            numVal /= 10;
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            shift--;
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        hour = numVal / 10000;
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        min = (numVal % 10000) / 100;
1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        sec = numVal % 100;
1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offset = ((hour*60 + min)*60 + sec)*1000;
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (negative) {
1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset = -offset;
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return offset;
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleDateFormat::isDefaultGMTFormat() const {
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // GMT pattern
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fSymbols->fGmtFormat.length() == 0) {
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // No GMT pattern is set
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (fSymbols->fGmtFormat.compare(gDefGmtPat, kGmtPatLen) != 0) {
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Hour patterns
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fSymbols->fGmtHourFormats == NULL || fSymbols->fGmtHourFormatsCount != DateFormatSymbols::GMT_HOUR_COUNT) {
1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // No Hour pattern is set
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if ((fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_NEGATIVE_HMS].compare(gDefGmtNegHmsPat, kNegHmsLen) != 0)
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || (fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_NEGATIVE_HM].compare(gDefGmtNegHmPat, kNegHmLen) != 0)
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || (fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_POSITIVE_HMS].compare(gDefGmtPosHmsPat, kPosHmsLen) != 0)
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || (fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_POSITIVE_HM].compare(gDefGmtPosHmPat, kPosHmLen) != 0)) {
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleDateFormat::formatRFC822TZ(UnicodeString &appendTo, int32_t offset) const {
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar sign = 0x002B /* '+' */;
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (offset < 0) {
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset = -offset;
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        sign = 0x002D /* '-' */;
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    appendTo.append(sign);
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offsetH = offset / U_MILLIS_PER_HOUR;
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    offset = offset % U_MILLIS_PER_HOUR;
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offsetM = offset / U_MILLIS_PER_MINUTE;
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    offset = offset % U_MILLIS_PER_MINUTE;
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offsetS = offset / U_MILLIS_PER_SECOND;
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t num = 0, denom = 0;
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (offsetS == 0) {
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset = offsetH*100 + offsetM; // HHmm
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        num = offset % 10000;
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        denom = 1000;
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        offset = offsetH*10000 + offsetM*100 + offsetS; // HHmmss
1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        num = offset % 1000000;
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        denom = 100000;
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (denom >= 1) {
1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UChar digit = (UChar)0x0030 + (num / denom);
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        appendTo.append(digit);
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        num = num % denom;
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        denom /= 10;
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleDateFormat::initGMTFormatters(UErrorCode &status) {
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_lock(&LOCK);
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fGMTFormatters == NULL) {
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fGMTFormatters = (MessageFormat**)uprv_malloc(kNumGMTFormatters * sizeof(MessageFormat*));
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (fGMTFormatters) {
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for (int32_t i = 0; i < kNumGMTFormatters; i++) {
123485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                const UnicodeString *hourPattern = NULL; //initialized it to avoid warning
1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                switch (i) {
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case kGMTNegativeHMS:
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        hourPattern = &(fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_NEGATIVE_HMS]);
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case kGMTNegativeHM:
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        hourPattern = &(fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_NEGATIVE_HM]);
1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case kGMTPositiveHMS:
1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        hourPattern = &(fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_POSITIVE_HMS]);
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case kGMTPositiveHM:
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        hourPattern = &(fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_POSITIVE_HM]);
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fGMTFormatters[i] = new MessageFormat(fSymbols->fGmtFormat, status);
125085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                GregorianCalendar *gcal = new GregorianCalendar(TimeZone::createTimeZone(UnicodeString(gEtcUTC)), status);
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (U_FAILURE(status)) {
1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
1253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                SimpleDateFormat *sdf = (SimpleDateFormat*)this->clone();
125585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                sdf->adoptCalendar(gcal);
1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                sdf->applyPattern(*hourPattern);
1257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fGMTFormatters[i]->adoptFormat(0, sdf);
125885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
125985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                // For parsing, we only allow Hms patterns to be equal or longer
126085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                // than its length with fixed minutes/seconds digits.
126185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                // See #6880
126285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (i == kGMTNegativeHMS || i == kGMTPositiveHMS) {
126385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    UnicodeString tmp;
126485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    Formattable tmpParam(60*60*1000, Formattable::kIsDate);
126585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    FieldPosition fpos(0);
126685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    fGMTFormatters[i]->format(&tmpParam, 1, tmp, fpos, status);
126785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    if (U_FAILURE(status)) {
126885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        break;
126985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    }
127085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    if (i == kGMTNegativeHMS) {
127185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        fGMTFormatHmsMinLen[kGMTNegativeHMSMinLenIdx] = tmp.length();
127285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    } else {
127385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        fGMTFormatHmsMinLen[kGMTPositiveHMSMinLenIdx] = tmp.length();
127485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    }
127585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            status = U_MEMORY_ALLOCATION_ERROR;
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_unlock(&LOCK);
1282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
128485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hovoid
128585bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::initNumberFormatters(const Locale &locale,UErrorCode &status) {
128685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (U_FAILURE(status)) {
128785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return;
128885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
128985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if ( fDateOverride.isBogus() && fTimeOverride.isBogus() ) {
129085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return;
129185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
129285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    umtx_lock(&LOCK);
129385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (fNumberFormatters == NULL) {
129485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fNumberFormatters = (NumberFormat**)uprv_malloc(UDAT_FIELD_COUNT * sizeof(NumberFormat*));
129585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (fNumberFormatters) {
129685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            for (int32_t i = 0; i < UDAT_FIELD_COUNT; i++) {
129785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                fNumberFormatters[i] = fNumberFormat;
129885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
129985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else {
130085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            status = U_MEMORY_ALLOCATION_ERROR;
130185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
130285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
130385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    umtx_unlock(&LOCK);
130485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
130585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    processOverrideString(locale,fDateOverride,kOvrStrDate,status);
130685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    processOverrideString(locale,fTimeOverride,kOvrStrTime,status);
130785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
130885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
130985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
131085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hovoid
131185bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::processOverrideString(const Locale &locale, const UnicodeString &str, int8_t type, UErrorCode &status) {
131285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (str.isBogus()) {
131385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return;
131485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
131585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t start = 0;
131685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t len;
131785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UnicodeString nsName;
131885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UnicodeString ovrField;
131985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UBool moreToProcess = TRUE;
132085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
132185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    while (moreToProcess) {
132285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        int32_t delimiterPosition = str.indexOf((UChar)ULOC_KEYWORD_ITEM_SEPARATOR,start);
132385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (delimiterPosition == -1) {
132485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            moreToProcess = FALSE;
132585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            len = str.length() - start;
132685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else {
132785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            len = delimiterPosition - start;
132885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
132985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UnicodeString currentString(str,start,len);
133085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        int32_t equalSignPosition = currentString.indexOf((UChar)ULOC_KEYWORD_ASSIGN,0);
133185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (equalSignPosition == -1) { // Simple override string such as "hebrew"
133285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            nsName.setTo(currentString);
133385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ovrField.setToBogus();
133485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else { // Field specific override string such as "y=hebrew"
133585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            nsName.setTo(currentString,equalSignPosition+1);
133685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ovrField.setTo(currentString,0,1); // We just need the first character.
133785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
133885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
133985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        int32_t nsNameHash = nsName.hashCode();
134085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // See if the numbering system is in the override list, if not, then add it.
134185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        NSOverride *cur = fOverrideList;
134285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        NumberFormat *nf = NULL;
134385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UBool found = FALSE;
134485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        while ( cur && !found ) {
134585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if ( cur->hash == nsNameHash ) {
134685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                nf = cur->nf;
134785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                found = TRUE;
134885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
134985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            cur = cur->next;
135085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
135185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
135285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (!found) {
135385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           cur = (NSOverride *)uprv_malloc(sizeof(NSOverride));
135485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           if (cur) {
135585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               char kw[ULOC_KEYWORD_AND_VALUES_CAPACITY];
135685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               uprv_strcpy(kw,"numbers=");
135785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               nsName.extract(0,len,kw+8,ULOC_KEYWORD_AND_VALUES_CAPACITY-8,US_INV);
135885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
135985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               Locale ovrLoc(locale.getLanguage(),locale.getCountry(),locale.getVariant(),kw);
136085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               nf = NumberFormat::createInstance(ovrLoc,status);
136185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
136285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               // no matter what the locale's default number format looked like, we want
136385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               // to modify it so that it doesn't use thousands separators, doesn't always
136485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               // show the decimal point, and recognizes integers only when parsing
136585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
136685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               if (U_SUCCESS(status)) {
136785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   nf->setGroupingUsed(FALSE);
136885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   if (nf->getDynamicClassID() == DecimalFormat::getStaticClassID())
136985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                       ((DecimalFormat*)nf)->setDecimalSeparatorAlwaysShown(FALSE);
137085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   nf->setParseIntegerOnly(TRUE);
137185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   nf->setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
137285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
137385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   cur->nf = nf;
137485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   cur->hash = nsNameHash;
137585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   cur->next = fOverrideList;
137685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   fOverrideList = cur;
137785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               }
137885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               else {
137985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   // clean up before returning
138085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   if (cur != NULL) {
138185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                       uprv_free(cur);
138285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   }
138385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                  return;
138485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               }
138585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
138685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           } else {
138785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               status = U_MEMORY_ALLOCATION_ERROR;
138885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               return;
138985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           }
139085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
139185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
139285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // Now that we have an appropriate number formatter, fill in the appropriate spaces in the
139385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // number formatters table.
139485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
139585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (ovrField.isBogus()) {
139685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            switch (type) {
139785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case kOvrStrDate:
139885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case kOvrStrBoth: {
139985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    for ( int8_t i=0 ; i<kDateFieldsCount; i++ ) {
140085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        fNumberFormatters[kDateFields[i]] = nf;
140185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    }
140285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    if (type==kOvrStrDate) {
140385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        break;
140485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    }
140585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
140685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case kOvrStrTime : {
140785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    for ( int8_t i=0 ; i<kTimeFieldsCount; i++ ) {
140885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        fNumberFormatters[kTimeFields[i]] = nf;
140985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    }
141085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
141185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
141285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
141385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else {
141485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           UChar ch = ovrField.charAt(0);
141585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           UChar *patternCharPtr = u_strchr(DateFormatSymbols::getPatternUChars(), ch);
141685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           UDateFormatField patternCharIndex;
141785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
141885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           // if the pattern character is unrecognized, signal an error and bail out
141985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           if (patternCharPtr == NULL) {
142085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               status = U_INVALID_FORMAT_ERROR;
142185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho               return;
142285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           }
142385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           patternCharIndex = (UDateFormatField)(patternCharPtr - DateFormatSymbols::getPatternUChars());
142485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
142585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           // Set the number formatter in the table
142685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           fNumberFormatters[patternCharIndex] = nf;
142785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
142885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
142985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        start = delimiterPosition + 1;
143085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
143185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
1432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//---------------------------------------------------------------------
1433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::subFormat(UnicodeString &appendTo,
1435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            UChar ch,
1436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            int32_t count,
1437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            FieldPosition& pos,
1438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            Calendar& cal,
1439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            UErrorCode& status) const
1440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
1442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // this function gets called by format() to produce the appropriate substitution
1446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // text for an individual pattern symbol (e.g., "HH" or "yyyy")
1447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar *patternCharPtr = u_strchr(DateFormatSymbols::getPatternUChars(), ch);
1449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UDateFormatField patternCharIndex;
1450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const int32_t maxIntCount = 10;
1451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t beginOffset = appendTo.length();
145285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    NumberFormat *currentNumberFormat;
1453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // if the pattern character is unrecognized, signal an error and dump out
1455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (patternCharPtr == NULL)
1456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
1457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_INVALID_FORMAT_ERROR;
1458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    patternCharIndex = (UDateFormatField)(patternCharPtr - DateFormatSymbols::getPatternUChars());
1462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UCalendarDateFields field = fgPatternIndexToCalendarField[patternCharIndex];
1463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t value = cal.get(field, status);
1464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
1465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
146885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    currentNumberFormat = getNumberFormat(patternCharIndex);
1469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    switch (patternCharIndex) {
1470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for any "G" symbol, write out the appropriate era string
147285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // "GGGG" is wide era name, "GGGGG" is narrow era name, anything else is abbreviated name
1473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_ERA_FIELD:
147485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (count == 5)
147585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           _appendSymbol(appendTo, value, fSymbols->fNarrowEras, fSymbols->fNarrowErasCount);
147685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        else if (count == 4)
1477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru           _appendSymbol(appendTo, value, fSymbols->fEraNames, fSymbols->fEraNamesCount);
1478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else
1479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru           _appendSymbol(appendTo, value, fSymbols->fEras, fSymbols->fErasCount);
1480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
148285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // OLD: for "yyyy", write out the whole year; for "yy", write out the last 2 digits
148385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // NEW: UTS#35:
148485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//Year  	y  	yy  	yyy  	yyyy  	yyyyy
148585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//AD 1 	1 	01 	001 	0001 	00001
148685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//AD 12 	12 	12 	012 	0012 	00012
148785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//AD 123 	123 	23 	123 	0123 	00123
148885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//AD 1234 	1234 	34 	1234 	1234 	01234
148985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//AD 12345 	12345 	45 	12345 	12345 	12345
1490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_YEAR_FIELD:
1491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_YEAR_WOY_FIELD:
149285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(count == 2)
149385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, value, 2, 2);
149485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        else
149585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, value, count, maxIntCount);
149685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        break;
1497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "MMMM", write out the whole month name, for "MMM", write out the month
1499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // abbreviation, for "M" or "MM", write out the month as a number with the
1500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // appropriate number of digits
1501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "MMMMM", use the narrow form
1502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_MONTH_FIELD:
1503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (count == 5)
1504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fNarrowMonths,
1505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fNarrowMonthsCount);
1506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else if (count == 4)
1507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fMonths,
1508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fMonthsCount);
1509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else if (count == 3)
1510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fShortMonths,
1511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fShortMonthsCount);
1512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else
151385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, value + 1, count, maxIntCount);
1514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "LLLL", write out the whole month name, for "LLL", write out the month
1517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // abbreviation, for "L" or "LL", write out the month as a number with the
1518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // appropriate number of digits
1519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "LLLLL", use the narrow form
1520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_STANDALONE_MONTH_FIELD:
1521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (count == 5)
1522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fStandaloneNarrowMonths,
1523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fStandaloneNarrowMonthsCount);
1524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else if (count == 4)
1525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fStandaloneMonths,
1526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fStandaloneMonthsCount);
1527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else if (count == 3)
1528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fStandaloneShortMonths,
1529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fStandaloneShortMonthsCount);
1530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else
153185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, value + 1, count, maxIntCount);
1532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "k" and "kk", write out the hour, adjusting midnight to appear as "24"
1535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_HOUR_OF_DAY1_FIELD:
1536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (value == 0)
153785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, cal.getMaximum(UCAL_HOUR_OF_DAY) + 1, count, maxIntCount);
1538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else
153985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, value, count, maxIntCount);
1540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_FRACTIONAL_SECOND_FIELD:
1543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Fractional seconds left-justify
1544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
154585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            currentNumberFormat->setMinimumIntegerDigits((count > 3) ? 3 : count);
154685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            currentNumberFormat->setMaximumIntegerDigits(maxIntCount);
1547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (count == 1) {
1548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                value = (value + 50) / 100;
1549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if (count == 2) {
1550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                value = (value + 5) / 10;
1551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            FieldPosition p(0);
155385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            currentNumberFormat->format(value, appendTo, p);
1554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (count > 3) {
155585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                currentNumberFormat->setMinimumIntegerDigits(count - 3);
155685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                currentNumberFormat->format((int32_t)0, appendTo, p);
1557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
156185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // for "ee" or "e", use local numeric day-of-the-week
156285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // for "EEEEE" or "eeeee", write out the narrow day-of-the-week name
156385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // for "EEEE" or "eeee", write out the wide day-of-the-week name
156485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // for "EEE" or "EE" or "E" or "eee", write out the abbreviated day-of-the-week name
156585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    case UDAT_DOW_LOCAL_FIELD:
156685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if ( count < 3 ) {
156785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, value, count, maxIntCount);
156885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            break;
156985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
157085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // fall through to EEEEE-EEE handling, but for that we don't want local day-of-week,
157185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // we want standard day-of-week, so first fix value to work for EEEEE-EEE.
157285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        value = cal.get(UCAL_DAY_OF_WEEK, status);
157385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
157485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return;
157585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
157685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // fall through, do not break here
1577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_DAY_OF_WEEK_FIELD:
1578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (count == 5)
1579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fNarrowWeekdays,
1580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fNarrowWeekdaysCount);
1581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else if (count == 4)
1582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fWeekdays,
1583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fWeekdaysCount);
1584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else
1585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fShortWeekdays,
1586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fShortWeekdaysCount);
1587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "ccc", write out the abbreviated day-of-the-week name
1590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "cccc", write out the wide day-of-the-week name
1591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "ccccc", use the narrow day-of-the-week name
1592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_STANDALONE_DAY_FIELD:
159385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if ( count < 3 ) {
159485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, value, 1, maxIntCount);
159585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            break;
159685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
159785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // fall through to alpha DOW handling, but for that we don't want local day-of-week,
159885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // we want standard day-of-week, so first fix value.
159985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        value = cal.get(UCAL_DAY_OF_WEEK, status);
160085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
160185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return;
160285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
1603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (count == 5)
1604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fStandaloneNarrowWeekdays,
1605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fStandaloneNarrowWeekdaysCount);
1606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else if (count == 4)
1607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fStandaloneWeekdays,
1608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fStandaloneWeekdaysCount);
160985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        else // count == 3
1610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value, fSymbols->fStandaloneShortWeekdays,
1611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fStandaloneShortWeekdaysCount);
1612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for and "a" symbol, write out the whole AM/PM string
1615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_AM_PM_FIELD:
1616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        _appendSymbol(appendTo, value, fSymbols->fAmPms,
1617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                      fSymbols->fAmPmsCount);
1618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for "h" and "hh", write out the hour, adjusting noon and midnight to show up
1621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // as "12"
1622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_HOUR1_FIELD:
1623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (value == 0)
162485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, cal.getLeastMaximum(UCAL_HOUR) + 1, count, maxIntCount);
1625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else
162685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, value, count, maxIntCount);
1627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for the "z" symbols, we have to check our time zone data first.  If we have a
1630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // localized name for the time zone, then "zzzz" / "zzz" indicate whether
1631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // daylight time is in effect (long/short) and "zz" / "z" do not (long/short).
1632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // If we don't have a localized time zone name,
1633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // then the time zone shows up as "GMT+hh:mm" or "GMT-hh:mm" (where "hh:mm" is the
1634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // offset from GMT) regardless of how many z's were in the pattern symbol
1635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_TIMEZONE_FIELD:
1636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case UDAT_TIMEZONE_GENERIC_FIELD:
1637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_TIMEZONE_SPECIAL_FIELD:
1638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UnicodeString zoneString;
1640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const ZoneStringFormat *zsf = fSymbols->getZoneStringFormat();
1641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (zsf) {
1642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (patternCharIndex == UDAT_TIMEZONE_FIELD) {
1643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (count < 4) {
1644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // "z", "zz", "zzz"
1645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        zsf->getSpecificShortString(cal, TRUE /*commonly used only*/,
1646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            zoneString, status);
1647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else {
1648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // "zzzz"
1649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        zsf->getSpecificLongString(cal, zoneString, status);
1650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else if (patternCharIndex == UDAT_TIMEZONE_GENERIC_FIELD) {
1652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (count == 1) {
1653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // "v"
1654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        zsf->getGenericShortString(cal, TRUE /*commonly used only*/,
1655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            zoneString, status);
1656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else if (count == 4) {
1657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // "vvvv"
1658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        zsf->getGenericLongString(cal, zoneString, status);
1659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else { // patternCharIndex == UDAT_TIMEZONE_SPECIAL_FIELD
1661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (count == 1) {
1662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // "V"
1663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        zsf->getSpecificShortString(cal, FALSE /*ignore commonly used*/,
1664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            zoneString, status);
1665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else if (count == 4) {
1666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // "VVVV"
1667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        zsf->getGenericLocationString(cal, zoneString, status);
1668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (zoneString.isEmpty()) {
167285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                appendGMT(currentNumberFormat,appendTo, cal, status);
1673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
1674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                appendTo += zoneString;
1675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
1678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case UDAT_TIMEZONE_RFC_FIELD: // 'Z' - TIMEZONE_RFC
1680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (count < 4) {
1681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // RFC822 format, must use ASCII digits
1682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            value = (cal.get(UCAL_ZONE_OFFSET, status) + cal.get(UCAL_DST_OFFSET, status));
1683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            formatRFC822TZ(appendTo, value);
1684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // long form, localized GMT pattern
168685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            appendGMT(currentNumberFormat,appendTo, cal, status);
1687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_QUARTER_FIELD:
1691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (count >= 4)
1692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value/3, fSymbols->fQuarters,
1693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fQuartersCount);
1694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else if (count == 3)
1695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value/3, fSymbols->fShortQuarters,
1696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fShortQuartersCount);
1697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else
169885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, (value/3) + 1, count, maxIntCount);
1699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_STANDALONE_QUARTER_FIELD:
1702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (count >= 4)
1703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value/3, fSymbols->fStandaloneQuarters,
1704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fStandaloneQuartersCount);
1705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else if (count == 3)
1706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _appendSymbol(appendTo, value/3, fSymbols->fStandaloneShortQuarters,
1707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          fSymbols->fStandaloneShortQuartersCount);
1708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else
170985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            zeroPaddingNumber(currentNumberFormat,appendTo, (value/3) + 1, count, maxIntCount);
1710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // all of the other pattern symbols can be formatted as simple numbers with
1714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // appropriate zero padding
1715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    default:
171685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        zeroPaddingNumber(currentNumberFormat,appendTo, value, count, maxIntCount);
1717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // if the field we're formatting is the one the FieldPosition says it's interested
1721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // in, fill in the FieldPosition with this field's positions
1722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (pos.getBeginIndex() == pos.getEndIndex() &&
1723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pos.getField() == fgPatternIndexToDateFormatField[patternCharIndex]) {
1724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pos.setBeginIndex(beginOffset);
1725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pos.setEndIndex(appendTo.length());
1726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1727ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
172885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
172985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
173085bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoNumberFormat *
173185bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::getNumberFormat(UDateFormatField index) const {
173285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (fNumberFormatters != NULL) {
173385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return fNumberFormatters[index];
173485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    } else {
173585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return fNumberFormat;
173685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
173785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
1738ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1739ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
1740ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
174185bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::zeroPaddingNumber(NumberFormat *currentNumberFormat,UnicodeString &appendTo, int32_t value, int32_t minDigits, int32_t maxDigits) const
1742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
174385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (currentNumberFormat!=NULL) {
174485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        FieldPosition pos(0);
1745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
174685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        currentNumberFormat->setMinimumIntegerDigits(minDigits);
174785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        currentNumberFormat->setMaximumIntegerDigits(maxDigits);
174885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        currentNumberFormat->format(value, appendTo, pos);  // 3rd arg is there to speed up processing
174985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
1750ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1751ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1752ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
1753ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1754ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
1755ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Format characters that indicate numeric fields.  The character
1756ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * at index 0 is treated specially.
1757ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
175885bf2e2fbc60a9f938064abc8127d61da7d19882Claire 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" */
1759ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1760ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
1761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Return true if the given format character, occuring count
1762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * times, represents a numeric field.
1763ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
1764ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool SimpleDateFormat::isNumeric(UChar formatChar, int32_t count) {
1765ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString s(NUMERIC_FORMAT_CHARS);
1766ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i = s.indexOf(formatChar);
1767ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (i > 0 || (i == 0 && count < 3));
1768ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1769ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1770ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1771ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition& parsePos) const
1772ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
177385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UErrorCode status = U_ZERO_ERROR;
1774ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t pos = parsePos.getIndex();
1775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t start = pos;
177685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
1777ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool ambiguousYear[] = { FALSE };
1778ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t count = 0;
1779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // hack, reset tztype, cast away const
1781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ((SimpleDateFormat*)this)->tztype = TZTYPE_UNK;
1782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // For parsing abutting numeric fields. 'abutPat' is the
1784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // offset into 'pattern' of the first of 2 or more abutting
1785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // numeric fields.  'abutStart' is the offset into 'text'
1786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // where parsing the fields begins. 'abutPass' starts off as 0
1787ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // and increments each time we try to parse the fields.
1788ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t abutPat = -1; // If >=0, we are in a run of abutting numeric fields
1789ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t abutStart = 0;
1790ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t abutPass = 0;
1791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool inQuote = FALSE;
1792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UnicodeString numericFormatChars(NUMERIC_FORMAT_CHARS);
1794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
179585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    TimeZone *backupTZ = NULL;
179685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    Calendar *workCal = &cal;
179785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (&cal != fCalendar && uprv_strcmp(cal.getType(), fCalendar->getType()) != 0) {
179885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // Different calendar type
179985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // We use the time/zone from the input calendar, but
180085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // do not use the input calendar for field calculation.
180185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fCalendar->setTime(cal.getTime(status),status);
180285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
180385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            goto ExitParse;
180485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
180585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        backupTZ = fCalendar->getTimeZone().clone();
180685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fCalendar->setTimeZone(cal.getTimeZone());
180785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        workCal = fCalendar;
180885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
180985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
1810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (int32_t i=0; i<fPattern.length(); ++i) {
1811ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar ch = fPattern.charAt(i);
1812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Handle alphabetic field characters.
1814ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (!inQuote && ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A))) { // [A-Za-z]
1815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t fieldPat = i;
1816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Count the length of this field specifier
1818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            count = 1;
1819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while ((i+1)<fPattern.length() &&
1820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                   fPattern.charAt(i+1) == ch) {
1821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++count;
1822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++i;
1823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (isNumeric(ch, count)) {
1826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (abutPat < 0) {
1827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // Determine if there is an abutting numeric field.  For
1828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // most fields we can just look at the next characters,
1829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // but the 'm' field is either numeric or text,
1830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // depending on the count, so we have to look ahead for
1831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // that field.
1832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if ((i+1)<fPattern.length()) {
1833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        UBool abutting;
1834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        UChar nextCh = fPattern.charAt(i+1);
1835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        int32_t k = numericFormatChars.indexOf(nextCh);
1836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        if (k == 0) {
1837ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            int32_t j = i+2;
1838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            while (j<fPattern.length() &&
1839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   fPattern.charAt(j) == nextCh) {
1840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                ++j;
1841ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            }
1842ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            abutting = (j-i) < 4; // nextCount < 3
1843ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        } else {
1844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            abutting = k > 0;
1845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        }
1846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        // Record the start of a set of abutting numeric
1848ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        // fields.
1849ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        if (abutting) {
1850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            abutPat = fieldPat;
1851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            abutStart = pos;
1852ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            abutPass = 0;
1853ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        }
1854ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1855ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1856ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
1857ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                abutPat = -1; // End of any abutting fields
1858ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1859ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1860ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Handle fields within a run of abutting numeric fields.  Take
1861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // the pattern "HHmmss" as an example. We will try to parse
1862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // 2/2/2 characters of the input text, then if that fails,
1863ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // 1/2/2.  We only adjust the width of the leftmost field; the
1864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // others remain fixed.  This allows "123456" => 12:34:56, but
1865ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // "12345" => 1:23:45.  Likewise, for the pattern "yyyyMMdd" we
1866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // try 4/2/2, 3/2/2, 2/2/2, and finally 1/2/2.
1867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (abutPat >= 0) {
1868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // If we are at the start of a run of abutting fields, then
1869ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // shorten this field in each pass.  If we can't shorten
1870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // this field any more, then the parse of this set of
1871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // abutting numeric fields has failed.
1872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (fieldPat == abutPat) {
1873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    count -= abutPass++;
1874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (count == 0) {
187585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        status = U_PARSE_ERROR;
187685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        goto ExitParse;
1877ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1878ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                pos = subParse(text, pos, ch, count,
188185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                               TRUE, FALSE, ambiguousYear, *workCal, i);
1882ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1883ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // If the parse fails anywhere in the run, back up to the
1884ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // start of the run and retry.
1885ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (pos < 0) {
1886ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    i = abutPat - 1;
1887ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    pos = abutStart;
1888ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    continue;
1889ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Handle non-numeric fields and non-abutting numeric
1893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // fields.
1894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            else {
189585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                int32_t s = subParse(text, pos, ch, count,
189685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                               FALSE, TRUE, ambiguousYear, *workCal, i);
1897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
189885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (s < 0) {
189985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    status = U_PARSE_ERROR;
190085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    goto ExitParse;
1901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
190285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                pos = s;
1903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Handle literal pattern characters.  These are any
1907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // quoted characters and non-alphabetic unquoted
1908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // characters.
1909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else {
1910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            abutPat = -1; // End of any abutting fields
1912ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1913ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Handle quotes.  Two consecutive quotes is a quote
1914ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // literal, inside or outside of quotes.  Otherwise a
1915ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // quote indicates entry or exit from a quoted region.
1916ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (ch == QUOTE) {
1917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // Match a quote literal '' within OR outside of quotes
1918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if ((i+1)<fPattern.length() && fPattern.charAt(i+1)==ch) {
1919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    ++i; // Skip over doubled quote
1920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // Fall through and treat quote as a literal
1921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
1922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // Enter or exit quoted region
1923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    inQuote = !inQuote;
1924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    continue;
1925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1927ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1928ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // A run of white space in the pattern matches a run
1929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // of white space in the input text.
1930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (uprv_isRuleWhiteSpace(ch)) {
1931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // Advance over run in pattern
1932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                while ((i+1)<fPattern.length() &&
1933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       uprv_isRuleWhiteSpace(fPattern.charAt(i+1))) {
1934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    ++i;
1935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // Advance over run in input text
1938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                int32_t s = pos;
1939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                while (pos<text.length() &&
1940ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       ( u_isUWhiteSpace(text.charAt(pos)) || uprv_isRuleWhiteSpace(text.charAt(pos)))) {
1941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    ++pos;
1942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // Must see at least one white space char in input
1945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (pos > s) {
1946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    continue;
1947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if (pos<text.length() && text.charAt(pos)==ch) {
1949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // Match a literal
1950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++pos;
1951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                continue;
1952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // We fall through to this point if the match fails
195585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            status = U_PARSE_ERROR;
195685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            goto ExitParse;
1957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // At this point the fields of Calendar have been set.  Calendar
1961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // will fill in default values for missing fields when the time
1962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // is computed.
1963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    parsePos.setIndex(pos);
1965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // This part is a problem:  When we call parsedDate.after, we compute the time.
1967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Take the date April 3 2004 at 2:30 am.  When this is first set up, the year
1968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // will be wrong if we're parsing a 2-digit year pattern.  It will be 1904.
1969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // April 3 1904 is a Sunday (unlike 2004) so it is the DST onset day.  2:30 am
1970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // is therefore an "impossible" time, since the time goes from 1:59 to 3:00 am
1971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // on that day.  It is therefore parsed out to fields as 3:30 am.  Then we
1972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // add 100 years, and get April 3 2004 at 3:30 am.  Note that April 3 2004 is
1973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // a Saturday, so it can have a 2:30 am -- and it should. [LIU]
1974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
1975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UDate parsedDate = calendar.getTime();
1976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if( ambiguousYear[0] && !parsedDate.after(fDefaultCenturyStart) ) {
1977ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            calendar.add(Calendar.YEAR, 100);
1978ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            parsedDate = calendar.getTime();
1979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1980ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
1981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Because of the above condition, save off the fields in case we need to readjust.
1982ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // The procedure we use here is not particularly efficient, but there is no other
1983ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // way to do this given the API restrictions present in Calendar.  We minimize
1984ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // inefficiency by only performing this computation when it might apply, that is,
1985ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // when the two-digit year is equal to the start year, and thus might fall at the
1986ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // front or the back of the default century.  This only works because we adjust
1987ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // the year correctly to start with in other cases -- see subParse().
1988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (ambiguousYear[0] || tztype != TZTYPE_UNK) // If this is true then the two-digit year == the default start year
1989ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
1990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // We need a copy of the fields, and we need to avoid triggering a call to
1991ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // complete(), which will recalculate the fields.  Since we can't access
1992ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // the fields[] array in Calendar, we clone the entire object.  This will
1993ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // stop working if Calendar.clone() is ever rewritten to call complete().
1994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Calendar *copy;
1995ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (ambiguousYear[0]) {
1996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            copy = cal.clone();
199785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Check for failed cloning.
199885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (copy == NULL) {
199985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            	status = U_MEMORY_ALLOCATION_ERROR;
200085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            	goto ExitParse;
200185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
2002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UDate parsedDate = copy->getTime(status);
2003ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // {sfb} check internalGetDefaultCenturyStart
2004ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (fHaveDefaultCentury && (parsedDate < fDefaultCenturyStart)) {
2005ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // We can't use add here because that does a complete() first.
2006ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cal.set(UCAL_YEAR, fDefaultCenturyStartYear + 100);
2007ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete copy;
2009ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2010ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (tztype != TZTYPE_UNK) {
2012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            copy = cal.clone();
201385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Check for failed cloning.
201485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (copy == NULL) {
201585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            	status = U_MEMORY_ALLOCATION_ERROR;
201685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            	goto ExitParse;
201785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
2018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const TimeZone & tz = cal.getTimeZone();
2019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            BasicTimeZone *btz = NULL;
2020ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (tz.getDynamicClassID() == OlsonTimeZone::getStaticClassID()
2022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                || tz.getDynamicClassID() == SimpleTimeZone::getStaticClassID()
2023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                || tz.getDynamicClassID() == RuleBasedTimeZone::getStaticClassID()
2024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                || tz.getDynamicClassID() == VTimeZone::getStaticClassID()) {
2025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                btz = (BasicTimeZone*)&tz;
2026ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2027ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Get local millis
2029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            copy->set(UCAL_ZONE_OFFSET, 0);
2030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            copy->set(UCAL_DST_OFFSET, 0);
2031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UDate localMillis = copy->getTime(status);
2032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Make sure parsed time zone type (Standard or Daylight)
2034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // matches the rule used by the parsed time zone.
2035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t raw, dst;
2036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (btz != NULL) {
2037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (tztype == TZTYPE_STD) {
2038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    btz->getOffsetFromLocal(localMillis,
2039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        BasicTimeZone::kStandard, BasicTimeZone::kStandard, raw, dst, status);
2040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
2041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    btz->getOffsetFromLocal(localMillis,
2042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        BasicTimeZone::kDaylight, BasicTimeZone::kDaylight, raw, dst, status);
2043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
2045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // No good way to resolve ambiguous time at transition,
2046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // but following code work in most case.
2047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                tz.getOffset(localMillis, TRUE, raw, dst, status);
2048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Now, compare the results with parsed type, either standard or daylight saving time
2051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t resolvedSavings = dst;
2052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (tztype == TZTYPE_STD) {
2053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (dst != 0) {
2054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // Override DST_OFFSET = 0 in the result calendar
2055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    resolvedSavings = 0;
2056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else { // tztype == TZTYPE_DST
2058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (dst == 0) {
2059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (btz != NULL) {
2060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        UDate time = localMillis + raw;
2061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // We use the nearest daylight saving time rule.
2062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        TimeZoneTransition beforeTrs, afterTrs;
2063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        UDate beforeT = time, afterT = time;
2064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        int32_t beforeSav = 0, afterSav = 0;
2065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        UBool beforeTrsAvail, afterTrsAvail;
2066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // Search for DST rule before or on the time
2068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        while (TRUE) {
2069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            beforeTrsAvail = btz->getPreviousTransition(beforeT, TRUE, beforeTrs);
2070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            if (!beforeTrsAvail) {
2071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                break;
2072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            }
2073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            beforeT = beforeTrs.getTime() - 1;
2074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            beforeSav = beforeTrs.getFrom()->getDSTSavings();
2075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            if (beforeSav != 0) {
2076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                break;
2077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            }
2078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
2079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // Search for DST rule after the time
2081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        while (TRUE) {
2082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            afterTrsAvail = btz->getNextTransition(afterT, FALSE, afterTrs);
2083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            if (!afterTrsAvail) {
2084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                break;
2085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            }
2086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            afterT = afterTrs.getTime();
2087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            afterSav = afterTrs.getTo()->getDSTSavings();
2088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            if (afterSav != 0) {
2089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                break;
2090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            }
2091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
2092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if (beforeTrsAvail && afterTrsAvail) {
2094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            if (time - beforeT > afterT - time) {
2095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                resolvedSavings = afterSav;
2096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            } else {
2097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                resolvedSavings = beforeSav;
2098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            }
2099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        } else if (beforeTrsAvail && beforeSav != 0) {
2100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            resolvedSavings = beforeSav;
2101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        } else if (afterTrsAvail && afterSav != 0) {
2102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            resolvedSavings = afterSav;
2103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        } else {
2104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            resolvedSavings = btz->getDSTSavings();
2105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
2106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else {
2107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        resolvedSavings = tz.getDSTSavings();
2108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
2109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (resolvedSavings == 0) {
2110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // final fallback
2111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        resolvedSavings = U_MILLIS_PER_HOUR;
2112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
2113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            cal.set(UCAL_ZONE_OFFSET, raw);
2116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            cal.set(UCAL_DST_OFFSET, resolvedSavings);
2117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete copy;
2118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
212085bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoExitParse:
212185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // Set the parsed result if local calendar is used
212285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // instead of the input calendar
212385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (U_SUCCESS(status) && workCal != &cal) {
212485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        cal.setTimeZone(workCal->getTimeZone());
212585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        cal.setTime(workCal->getTime(status), status);
212685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
212785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
212885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // Restore the original time zone if required
212985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (backupTZ != NULL) {
213085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fCalendar->adoptTimeZone(backupTZ);
213185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
2132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // If any Calendar calls failed, we pretend that we
2134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // couldn't parse the string, when in reality this isn't quite accurate--
2135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // we did parse it; the Calendar calls just failed.
2136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
2137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        parsePos.setErrorIndex(pos);
213885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        parsePos.setIndex(start);
2139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate
2143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::parse( const UnicodeString& text,
2144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         ParsePosition& pos) const {
2145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // redefined here because the other parse() function hides this function's
2146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // cunterpart on DateFormat
2147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return DateFormat::parse(text, pos);
2148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate
2151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::parse(const UnicodeString& text, UErrorCode& status) const
2152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // redefined here because the other parse() function hides this function's
2154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // counterpart on DateFormat
2155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return DateFormat::parse(text, status);
2156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
2158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t SimpleDateFormat::matchQuarterString(const UnicodeString& text,
2160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              int32_t start,
2161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UCalendarDateFields field,
2162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              const UnicodeString* data,
2163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              int32_t dataCount,
2164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              Calendar& cal) const
2165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i = 0;
2167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t count = dataCount;
2168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // There may be multiple strings in the data[] array which begin with
2170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // the same prefix (e.g., Cerven and Cervenec (June and July) in Czech).
2171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // We keep track of the longest match, and return that.  Note that this
2172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // unfortunately requires us to test all array elements.
2173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t bestMatchLength = 0, bestMatch = -1;
2174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // {sfb} kludge to support case-insensitive comparison
2176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // {markus 2002oct11} do not just use caseCompareBetween because we do not know
2177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // the length of the match after case folding
2178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // {alan 20040607} don't case change the whole string, since the length
2179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // can change
2180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // TODO we need a case-insensitive startsWith function
2181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString lcase, lcaseText;
2182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    text.extract(start, INT32_MAX, lcaseText);
2183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lcaseText.foldCase();
2184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (; i < count; ++i)
2186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
2187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Always compare if we have no match yet; otherwise only compare
2188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // against potentially better matches (longer strings).
2189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        lcase.fastCopyFrom(data[i]).foldCase();
2191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t length = lcase.length();
2192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (length > bestMatchLength &&
2194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            lcaseText.compareBetween(0, length, lcase, 0, length) == 0)
2195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            bestMatch = i;
2197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            bestMatchLength = length;
2198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (bestMatch >= 0)
2201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
2202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cal.set(field, bestMatch * 3);
2203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Once we have a match, we have to determine the length of the
2205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // original source string.  This will usually be == the length of
2206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // the case folded string, but it may differ (e.g. sharp s).
2207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        lcase.fastCopyFrom(data[bestMatch]).foldCase();
2208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Most of the time, the length will be the same as the length
2210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // of the string from the locale data.  Sometimes it will be
2211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // different, in which case we will have to figure it out by
2212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // adding a character at a time, until we have a match.  We do
2213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // this all in one loop, where we try 'len' first (at index
2214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // i==0).
2215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t len = data[bestMatch].length(); // 99+% of the time
2216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t n = text.length() - start;
2217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (i=0; i<=n; ++i) {
2218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t j=i;
2219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (i == 0) {
2220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                j = len;
2221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if (i == len) {
2222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                continue; // already tried this when i was 0
2223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            text.extract(start, j, lcaseText);
2225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            lcaseText.foldCase();
2226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (lcase == lcaseText) {
2227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return start + j;
2228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return -start;
2233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
2236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t SimpleDateFormat::matchString(const UnicodeString& text,
2238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              int32_t start,
2239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UCalendarDateFields field,
2240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              const UnicodeString* data,
2241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              int32_t dataCount,
2242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              Calendar& cal) const
2243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i = 0;
2245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t count = dataCount;
2246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (field == UCAL_DAY_OF_WEEK) i = 1;
2248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // There may be multiple strings in the data[] array which begin with
2250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // the same prefix (e.g., Cerven and Cervenec (June and July) in Czech).
2251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // We keep track of the longest match, and return that.  Note that this
2252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // unfortunately requires us to test all array elements.
2253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t bestMatchLength = 0, bestMatch = -1;
2254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // {sfb} kludge to support case-insensitive comparison
2256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // {markus 2002oct11} do not just use caseCompareBetween because we do not know
2257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // the length of the match after case folding
2258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // {alan 20040607} don't case change the whole string, since the length
2259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // can change
2260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // TODO we need a case-insensitive startsWith function
2261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString lcase, lcaseText;
2262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    text.extract(start, INT32_MAX, lcaseText);
2263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lcaseText.foldCase();
2264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (; i < count; ++i)
2266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
2267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Always compare if we have no match yet; otherwise only compare
2268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // against potentially better matches (longer strings).
2269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        lcase.fastCopyFrom(data[i]).foldCase();
2271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t length = lcase.length();
2272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (length > bestMatchLength &&
2274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            lcaseText.compareBetween(0, length, lcase, 0, length) == 0)
2275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            bestMatch = i;
2277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            bestMatchLength = length;
2278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (bestMatch >= 0)
2281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
2282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cal.set(field, bestMatch);
2283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Once we have a match, we have to determine the length of the
2285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // original source string.  This will usually be == the length of
2286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // the case folded string, but it may differ (e.g. sharp s).
2287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        lcase.fastCopyFrom(data[bestMatch]).foldCase();
2288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Most of the time, the length will be the same as the length
2290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // of the string from the locale data.  Sometimes it will be
2291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // different, in which case we will have to figure it out by
2292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // adding a character at a time, until we have a match.  We do
2293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // this all in one loop, where we try 'len' first (at index
2294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // i==0).
2295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t len = data[bestMatch].length(); // 99+% of the time
2296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t n = text.length() - start;
2297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (i=0; i<=n; ++i) {
2298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t j=i;
2299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (i == 0) {
2300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                j = len;
2301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if (i == len) {
2302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                continue; // already tried this when i was 0
2303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            text.extract(start, j, lcaseText);
2305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            lcaseText.foldCase();
2306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (lcase == lcaseText) {
2307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return start + j;
2308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return -start;
2313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
2316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
2318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::set2DigitYearStart(UDate d, UErrorCode& status)
2319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    parseAmbiguousDatesAsAfter(d, status);
2321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
2324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Private member function that converts the parsed date strings into
2325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * timeFields. Returns -start (for ParsePosition) if failed.
2326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param text the time text to be parsed.
2327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param start where to start parsing.
2328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param ch the pattern character for the date field text to be parsed.
2329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param count the count of a pattern character.
2330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return the new start position if matching succeeded; a negative number
2331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * indicating matching failure, otherwise.
2332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
2333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UChar ch, int32_t count,
233485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                           UBool obeyCount, UBool allowNegative, UBool ambiguousYear[], Calendar& cal,
233585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                           int32_t patLoc) const
2336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Formattable number;
2338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t value = 0;
2339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i;
2340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ParsePosition pos(0);
234185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UDateFormatField patternCharIndex;
234285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    NumberFormat *currentNumberFormat;
2343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString temp;
2344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar *patternCharPtr = u_strchr(DateFormatSymbols::getPatternUChars(), ch);
2345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if defined (U_DEBUG_CAL)
2347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //fprintf(stderr, "%s:%d - [%c]  st=%d \n", __FILE__, __LINE__, (char) ch, start);
2348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
2349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (patternCharPtr == NULL) {
2351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return -start;
2352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    patternCharIndex = (UDateFormatField)(patternCharPtr - DateFormatSymbols::getPatternUChars());
235585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    currentNumberFormat = getNumberFormat(patternCharIndex);
2356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UCalendarDateFields field = fgPatternIndexToCalendarField[patternCharIndex];
2357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // If there are any spaces here, skip over them.  If we hit the end
2359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // of the string, then fail.
2360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (;;) {
2361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (start >= text.length()) {
2362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return -start;
2363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar32 c = text.char32At(start);
2365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (!u_isUWhiteSpace(c)) {
2366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
2367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        start += UTF_CHAR_LENGTH(c);
2369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pos.setIndex(start);
2371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // We handle a few special cases here where we need to parse
2373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // a number value.  We handle further, more generic cases below.  We need
2374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // to handle some of them here because some fields require extra processing on
2375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // the parsed value.
2376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (patternCharIndex == UDAT_HOUR_OF_DAY1_FIELD ||
2377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        patternCharIndex == UDAT_HOUR1_FIELD ||
237885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        (patternCharIndex == UDAT_DOW_LOCAL_FIELD && count <= 2) ||
237985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        (patternCharIndex == UDAT_STANDALONE_DAY_FIELD && count <= 2) ||
2380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        (patternCharIndex == UDAT_MONTH_FIELD && count <= 2) ||
2381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        (patternCharIndex == UDAT_STANDALONE_MONTH_FIELD && count <= 2) ||
2382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        (patternCharIndex == UDAT_QUARTER_FIELD && count <= 2) ||
2383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        (patternCharIndex == UDAT_STANDALONE_QUARTER_FIELD && count <= 2) ||
2384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        patternCharIndex == UDAT_YEAR_FIELD ||
2385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        patternCharIndex == UDAT_YEAR_WOY_FIELD ||
2386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        patternCharIndex == UDAT_FRACTIONAL_SECOND_FIELD)
2387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
2388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t parseStart = pos.getIndex();
2389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // It would be good to unify this with the obeyCount logic below,
2390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // but that's going to be difficult.
2391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const UnicodeString* src;
2392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (obeyCount) {
2394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((start+count) > text.length()) {
2395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return -start;
2396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            text.extractBetween(0, start + count, temp);
2399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            src = &temp;
2400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
2401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            src = &text;
2402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
240485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        parseInt(*src, number, pos, allowNegative,currentNumberFormat);
2405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (pos.getIndex() == parseStart)
2407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return -start;
2408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        value = number.getLong();
240985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
241085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // suffix processing
241185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        int32_t txtLoc = pos.getIndex();
241285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (value <0 ) {
241385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            txtLoc = checkIntSuffix(text, txtLoc, patLoc+1, TRUE);
241485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (txtLoc != pos.getIndex()) {
241585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                value *= -1;
241685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
241785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
241885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        else {
241985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            txtLoc = checkIntSuffix(text, txtLoc, patLoc+1, FALSE);
242085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
242185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pos.setIndex(txtLoc);
242285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
2423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    switch (patternCharIndex) {
2426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_ERA_FIELD:
242785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (count == 5) {
242885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return matchString(text, start, UCAL_ERA, fSymbols->fNarrowEras, fSymbols->fNarrowErasCount, cal);
242985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
2430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (count == 4) {
2431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return matchString(text, start, UCAL_ERA, fSymbols->fEraNames, fSymbols->fEraNamesCount, cal);
2432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return matchString(text, start, UCAL_ERA, fSymbols->fEras, fSymbols->fErasCount, cal);
2435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_YEAR_FIELD:
2437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // If there are 3 or more YEAR pattern characters, this indicates
2438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // that the year value is to be treated literally, without any
2439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // two-digit year adjustments (e.g., from "01" to 2001).  Otherwise
2440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // we made adjustments to place the 2-digit year in the proper
2441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // century, for parsed strings from "00" to "99".  Any other string
2442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // is treated literally:  "2250", "-1", "1", "002".
2443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (count <= 2 && (pos.getIndex() - start) == 2
2444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            && u_isdigit(text.charAt(start))
2445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            && u_isdigit(text.charAt(start+1)))
2446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Assume for example that the defaultCenturyStart is 6/18/1903.
2448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // This means that two-digit years will be forced into the range
2449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // 6/18/1903 to 6/17/2003.  As a result, years 00, 01, and 02
2450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // correspond to 2000, 2001, and 2002.  Years 04, 05, etc. correspond
2451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // to 1904, 1905, etc.  If the year is 03, then it is 2003 if the
2452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // other fields specify a date before 6/18, or 1903 if they specify a
2453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // date afterwards.  As a result, 03 is an ambiguous year.  All other
2454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // two-digit years are unambiguous.
2455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          if(fHaveDefaultCentury) { // check if this formatter even has a pivot year
2456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              int32_t ambiguousTwoDigitYear = fDefaultCenturyStartYear % 100;
2457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              ambiguousYear[0] = (value == ambiguousTwoDigitYear);
2458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              value += (fDefaultCenturyStartYear/100)*100 +
2459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                (value < ambiguousTwoDigitYear ? 100 : 0);
2460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cal.set(UCAL_YEAR, value);
2463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return pos.getIndex();
2464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_YEAR_WOY_FIELD:
2466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Comment is the same as for UDAT_Year_FIELDs - look above
2467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (count <= 2 && (pos.getIndex() - start) == 2
2468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            && u_isdigit(text.charAt(start))
2469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            && u_isdigit(text.charAt(start+1))
2470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            && fHaveDefaultCentury )
2471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t ambiguousTwoDigitYear = fDefaultCenturyStartYear % 100;
2473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ambiguousYear[0] = (value == ambiguousTwoDigitYear);
2474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            value += (fDefaultCenturyStartYear/100)*100 +
2475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                (value < ambiguousTwoDigitYear ? 100 : 0);
2476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cal.set(UCAL_YEAR_WOY, value);
2478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return pos.getIndex();
2479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_MONTH_FIELD:
2481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (count <= 2) // i.e., M or MM.
2482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Don't want to parse the month if it is a string
2484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // while pattern uses numeric style: M or MM.
2485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // [We computed 'value' above.]
2486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cal.set(UCAL_MONTH, value - 1);
2487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return pos.getIndex();
2488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
2489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // count >= 3 // i.e., MMM or MMMM
2490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Want to be able to parse both short and long forms.
2491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Try count == 4 first:
2492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t newStart = 0;
2493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((newStart = matchString(text, start, UCAL_MONTH,
2495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                      fSymbols->fMonths, fSymbols->fMonthsCount, cal)) > 0)
2496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return newStart;
2497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            else // count == 4 failed, now try count == 3
2498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return matchString(text, start, UCAL_MONTH,
2499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   fSymbols->fShortMonths, fSymbols->fShortMonthsCount, cal);
2500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_STANDALONE_MONTH_FIELD:
2503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (count <= 2) // i.e., L or LL.
2504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Don't want to parse the month if it is a string
2506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // while pattern uses numeric style: M or MM.
2507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // [We computed 'value' above.]
2508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cal.set(UCAL_MONTH, value - 1);
2509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return pos.getIndex();
2510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
2511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // count >= 3 // i.e., LLL or LLLL
2512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Want to be able to parse both short and long forms.
2513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Try count == 4 first:
2514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t newStart = 0;
2515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((newStart = matchString(text, start, UCAL_MONTH,
2517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                      fSymbols->fStandaloneMonths, fSymbols->fStandaloneMonthsCount, cal)) > 0)
2518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return newStart;
2519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            else // count == 4 failed, now try count == 3
2520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return matchString(text, start, UCAL_MONTH,
2521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   fSymbols->fStandaloneShortMonths, fSymbols->fStandaloneShortMonthsCount, cal);
2522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_HOUR_OF_DAY1_FIELD:
2525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // [We computed 'value' above.]
2526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (value == cal.getMaximum(UCAL_HOUR_OF_DAY) + 1)
2527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            value = 0;
2528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cal.set(UCAL_HOUR_OF_DAY, value);
2529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return pos.getIndex();
2530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_FRACTIONAL_SECOND_FIELD:
2532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Fractional seconds left-justify
2533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        i = pos.getIndex() - start;
2534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (i < 3) {
2535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while (i < 3) {
2536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                value *= 10;
2537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                i++;
2538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
2540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t a = 1;
2541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while (i > 3) {
2542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                a *= 10;
2543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                i--;
2544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            value = (value + (a>>1)) / a;
2546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cal.set(UCAL_MILLISECOND, value);
2548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return pos.getIndex();
2549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
255085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    case UDAT_DOW_LOCAL_FIELD:
255185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (count <= 2) // i.e., e or ee
255285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {
255385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // [We computed 'value' above.]
255485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            cal.set(UCAL_DOW_LOCAL, value);
255585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return pos.getIndex();
255685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
255785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // else for eee-eeeee fall through to handling of EEE-EEEEE
255885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // fall through, do not break here
2559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_DAY_OF_WEEK_FIELD:
2560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Want to be able to parse both short and long forms.
256285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Try count == 4 (EEEE) first:
2563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t newStart = 0;
2564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
2565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                      fSymbols->fWeekdays, fSymbols->fWeekdaysCount, cal)) > 0)
2566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return newStart;
256785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // EEEE failed, now try EEE
256885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            else if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
256985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                   fSymbols->fShortWeekdays, fSymbols->fShortWeekdaysCount, cal)) > 0)
257085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return newStart;
257185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // EEE failed, now try EEEEE
257285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            else
2573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return matchString(text, start, UCAL_DAY_OF_WEEK,
257485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                   fSymbols->fNarrowWeekdays, fSymbols->fNarrowWeekdaysCount, cal);
2575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_STANDALONE_DAY_FIELD:
2578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
257985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (count <= 2) // c or cc
258085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            {
258185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                // [We computed 'value' above.]
258285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                cal.set(UCAL_DOW_LOCAL, value);
258385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return pos.getIndex();
258485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
2585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Want to be able to parse both short and long forms.
258685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Try count == 4 (cccc) first:
2587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t newStart = 0;
2588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((newStart = matchString(text, start, UCAL_DAY_OF_WEEK,
2589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                      fSymbols->fStandaloneWeekdays, fSymbols->fStandaloneWeekdaysCount, cal)) > 0)
2590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return newStart;
259185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            else // cccc failed, now try ccc
2592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return matchString(text, start, UCAL_DAY_OF_WEEK,
2593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   fSymbols->fStandaloneShortWeekdays, fSymbols->fStandaloneShortWeekdaysCount, cal);
2594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_AM_PM_FIELD:
2597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return matchString(text, start, UCAL_AM_PM, fSymbols->fAmPms, fSymbols->fAmPmsCount, cal);
2598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_HOUR1_FIELD:
2600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // [We computed 'value' above.]
2601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (value == cal.getLeastMaximum(UCAL_HOUR)+1)
2602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            value = 0;
2603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cal.set(UCAL_HOUR, value);
2604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return pos.getIndex();
2605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_QUARTER_FIELD:
2607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (count <= 2) // i.e., Q or QQ.
2608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Don't want to parse the month if it is a string
2610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // while pattern uses numeric style: Q or QQ.
2611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // [We computed 'value' above.]
2612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cal.set(UCAL_MONTH, (value - 1) * 3);
2613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return pos.getIndex();
2614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
2615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // count >= 3 // i.e., QQQ or QQQQ
2616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Want to be able to parse both short and long forms.
2617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Try count == 4 first:
2618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t newStart = 0;
2619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((newStart = matchQuarterString(text, start, UCAL_MONTH,
2621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                      fSymbols->fQuarters, fSymbols->fQuartersCount, cal)) > 0)
2622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return newStart;
2623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            else // count == 4 failed, now try count == 3
2624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return matchQuarterString(text, start, UCAL_MONTH,
2625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   fSymbols->fShortQuarters, fSymbols->fShortQuartersCount, cal);
2626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_STANDALONE_QUARTER_FIELD:
2629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (count <= 2) // i.e., q or qq.
2630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Don't want to parse the month if it is a string
2632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // while pattern uses numeric style: q or q.
2633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // [We computed 'value' above.]
2634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cal.set(UCAL_MONTH, (value - 1) * 3);
2635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return pos.getIndex();
2636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
2637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // count >= 3 // i.e., qqq or qqqq
2638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Want to be able to parse both short and long forms.
2639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Try count == 4 first:
2640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t newStart = 0;
2641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((newStart = matchQuarterString(text, start, UCAL_MONTH,
2643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                      fSymbols->fStandaloneQuarters, fSymbols->fStandaloneQuartersCount, cal)) > 0)
2644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return newStart;
2645ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            else // count == 4 failed, now try count == 3
2646ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return matchQuarterString(text, start, UCAL_MONTH,
2647ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   fSymbols->fStandaloneShortQuarters, fSymbols->fStandaloneShortQuartersCount, cal);
2648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_TIMEZONE_FIELD:
2651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_TIMEZONE_RFC_FIELD:
2652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UDAT_TIMEZONE_GENERIC_FIELD:
2653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case UDAT_TIMEZONE_SPECIAL_FIELD:
2654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
2655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t offset = 0;
2656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UBool parsed = FALSE;
2657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Step 1
2659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Check if this is a long GMT offset string (either localized or default)
2660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            offset = parseGMT(text, pos);
2661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (pos.getIndex() - start > 0) {
2662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                parsed = TRUE;
2663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (!parsed) {
2665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Step 2
2666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Check if this is an RFC822 time zone offset.
2667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // ICU supports the standard RFC822 format [+|-]HHmm
2668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // and its extended form [+|-]HHmmSS.
2669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                do {
2670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    int32_t sign = 0;
2671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    UChar signChar = text.charAt(start);
2672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (signChar == (UChar)0x002B /* '+' */) {
2673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        sign = 1;
2674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else if (signChar == (UChar)0x002D /* '-' */) {
2675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        sign = -1;
2676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else {
2677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // Not an RFC822 offset string
2678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
2679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
2680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // Parse digits
2682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    int32_t orgPos = start + 1;
2683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    pos.setIndex(orgPos);
268485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    parseInt(text, number, 6, pos, FALSE,currentNumberFormat);
2685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    int32_t numLen = pos.getIndex() - orgPos;
2686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (numLen <= 0) {
2687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
2688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
2689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // Followings are possible format (excluding sign char)
2691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // HHmmSS
2692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // HmmSS
2693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // HHmm
2694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // Hmm
2695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // HH
2696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // H
2697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    int32_t val = number.getLong();
2698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    int32_t hour = 0, min = 0, sec = 0;
2699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    switch(numLen) {
2700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case 1: // H
2701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case 2: // HH
2702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        hour = val;
2703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
2704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case 3: // Hmm
2705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case 4: // HHmm
2706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        hour = val / 100;
2707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        min = val % 100;
2708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
2709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case 5: // Hmmss
2710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case 6: // HHmmss
2711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        hour = val / 10000;
2712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        min = (val % 10000) / 100;
2713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        sec = val % 100;
2714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
2715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
2716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (hour > 23 || min > 59 || sec > 59) {
2717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // Invalid value range
2718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
2719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
2720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    offset = (((hour * 60) + min) * 60 + sec) * 1000 * sign;
2721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    parsed = TRUE;
2722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } while (FALSE);
2723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (!parsed) {
2725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // Failed to parse.  Reset the position.
2726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    pos.setIndex(start);
2727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2728ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (parsed) {
2731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // offset was successfully parsed as either a long GMT string or RFC822 zone offset
2732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // string.  Create normalized zone ID for the offset.
2733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UnicodeString tzID(gGmt);
2735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                formatRFC822TZ(tzID, offset);
2736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                //TimeZone *customTZ = TimeZone::createTimeZone(tzID);
2737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                TimeZone *customTZ = new SimpleTimeZone(offset, tzID);    // faster than TimeZone::createTimeZone
2738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                cal.adoptTimeZone(customTZ);
2739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return pos.getIndex();
2741ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Step 3
2744ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // At this point, check for named time zones by looking through
2745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // the locale data from the DateFormatZoneData strings.
2746ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // Want to be able to parse both short and long forms.
2747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // optimize for calendar's current time zone
2748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const ZoneStringFormat *zsf = fSymbols->getZoneStringFormat();
2749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (zsf) {
2750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UErrorCode status = U_ZERO_ERROR;
2751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                const ZoneStringInfo *zsinfo = NULL;
2752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                int32_t matchLen;
2753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                switch (patternCharIndex) {
2755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case UDAT_TIMEZONE_FIELD: // 'z'
2756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if (count < 4) {
2757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            zsinfo = zsf->findSpecificShort(text, start, matchLen, status);
2758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        } else {
2759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            zsinfo = zsf->findSpecificLong(text, start, matchLen, status);
2760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
2761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
2762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case UDAT_TIMEZONE_GENERIC_FIELD: // 'v'
2763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if (count == 1) {
2764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            zsinfo = zsf->findGenericShort(text, start, matchLen, status);
2765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        } else if (count == 4) {
2766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            zsinfo = zsf->findGenericLong(text, start, matchLen, status);
2767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
2768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
2769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    case UDAT_TIMEZONE_SPECIAL_FIELD: // 'V'
2770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if (count == 1) {
2771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            zsinfo = zsf->findSpecificShort(text, start, matchLen, status);
2772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        } else if (count == 4) {
2773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            zsinfo = zsf->findGenericLocation(text, start, matchLen, status);
2774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
2775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
277685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    default:
277785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        break;
2778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (U_SUCCESS(status) && zsinfo != NULL) {
2781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (zsinfo->isStandard()) {
2782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        ((SimpleDateFormat*)this)->tztype = TZTYPE_STD;
2783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else if (zsinfo->isDaylight()) {
2784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        ((SimpleDateFormat*)this)->tztype = TZTYPE_DST;
2785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
2786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    UnicodeString tzid;
2787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    zsinfo->getID(tzid);
2788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    UnicodeString current;
2790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    cal.getTimeZone().getID(current);
2791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (tzid != current) {
2792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        TimeZone *tz = TimeZone::createTimeZone(tzid);
2793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        cal.adoptTimeZone(tz);
2794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
2795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return start + matchLen;
2796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
279885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Step 4
279985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Final attempt - is this standalone GMT/UT/UTC?
280085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            int32_t gmtLen = 0;
280185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (text.compare(start, kGmtLen, gGmt) == 0) {
280285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                gmtLen = kGmtLen;
280385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            } else if (text.compare(start, kUtcLen, gUtc) == 0) {
280485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                gmtLen = kUtcLen;
280585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            } else if (text.compare(start, kUtLen, gUt) == 0) {
280685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                gmtLen = kUtLen;
280785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
280885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (gmtLen > 0) {
280985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                TimeZone *tz = TimeZone::createTimeZone(UnicodeString("Etc/GMT"));
281085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                cal.adoptTimeZone(tz);
281185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return start + gmtLen;
281285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
281385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
2814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // complete failure
2815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return -start;
2816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    default:
2819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Handle "generic" fields
2820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t parseStart = pos.getIndex();
2821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const UnicodeString* src;
2822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (obeyCount) {
2823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((start+count) > text.length()) {
2824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return -start;
2825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            text.extractBetween(0, start + count, temp);
2827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            src = &temp;
2828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
2829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            src = &text;
2830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
283185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        parseInt(*src, number, pos, allowNegative,currentNumberFormat);
2832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (pos.getIndex() != parseStart) {
2833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cal.set(field, number.getLong());
2834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return pos.getIndex();
2835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return -start;
2837ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
2841ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Parse an integer using fNumberFormat.  This method is semantically
2842ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * const, but actually may modify fNumberFormat.
2843ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
2844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid SimpleDateFormat::parseInt(const UnicodeString& text,
2845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                Formattable& number,
2846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                ParsePosition& pos,
284785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                UBool allowNegative,
284885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                NumberFormat *fmt) const {
284985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    parseInt(text, number, -1, pos, allowNegative,fmt);
2850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
2853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Parse an integer using fNumberFormat up to maxDigits.
2854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
2855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid SimpleDateFormat::parseInt(const UnicodeString& text,
2856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                Formattable& number,
2857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                int32_t maxDigits,
2858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                ParsePosition& pos,
285985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                UBool allowNegative,
286085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                NumberFormat *fmt) const {
2861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString oldPrefix;
2862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DecimalFormat* df = NULL;
2863ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!allowNegative &&
286485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fmt->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
286585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        df = (DecimalFormat*)fmt;
2866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        df->getNegativePrefix(oldPrefix);
2867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        df->setNegativePrefix(SUPPRESS_NEGATIVE_PREFIX);
2868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t oldPos = pos.getIndex();
287085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fmt->parse(text, number, pos);
2871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (df != NULL) {
2872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        df->setNegativePrefix(oldPrefix);
2873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (maxDigits > 0) {
2876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // adjust the result to fit into
2877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // the maxDigits and move the position back
2878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t nDigits = pos.getIndex() - oldPos;
2879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (nDigits > maxDigits) {
2880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t val = number.getLong();
2881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            nDigits -= maxDigits;
2882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while (nDigits > 0) {
2883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                val /= 10;
2884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                nDigits--;
2885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pos.setIndex(oldPos + maxDigits);
2887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            number.setLong(val);
2888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
2893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid SimpleDateFormat::translatePattern(const UnicodeString& originalPattern,
2895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                        UnicodeString& translatedPattern,
2896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                        const UnicodeString& from,
2897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                        const UnicodeString& to,
2898ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                        UErrorCode& status)
2899ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // run through the pattern and convert any pattern symbols from the version
2901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // in "from" to the corresponding character ion "to".  This code takes
2902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // quoted strings into account (it doesn't try to translate them), and it signals
2903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // an error if a particular "pattern character" doesn't appear in "from".
2904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // Depending on the values of "from" and "to" this can convert from generic
2905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // to localized patterns or localized to generic.
2906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  if (U_FAILURE(status))
2907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return;
2908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  translatedPattern.remove();
2910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  UBool inQuote = FALSE;
2911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  for (int32_t i = 0; i < originalPattern.length(); ++i) {
2912ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar c = originalPattern[i];
2913ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (inQuote) {
2914ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      if (c == QUOTE)
2915ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inQuote = FALSE;
2916ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else {
2918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      if (c == QUOTE)
2919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inQuote = TRUE;
2920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      else if ((c >= 0x0061 /*'a'*/ && c <= 0x007A) /*'z'*/
2921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru           || (c >= 0x0041 /*'A'*/ && c <= 0x005A /*'Z'*/)) {
2922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t ci = from.indexOf(c);
2923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (ci == -1) {
2924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      status = U_INVALID_FORMAT_ERROR;
2925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      return;
2926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2927ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    c = to[ci];
2928ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      }
2929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    translatedPattern += c;
2931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  }
2932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  if (inQuote) {
2933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    status = U_INVALID_FORMAT_ERROR;
2934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return;
2935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  }
2936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
2939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2940ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
2941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::toPattern(UnicodeString& result) const
2942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result = fPattern;
2944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
2945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
2948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
2950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::toLocalizedPattern(UnicodeString& result,
2951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                     UErrorCode& status) const
2952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    translatePattern(fPattern, result, DateFormatSymbols::getPatternUChars(), fSymbols->fLocalPatternChars, status);
2954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
2955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
2958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
2960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::applyPattern(const UnicodeString& pattern)
2961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fPattern = pattern;
2963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
2966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
2968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::applyLocalizedPattern(const UnicodeString& pattern,
2969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                        UErrorCode &status)
2970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    translatePattern(pattern, fPattern, fSymbols->fLocalPatternChars, DateFormatSymbols::getPatternUChars(), status);
2972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
2975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst DateFormatSymbols*
2977ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::getDateFormatSymbols() const
2978ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return fSymbols;
2980ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2982ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
2983ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2984ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
2985ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::adoptDateFormatSymbols(DateFormatSymbols* newFormatSymbols)
2986ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2987ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete fSymbols;
2988ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols = newFormatSymbols;
2989ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2991ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
2992ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
2993ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleDateFormat::setDateFormatSymbols(const DateFormatSymbols& newFormatSymbols)
2994ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
2995ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete fSymbols;
2996ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fSymbols = new DateFormatSymbols(newFormatSymbols);
2997ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2998ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2999ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3000ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//----------------------------------------------------------------------
3001ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3003ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid SimpleDateFormat::adoptCalendar(Calendar* calendarToAdopt)
3004ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
3005ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  UErrorCode status = U_ZERO_ERROR;
3006ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  DateFormat::adoptCalendar(calendarToAdopt);
3007ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  delete fSymbols;
3008ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  fSymbols=NULL;
3009ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  initializeSymbols(fLocale, fCalendar, status);  // we need new symbols
3010ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  initializeDefaultCentury();  // we need a new century (possibly)
3011ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
3012ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
301385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
301485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
301585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
301685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
301785bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoUBool
301885bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::isFieldUnitIgnored(UCalendarDateFields field) const {
301985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return isFieldUnitIgnored(fPattern, field);
302085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
302185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
302285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
302385bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoUBool
302485bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::isFieldUnitIgnored(const UnicodeString& pattern,
302585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                     UCalendarDateFields field) {
302685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t fieldLevel = fgCalendarFieldToLevel[field];
302785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t level;
302885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UChar ch;
302985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UBool inQuote = FALSE;
303085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UChar prevCh = 0;
303185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t count = 0;
303285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
303385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    for (int32_t i = 0; i < pattern.length(); ++i) {
303485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ch = pattern[i];
303585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (ch != prevCh && count > 0) {
303685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            level = fgPatternCharToLevel[prevCh - PATTERN_CHAR_BASE];
303785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // the larger the level, the smaller the field unit.
303885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if ( fieldLevel <= level ) {
303985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return FALSE;
304085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
304185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            count = 0;
304285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
304385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (ch == QUOTE) {
304485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if ((i+1) < pattern.length() && pattern[i+1] == QUOTE) {
304585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                ++i;
304685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            } else {
304785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                inQuote = ! inQuote;
304885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
304985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
305085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        else if ( ! inQuote && ((ch >= 0x0061 /*'a'*/ && ch <= 0x007A /*'z'*/)
305185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    || (ch >= 0x0041 /*'A'*/ && ch <= 0x005A /*'Z'*/))) {
305285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            prevCh = ch;
305385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ++count;
305485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
305585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
305685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if ( count > 0 ) {
305785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // last item
305885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        level = fgPatternCharToLevel[prevCh - PATTERN_CHAR_BASE];
305985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if ( fieldLevel <= level ) {
306085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return FALSE;
306185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
306285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
306385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return TRUE;
306485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
306585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
306685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
306785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
306885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoconst Locale&
306985bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::getSmpFmtLocale(void) const {
307085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return fLocale;
307185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
307285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
307385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
307485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
307585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoint32_t
307685bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::checkIntSuffix(const UnicodeString& text, int32_t start,
307785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                 int32_t patLoc, UBool isNegative) const {
307885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // local variables
307985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UnicodeString suf;
308085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t patternMatch;
308185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t textPreMatch;
308285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t textPostMatch;
308385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
308485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // check that we are still in range
308585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if ( (start > text.length()) ||
308685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         (start < 0) ||
308785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         (patLoc < 0) ||
308885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         (patLoc > fPattern.length())) {
308985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // out of range, don't advance location in text
309085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return start;
309185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
309285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
309385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // get the suffix
309485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (fNumberFormat->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
309585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (isNegative) {
309685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            suf = ((DecimalFormat*)fNumberFormat)->getNegativeSuffix(suf);
309785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
309885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        else {
309985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            suf = ((DecimalFormat*)fNumberFormat)->getPositiveSuffix(suf);
310085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
310185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
310285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
310385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // check for suffix
310485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (suf.length() <= 0) {
310585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return start;
310685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
310785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
310885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // check suffix will be encountered in the pattern
310985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    patternMatch = compareSimpleAffix(suf,fPattern,patLoc);
311085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
311185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // check if a suffix will be encountered in the text
311285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    textPreMatch = compareSimpleAffix(suf,text,start);
311385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
311485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // check if a suffix was encountered in the text
311585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    textPostMatch = compareSimpleAffix(suf,text,start-suf.length());
311685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
311785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // check for suffix match
311885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if ((textPreMatch >= 0) && (patternMatch >= 0) && (textPreMatch == patternMatch)) {
311985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return start;
312085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
312185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    else if ((textPostMatch >= 0) && (patternMatch >= 0) && (textPostMatch == patternMatch)) {
312285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return  start - suf.length();
312385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
312485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
312585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // should not get here
312685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return start;
312785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
312885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
312985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
313085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
313185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoint32_t
313285bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::compareSimpleAffix(const UnicodeString& affix,
313385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   const UnicodeString& input,
313485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   int32_t pos) const {
313585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t start = pos;
313685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    for (int32_t i=0; i<affix.length(); ) {
313785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UChar32 c = affix.char32At(i);
313885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        int32_t len = U16_LENGTH(c);
313985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (uprv_isRuleWhiteSpace(c)) {
314085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // We may have a pattern like: \u200F \u0020
314185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            //        and input text like: \u200F \u0020
314285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Note that U+200F and U+0020 are RuleWhiteSpace but only
314385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // U+0020 is UWhiteSpace.  So we have to first do a direct
314485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // match of the run of RULE whitespace in the pattern,
314585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // then match any extra characters.
314685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UBool literalMatch = FALSE;
314785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            while (pos < input.length() &&
314885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                   input.char32At(pos) == c) {
314985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                literalMatch = TRUE;
315085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                i += len;
315185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                pos += len;
315285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (i == affix.length()) {
315385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
315485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
315585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                c = affix.char32At(i);
315685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                len = U16_LENGTH(c);
315785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (!uprv_isRuleWhiteSpace(c)) {
315885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
315985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
316085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
316185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
316285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Advance over run in pattern
316385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            i = skipRuleWhiteSpace(affix, i);
316485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
316585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Advance over run in input text
316685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Must see at least one white space char in input,
316785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // unless we've already matched some characters literally.
316885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            int32_t s = pos;
316985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            pos = skipUWhiteSpace(input, pos);
317085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (pos == s && !literalMatch) {
317185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return -1;
317285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
317385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
317485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // If we skip UWhiteSpace in the input text, we need to skip it in the pattern.
317585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // Otherwise, the previous lines may have skipped over text (such as U+00A0) that
317685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // is also in the affix.
317785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            i = skipUWhiteSpace(affix, i);
317885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else {
317985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (pos < input.length() &&
318085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                input.char32At(pos) == c) {
318185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                i += len;
318285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                pos += len;
318385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            } else {
318485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return -1;
318585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
318685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
318785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
318885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return pos - start;
318985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
319085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
319185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
319285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
319385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoint32_t
319485bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::skipRuleWhiteSpace(const UnicodeString& text, int32_t pos) const {
319585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    while (pos < text.length()) {
319685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UChar32 c = text.char32At(pos);
319785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (!uprv_isRuleWhiteSpace(c)) {
319885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            break;
319985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
320085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pos += U16_LENGTH(c);
320185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
320285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return pos;
320385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
320485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
320585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho//----------------------------------------------------------------------
320685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
320785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoint32_t
320885bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoSimpleDateFormat::skipUWhiteSpace(const UnicodeString& text, int32_t pos) const {
320985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    while (pos < text.length()) {
321085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UChar32 c = text.char32At(pos);
321185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (!u_isUWhiteSpace(c)) {
321285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            break;
321385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
321485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pos += U16_LENGTH(c);
321585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
321685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return pos;
321785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
321885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
3219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END
3220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
3222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//eof
3224