1c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru/*******************************************************************************
2fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Copyright (C) 2008-2014, International Business Machines Corporation and
3c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru* others. All Rights Reserved.
4c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru*******************************************************************************
5c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru*
6c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru* File DTITVFMT.CPP
7c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru*
8c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru*******************************************************************************
9c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru*/
10c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "utypeinfo.h"  // for 'typeid' to work
1227f654740f2a26ad62a5c155af9199af9e69b889claireho
13c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "unicode/dtitvfmt.h"
14c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
15c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
16c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
17b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//TODO: put in compilation
18c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru//#define DTITVFMT_DEBUG 1
19c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
20c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "cstring.h"
21c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "unicode/msgfmt.h"
22c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "unicode/dtptngen.h"
23c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "unicode/dtitvinf.h"
24c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "unicode/calendar.h"
25c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "dtitv_impl.h"
26c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
27c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#ifdef DTITVFMT_DEBUG
28c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include <iostream>
29c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "cstring.h"
30c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#endif
31c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
32c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "gregoimp.h"
33c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
34c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruU_NAMESPACE_BEGIN
35c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
36c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
37c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
38c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#ifdef DTITVFMT_DEBUG
39c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#define PRINTMESG(msg) { std::cout << "(" << __FILE__ << ":" << __LINE__ << ") " << msg << "\n"; }
40c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#endif
41c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
42c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
43c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic const UChar gDateFormatSkeleton[][11] = {
44c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru//yMMMMEEEEd
45c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{LOW_Y, CAP_M, CAP_M, CAP_M, CAP_M, CAP_E, CAP_E, CAP_E, CAP_E, LOW_D, 0},
46c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru//yMMMMd
47c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{LOW_Y, CAP_M, CAP_M, CAP_M, CAP_M, LOW_D, 0},
48c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru//yMMMd
49c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{LOW_Y, CAP_M, CAP_M, CAP_M, LOW_D, 0},
50c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru//yMd
51c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{LOW_Y, CAP_M, LOW_D, 0} };
52c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
53c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
54c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic const char gDateTimePatternsTag[]="DateTimePatterns";
55c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
56c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
57c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru// latestFirst:
58b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const UChar gLaterFirstPrefix[] = {LOW_L, LOW_A, LOW_T, LOW_E, LOW_S,LOW_T, CAP_F, LOW_I, LOW_R, LOW_S, LOW_T, COLON};
59c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
60c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru// earliestFirst:
61b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const UChar gEarlierFirstPrefix[] = {LOW_E, LOW_A, LOW_R, LOW_L, LOW_I, LOW_E, LOW_S, LOW_T, CAP_F, LOW_I, LOW_R, LOW_S, LOW_T, COLON};
62c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
63c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
64c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateIntervalFormat)
65c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
66c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
67c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
68c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat* U_EXPORT2
69c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::createInstance(const UnicodeString& skeleton,
70c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   UErrorCode& status) {
71c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return createInstance(skeleton, Locale::getDefault(), status);
72c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
73c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
74c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
75c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat* U_EXPORT2
76c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::createInstance(const UnicodeString& skeleton,
77c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   const Locale& locale,
78c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   UErrorCode& status) {
79c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#ifdef DTITVFMT_DEBUG
80c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char result[1000];
81c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char result_1[1000];
82c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char mesg[2000];
83c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    skeleton.extract(0,  skeleton.length(), result, "UTF-8");
84c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString pat;
85c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    ((SimpleDateFormat*)dtfmt)->toPattern(pat);
86c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    pat.extract(0,  pat.length(), result_1, "UTF-8");
87c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    sprintf(mesg, "skeleton: %s; pattern: %s\n", result, result_1);
88c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    PRINTMESG(mesg)
89c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#endif
90c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
91c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    DateIntervalInfo* dtitvinf = new DateIntervalInfo(locale, status);
92b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return create(locale, dtitvinf, &skeleton, status);
93c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
94c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
95c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
96c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
97c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat* U_EXPORT2
98c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::createInstance(const UnicodeString& skeleton,
99c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   const DateIntervalInfo& dtitvinf,
100c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   UErrorCode& status) {
101c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return createInstance(skeleton, Locale::getDefault(), dtitvinf, status);
102c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
103c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
104c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
105c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat* U_EXPORT2
106c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::createInstance(const UnicodeString& skeleton,
107c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   const Locale& locale,
108c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   const DateIntervalInfo& dtitvinf,
109c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   UErrorCode& status) {
110c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    DateIntervalInfo* ptn = dtitvinf.clone();
111b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return create(locale, ptn, &skeleton, status);
112c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
113c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
114c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
115c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::DateIntervalFormat()
116c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru:   fInfo(NULL),
117c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fDateFormat(NULL),
118c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fFromCalendar(NULL),
119b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fToCalendar(NULL),
120b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fDtpng(NULL)
121c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{}
122c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
123c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
124c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::DateIntervalFormat(const DateIntervalFormat& itvfmt)
125c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru:   Format(itvfmt),
126c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fInfo(NULL),
127c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fDateFormat(NULL),
128c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fFromCalendar(NULL),
129b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fToCalendar(NULL),
130b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fDtpng(NULL) {
131c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    *this = itvfmt;
132c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
133c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
134c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
135c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat&
136c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::operator=(const DateIntervalFormat& itvfmt) {
137c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( this != &itvfmt ) {
138c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete fDateFormat;
139c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete fInfo;
140c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete fFromCalendar;
141c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete fToCalendar;
142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        delete fDtpng;
143c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( itvfmt.fDateFormat ) {
144c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fDateFormat = (SimpleDateFormat*)itvfmt.fDateFormat->clone();
145c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
146c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fDateFormat = NULL;
147c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
148c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( itvfmt.fInfo ) {
149c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fInfo = itvfmt.fInfo->clone();
150c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
151c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fInfo = NULL;
152c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
153c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( itvfmt.fFromCalendar ) {
154c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fFromCalendar = itvfmt.fFromCalendar->clone();
155c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
156c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fFromCalendar = NULL;
157c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
158c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( itvfmt.fToCalendar ) {
159c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fToCalendar = itvfmt.fToCalendar->clone();
160c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
161c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fToCalendar = NULL;
162c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
163c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fSkeleton = itvfmt.fSkeleton;
164c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int8_t i;
165c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        for ( i = 0; i< DateIntervalInfo::kIPI_MAX_INDEX; ++i ) {
166c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fIntervalPatterns[i] = itvfmt.fIntervalPatterns[i];
167c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
168b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (itvfmt.fDtpng) {
169b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fDtpng = itvfmt.fDtpng->clone();
170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
171c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
172c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return *this;
173c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
174c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
175c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
176c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::~DateIntervalFormat() {
177c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    delete fInfo;
178c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    delete fDateFormat;
179c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    delete fFromCalendar;
180c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    delete fToCalendar;
181b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    delete fDtpng;
182c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
183c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
184c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
185c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruFormat*
186c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::clone(void) const {
187c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return new DateIntervalFormat(*this);
188c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
189c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
190c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
191c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUBool
192c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::operator==(const Format& other) const {
19327f654740f2a26ad62a5c155af9199af9e69b889claireho    if (typeid(*this) == typeid(other)) {
19427f654740f2a26ad62a5c155af9199af9e69b889claireho        const DateIntervalFormat* fmt = (DateIntervalFormat*)&other;
195c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#ifdef DTITVFMT_DEBUG
196c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UBool equal;
197c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    equal = (this == fmt);
198c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
199c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    equal = (*fInfo == *fmt->fInfo);
200c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    equal = (*fDateFormat == *fmt->fDateFormat);
201c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    equal = fFromCalendar->isEquivalentTo(*fmt->fFromCalendar) ;
202c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    equal = fToCalendar->isEquivalentTo(*fmt->fToCalendar) ;
203c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    equal = (fSkeleton == fmt->fSkeleton);
204c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#endif
205c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UBool res;
206c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        res =  ( this == fmt ) ||
207c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru               ( Format::operator==(other) &&
208c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 fInfo &&
209c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 ( *fInfo == *fmt->fInfo ) &&
210c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 fDateFormat &&
211c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 ( *fDateFormat == *fmt->fDateFormat ) &&
212c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 fFromCalendar &&
213c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 fFromCalendar->isEquivalentTo(*fmt->fFromCalendar) &&
214c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 fToCalendar &&
215c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 fToCalendar->isEquivalentTo(*fmt->fToCalendar) &&
216b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                 fSkeleton == fmt->fSkeleton &&
217b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                 fDtpng &&
218b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                 (*fDtpng == *fmt->fDtpng) );
219c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int8_t i;
220c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        for (i = 0; i< DateIntervalInfo::kIPI_MAX_INDEX && res == TRUE; ++i ) {
221c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res =   ( fIntervalPatterns[i].firstPart ==
222c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                      fmt->fIntervalPatterns[i].firstPart) &&
223c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    ( fIntervalPatterns[i].secondPart ==
224c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                      fmt->fIntervalPatterns[i].secondPart ) &&
225c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    ( fIntervalPatterns[i].laterDateFirst ==
226c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                      fmt->fIntervalPatterns[i].laterDateFirst) ;
227c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
228c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return res;
229c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
230c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return FALSE;
231c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
232c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
233c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
234c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
235c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
236c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::format(const Formattable& obj,
237c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           UnicodeString& appendTo,
238c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           FieldPosition& fieldPosition,
239c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           UErrorCode& status) const {
240c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
241c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return appendTo;
242c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
243c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
244c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( obj.getType() == Formattable::kObject ) {
245c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        const UObject* formatObj = obj.getObject();
24627f654740f2a26ad62a5c155af9199af9e69b889claireho        const DateInterval* interval = dynamic_cast<const DateInterval*>(formatObj);
24727f654740f2a26ad62a5c155af9199af9e69b889claireho        if (interval != NULL){
24827f654740f2a26ad62a5c155af9199af9e69b889claireho            return format(interval, appendTo, fieldPosition, status);
249c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
250c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
251c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    status = U_ILLEGAL_ARGUMENT_ERROR;
252c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return appendTo;
253c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
254c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
255c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
256c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
257c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::format(const DateInterval* dtInterval,
258c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           UnicodeString& appendTo,
259c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           FieldPosition& fieldPosition,
260c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           UErrorCode& status) const {
261c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
262c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return appendTo;
263c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
264c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
265c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( fFromCalendar != NULL && fToCalendar != NULL &&
266c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         fDateFormat != NULL && fInfo != NULL ) {
267c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fFromCalendar->setTime(dtInterval->getFromDate(), status);
268c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fToCalendar->setTime(dtInterval->getToDate(), status);
269c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( U_SUCCESS(status) ) {
270c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return format(*fFromCalendar, *fToCalendar, appendTo,fieldPosition, status);
271c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
272c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
273c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return appendTo;
274c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
275c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
276c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
277c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
278c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::format(Calendar& fromCalendar,
279c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           Calendar& toCalendar,
280c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           UnicodeString& appendTo,
281c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           FieldPosition& pos,
282c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           UErrorCode& status) const {
283c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
284c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return appendTo;
285c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
286c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
287c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // not support different calendar types and time zones
288c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //if ( fromCalendar.getType() != toCalendar.getType() ) {
28950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if ( !fromCalendar.isEquivalentTo(toCalendar) ) {
290c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        status = U_ILLEGAL_ARGUMENT_ERROR;
291c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return appendTo;
292c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
293c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
294c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // First, find the largest different calendar field.
295c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UCalendarDateFields field = UCAL_FIELD_COUNT;
296c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
297c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( fromCalendar.get(UCAL_ERA,status) != toCalendar.get(UCAL_ERA,status)) {
298c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        field = UCAL_ERA;
299c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if ( fromCalendar.get(UCAL_YEAR, status) !=
300c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                toCalendar.get(UCAL_YEAR, status) ) {
301c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        field = UCAL_YEAR;
302c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if ( fromCalendar.get(UCAL_MONTH, status) !=
303c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                toCalendar.get(UCAL_MONTH, status) ) {
304c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        field = UCAL_MONTH;
305c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if ( fromCalendar.get(UCAL_DATE, status) !=
306c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                toCalendar.get(UCAL_DATE, status) ) {
307c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        field = UCAL_DATE;
308c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if ( fromCalendar.get(UCAL_AM_PM, status) !=
309c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                toCalendar.get(UCAL_AM_PM, status) ) {
310c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        field = UCAL_AM_PM;
311c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if ( fromCalendar.get(UCAL_HOUR, status) !=
312c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                toCalendar.get(UCAL_HOUR, status) ) {
313c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        field = UCAL_HOUR;
314c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if ( fromCalendar.get(UCAL_MINUTE, status) !=
315c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                toCalendar.get(UCAL_MINUTE, status) ) {
316c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        field = UCAL_MINUTE;
317c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
318c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
319c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
320c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return appendTo;
321c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
322c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( field == UCAL_FIELD_COUNT ) {
323c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        /* ignore the second/millisecond etc. small fields' difference.
324c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         * use single date when all the above are the same.
325c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         */
326c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return fDateFormat->format(fromCalendar, appendTo, pos);
327c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
328c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
329c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // following call should not set wrong status,
330c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // all the pass-in fields are valid till here
331c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t itvPtnIndex = DateIntervalInfo::calendarFieldToIntervalIndex(field,
332c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                                                        status);
333c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const PatternInfo& intervalPattern = fIntervalPatterns[itvPtnIndex];
334c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
335c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( intervalPattern.firstPart.isEmpty() &&
336c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         intervalPattern.secondPart.isEmpty() ) {
337c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( fDateFormat->isFieldUnitIgnored(field) ) {
338c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            /* the largest different calendar field is small than
339c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru             * the smallest calendar field in pattern,
340c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru             * return single date format.
341c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru             */
342c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return fDateFormat->format(fromCalendar, appendTo, pos);
343c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
344c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return fallbackFormat(fromCalendar, toCalendar, appendTo, pos, status);
345c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
346c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // If the first part in interval pattern is empty,
347c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // the 2nd part of it saves the full-pattern used in fall-back.
348c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // For a 'real' interval pattern, the first part will never be empty.
349c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( intervalPattern.firstPart.isEmpty() ) {
350c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // fall back
351c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UnicodeString originalPattern;
352c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fDateFormat->toPattern(originalPattern);
353c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fDateFormat->applyPattern(intervalPattern.secondPart);
354c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        appendTo = fallbackFormat(fromCalendar, toCalendar, appendTo, pos, status);
355c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fDateFormat->applyPattern(originalPattern);
356c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return appendTo;
357c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
358c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    Calendar* firstCal;
359c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    Calendar* secondCal;
360c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( intervalPattern.laterDateFirst ) {
361c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        firstCal = &toCalendar;
362c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        secondCal = &fromCalendar;
363c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
364c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        firstCal = &fromCalendar;
365c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        secondCal = &toCalendar;
366c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
367c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // break the interval pattern into 2 parts,
368c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // first part should not be empty,
369c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString originalPattern;
370c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fDateFormat->toPattern(originalPattern);
371c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fDateFormat->applyPattern(intervalPattern.firstPart);
372c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fDateFormat->format(*firstCal, appendTo, pos);
373c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( !intervalPattern.secondPart.isEmpty() ) {
374c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fDateFormat->applyPattern(intervalPattern.secondPart);
375c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fDateFormat->format(*secondCal, appendTo, pos);
376c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
377c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fDateFormat->applyPattern(originalPattern);
378c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return appendTo;
379c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
380c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
381c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
382c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
383c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
384c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::parseObject(const UnicodeString& /* source */,
385c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                Formattable& /* result */,
386c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                ParsePosition& /* parse_pos */) const {
387c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // parseObject(const UnicodeString&, Formattable&, UErrorCode&) const
388c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // will set status as U_INVALID_FORMAT_ERROR if
389c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // parse_pos is still 0
390c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
391c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
392c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
393c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
394c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
395c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruconst DateIntervalInfo*
396c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::getDateIntervalInfo() const {
397c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return fInfo;
398c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
399c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
400c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
401c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
402c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::setDateIntervalInfo(const DateIntervalInfo& newItvPattern,
403c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                        UErrorCode& status) {
404c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    delete fInfo;
405c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fInfo = new DateIntervalInfo(newItvPattern);
406c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( fDateFormat ) {
407c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        initializePattern(status);
408c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
409c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
410c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
411c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
412c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
413c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruconst DateFormat*
414c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::getDateFormat() const {
415c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return fDateFormat;
416c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
417c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
418c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
419b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
420b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoDateIntervalFormat::adoptTimeZone(TimeZone* zone)
421b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho{
422b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fDateFormat != NULL) {
423b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fDateFormat->adoptTimeZone(zone);
424b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
425b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // The fDateFormat has the master calendar for the DateIntervalFormat and has
426b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // ownership of any adopted TimeZone; fFromCalendar and fToCalendar are internal
427b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // work clones of that calendar (and should not also be given ownership of the
428b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // adopted TimeZone).
429b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fFromCalendar) {
430b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    	fFromCalendar->setTimeZone(*zone);
431b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
432b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fToCalendar) {
433b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    	fToCalendar->setTimeZone(*zone);
434b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
435b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
436b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
437b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
438b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoDateIntervalFormat::setTimeZone(const TimeZone& zone)
439b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho{
440b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fDateFormat != NULL) {
441b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fDateFormat->setTimeZone(zone);
442b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
443b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // The fDateFormat has the master calendar for the DateIntervalFormat;
444b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // fFromCalendar and fToCalendar are internal work clones of that calendar.
445b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fFromCalendar) {
446b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    	fFromCalendar->setTimeZone(zone);
447b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
448b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fToCalendar) {
449b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    	fToCalendar->setTimeZone(zone);
450b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
451b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
452b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
453b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst TimeZone&
454b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoDateIntervalFormat::getTimeZone() const
455b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho{
456b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fDateFormat != NULL) {
457b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return fDateFormat->getTimeZone();
458b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
459b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // If fDateFormat is NULL (unexpected), create default timezone.
460b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return *(TimeZone::createDefault());
461b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
462b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
463b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruDateIntervalFormat::DateIntervalFormat(const Locale& locale,
464c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       DateIntervalInfo* dtItvInfo,
465c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       const UnicodeString* skeleton,
466c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       UErrorCode& status)
467b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru:   fInfo(NULL),
468b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fDateFormat(NULL),
469b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fFromCalendar(NULL),
470b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fToCalendar(NULL),
471b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fDtpng(NULL)
472c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
473c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
474c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete dtItvInfo;
475c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
476c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
477b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fDtpng = DateTimePatternGenerator::createInstance(locale, status);
478b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    SimpleDateFormat* dtfmt = createSDFPatternInstance(*skeleton, locale,
479b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                                    fDtpng, status);
480b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if ( U_FAILURE(status) ) {
481b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        delete dtItvInfo;
482b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        delete fDtpng;
483b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        delete dtfmt;
484b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
485b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
486b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if ( dtfmt == NULL || dtItvInfo == NULL || fDtpng == NULL ) {
487c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
488c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // safe to delete NULL
489c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete dtfmt;
490c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete dtItvInfo;
491b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        delete fDtpng;
492c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
493c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
494c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( skeleton ) {
495c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fSkeleton = *skeleton;
496c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
497c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fInfo = dtItvInfo;
498b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fDateFormat = dtfmt;
499c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( dtfmt->getCalendar() ) {
500c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fFromCalendar = dtfmt->getCalendar()->clone();
501c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fToCalendar = dtfmt->getCalendar()->clone();
502c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
503c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fFromCalendar = NULL;
504c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fToCalendar = NULL;
505c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
506c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    initializePattern(status);
507c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
508c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
509c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
510b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruSimpleDateFormat* U_EXPORT2
511b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruDateIntervalFormat::createSDFPatternInstance(const UnicodeString& skeleton,
512b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                             const Locale& locale,
513b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                             DateTimePatternGenerator* dtpng,
514b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                             UErrorCode& status)
515b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru{
5161b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    DateFormat *df = DateFormat::internalCreateInstanceForSkeleton(
5171b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert            skeleton, locale, *dtpng, status);
5181b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    return static_cast<SimpleDateFormat *>(df);
519b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
520b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
521c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
522c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat* U_EXPORT2
523b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruDateIntervalFormat::create(const Locale& locale,
524c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           DateIntervalInfo* dtitvinf,
525c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           const UnicodeString* skeleton,
526c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           UErrorCode& status) {
527b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    DateIntervalFormat* f = new DateIntervalFormat(locale, dtitvinf,
528c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                                   skeleton, status);
529c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( f == NULL ) {
530c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
531c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete dtitvinf;
532c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if ( U_FAILURE(status) ) {
533c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // safe to delete f, although nothing acutally is saved
534c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete f;
535c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        f = 0;
536c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
537c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return f;
538c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
539c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
540c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
541c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
542c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru/**
543c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * Initialize interval patterns locale to this formatter
544c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
545c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * This code is a bit complicated since
546c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * 1. the interval patterns saved in resource bundle files are interval
547c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    patterns based on date or time only.
548c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    It does not have interval patterns based on both date and time.
549c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    Interval patterns on both date and time are algorithm generated.
550c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
551c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    For example, it has interval patterns on skeleton "dMy" and "hm",
552c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    but it does not have interval patterns on skeleton "dMyhm".
553c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
554c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    The rule to genearte interval patterns for both date and time skeleton are
555c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    1) when the year, month, or day differs, concatenate the two original
556c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    expressions with a separator between,
557c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    For example, interval pattern from "Jan 10, 2007 10:10 am"
558c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    to "Jan 11, 2007 10:10am" is
559c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    "Jan 10, 2007 10:10 am - Jan 11, 2007 10:10am"
560c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
561c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    2) otherwise, present the date followed by the range expression
562c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    for the time.
563c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    For example, interval pattern from "Jan 10, 2007 10:10 am"
564c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    to "Jan 10, 2007 11:10am" is
565c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    "Jan 10, 2007 10:10 am - 11:10am"
566c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
567c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * 2. even a pattern does not request a certion calendar field,
568c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    the interval pattern needs to include such field if such fields are
569c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    different between 2 dates.
570c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    For example, a pattern/skeleton is "hm", but the interval pattern
571c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    includes year, month, and date when year, month, and date differs.
572c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
573c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param status          output param set to success/failure code on exit
574b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * @stable ICU 4.0
575c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru */
576c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
577c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::initializePattern(UErrorCode& status) {
578c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
579c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
580c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
581c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const Locale& locale = fDateFormat->getSmpFmtLocale();
582c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( fSkeleton.isEmpty() ) {
583c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UnicodeString fullPattern;
584c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fDateFormat->toPattern(fullPattern);
585c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#ifdef DTITVFMT_DEBUG
586c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char result[1000];
587c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char result_1[1000];
588c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char mesg[2000];
589c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fSkeleton.extract(0,  fSkeleton.length(), result, "UTF-8");
590c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    sprintf(mesg, "in getBestSkeleton: fSkeleton: %s; \n", result);
591c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    PRINTMESG(mesg)
592c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#endif
593c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // fSkeleton is already set by createDateIntervalInstance()
594c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // or by createInstance(UnicodeString skeleton, .... )
595b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        fSkeleton = fDtpng->getSkeleton(fullPattern, status);
596c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( U_FAILURE(status) ) {
597c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return;
598c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
599c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
600c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
601c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // initialize the fIntervalPattern ordering
602c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int8_t i;
603c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for ( i = 0; i < DateIntervalInfo::kIPI_MAX_INDEX; ++i ) {
604c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fIntervalPatterns[i].laterDateFirst = fInfo->getDefaultOrder();
605c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
606c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
607c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* Check whether the skeleton is a combination of date and time.
608c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * For the complication reason 1 explained above.
609c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     */
610c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString dateSkeleton;
611c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString timeSkeleton;
612c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString normalizedTimeSkeleton;
613c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString normalizedDateSkeleton;
614c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
615c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
616c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* the difference between time skeleton and normalizedTimeSkeleton are:
61750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * 1. (Formerly, normalized time skeleton folded 'H' to 'h'; no longer true)
618c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * 2. 'a' is omitted in normalized time skeleton.
61950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * 3. there is only one appearance for 'h' or 'H', 'm','v', 'z' in normalized
620c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     *    time skeleton
621c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     *
622c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * The difference between date skeleton and normalizedDateSkeleton are:
623c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * 1. both 'y' and 'd' appear only once in normalizeDateSkeleton
624c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * 2. 'E' and 'EE' are normalized into 'EEE'
625c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * 3. 'MM' is normalized into 'M'
626c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     */
627c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    getDateTimeSkeleton(fSkeleton, dateSkeleton, normalizedDateSkeleton,
628c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                        timeSkeleton, normalizedTimeSkeleton);
629c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
630c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#ifdef DTITVFMT_DEBUG
631c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char result[1000];
632c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char result_1[1000];
633c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char mesg[2000];
634c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fSkeleton.extract(0,  fSkeleton.length(), result, "UTF-8");
635c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    sprintf(mesg, "in getBestSkeleton: fSkeleton: %s; \n", result);
636c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    PRINTMESG(mesg)
637c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#endif
638c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
639c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
640c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UBool found = setSeparateDateTimePtn(normalizedDateSkeleton,
641c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                         normalizedTimeSkeleton);
642c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
643c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( found == false ) {
644c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // use fallback
645c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // TODO: if user asks "m"(minute), but "d"(day) differ
646c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( timeSkeleton.length() != 0 ) {
647c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if ( dateSkeleton.length() == 0 ) {
648c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // prefix with yMd
649b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                timeSkeleton.insert(0, gDateFormatSkeleton[DateFormat::kShort], -1);
650b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                UnicodeString pattern = fDtpng->getBestPattern(timeSkeleton, status);
651c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                if ( U_FAILURE(status) ) {
652c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    return;
653c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                }
654c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // for fall back interval patterns,
655c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // the first part of the pattern is empty,
656c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // the second part of the pattern is the full-pattern
657c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // should be used in fall-back.
658c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                setPatternInfo(UCAL_DATE, NULL, &pattern, fInfo->getDefaultOrder());
659c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                setPatternInfo(UCAL_MONTH, NULL, &pattern, fInfo->getDefaultOrder());
660c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                setPatternInfo(UCAL_YEAR, NULL, &pattern, fInfo->getDefaultOrder());
661c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            } else {
662c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // TODO: fall back
663c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
664c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
665c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // TODO: fall back
666c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
667c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
668c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } // end of skeleton not found
669c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // interval patterns for skeleton are found in resource
670c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( timeSkeleton.length() == 0 ) {
671c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // done
672c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if ( dateSkeleton.length() == 0 ) {
673c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // prefix with yMd
674b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        timeSkeleton.insert(0, gDateFormatSkeleton[DateFormat::kShort], -1);
675b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UnicodeString pattern = fDtpng->getBestPattern(timeSkeleton, status);
676c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( U_FAILURE(status) ) {
677c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return;
678c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
679c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // for fall back interval patterns,
680c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // the first part of the pattern is empty,
681c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // the second part of the pattern is the full-pattern
682c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // should be used in fall-back.
683c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        setPatternInfo(UCAL_DATE, NULL, &pattern, fInfo->getDefaultOrder());
684c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        setPatternInfo(UCAL_MONTH, NULL, &pattern, fInfo->getDefaultOrder());
685c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        setPatternInfo(UCAL_YEAR, NULL, &pattern, fInfo->getDefaultOrder());
686c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
687c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        /* if both present,
688c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         * 1) when the year, month, or day differs,
689c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         * concatenate the two original expressions with a separator between,
690c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         * 2) otherwise, present the date followed by the
691c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         * range expression for the time.
692c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         */
693c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        /*
694c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         * 1) when the year, month, or day differs,
695c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         * concatenate the two original expressions with a separator between,
696c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         */
697c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // if field exists, use fall back
698c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UnicodeString skeleton = fSkeleton;
699c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( !fieldExistsInSkeleton(UCAL_DATE, dateSkeleton) ) {
700c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // prefix skeleton with 'd'
701c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            skeleton.insert(0, LOW_D);
702b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            setFallbackPattern(UCAL_DATE, skeleton, status);
703c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
704c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( !fieldExistsInSkeleton(UCAL_MONTH, dateSkeleton) ) {
705c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // then prefix skeleton with 'M'
706c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            skeleton.insert(0, CAP_M);
707b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            setFallbackPattern(UCAL_MONTH, skeleton, status);
708c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
709c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( !fieldExistsInSkeleton(UCAL_YEAR, dateSkeleton) ) {
710c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // then prefix skeleton with 'y'
711c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            skeleton.insert(0, LOW_Y);
712b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            setFallbackPattern(UCAL_YEAR, skeleton, status);
713c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
714c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
715c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        /*
716c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         * 2) otherwise, present the date followed by the
717c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         * range expression for the time.
718c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         */
719c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // Need the Date/Time pattern for concatnation the date with
720c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // the time interval.
721c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // The date/time pattern ( such as {0} {1} ) is saved in
722c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // calendar, that is why need to get the CalendarData here.
723c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        CalendarData* calData = new CalendarData(locale, NULL, status);
724c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
725c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( U_FAILURE(status) ) {
726c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            delete calData;
727c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return;
728c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
729c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
730c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( calData == NULL ) {
731c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            status = U_MEMORY_ALLOCATION_ERROR;
732c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return;
733c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
734c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
735c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        const UResourceBundle* dateTimePatternsRes = calData->getByKey(
736c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                           gDateTimePatternsTag, status);
737c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t dateTimeFormatLength;
738c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        const UChar* dateTimeFormat = ures_getStringByIndex(
739c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                            dateTimePatternsRes,
740c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                            (int32_t)DateFormat::kDateTime,
741c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                            &dateTimeFormatLength, &status);
742c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( U_FAILURE(status) ) {
743c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return;
744c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
745c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
746b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UnicodeString datePattern = fDtpng->getBestPattern(dateSkeleton, status);
747c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
748c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        concatSingleDate2TimeInterval(dateTimeFormat, dateTimeFormatLength,
749c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                      datePattern, UCAL_AM_PM, status);
750c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        concatSingleDate2TimeInterval(dateTimeFormat, dateTimeFormatLength,
751c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                      datePattern, UCAL_HOUR, status);
752c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        concatSingleDate2TimeInterval(dateTimeFormat, dateTimeFormatLength,
753c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                      datePattern, UCAL_MINUTE, status);
754c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete calData;
755c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
756c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
757c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
758c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
759c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
760c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid  U_EXPORT2
761c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::getDateTimeSkeleton(const UnicodeString& skeleton,
762c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                        UnicodeString& dateSkeleton,
763c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                        UnicodeString& normalizedDateSkeleton,
764c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                        UnicodeString& timeSkeleton,
765c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                        UnicodeString& normalizedTimeSkeleton) {
766c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // dateSkeleton follows the sequence of y*M*E*d*
767c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // timeSkeleton follows the sequence of hm*[v|z]?
768c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t ECount = 0;
769c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t dCount = 0;
770c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t MCount = 0;
771c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t yCount = 0;
772c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t hCount = 0;
77350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t HCount = 0;
774c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t mCount = 0;
775c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t vCount = 0;
776c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t zCount = 0;
777c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t i;
778c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
779c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for (i = 0; i < skeleton.length(); ++i) {
780c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UChar ch = skeleton[i];
781c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        switch ( ch ) {
782c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_E:
783c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            dateSkeleton.append(ch);
784c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++ECount;
785c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
786c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_D:
787c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            dateSkeleton.append(ch);
788c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++dCount;
789c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
790c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_M:
791c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            dateSkeleton.append(ch);
792c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++MCount;
793c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
794c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_Y:
795c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            dateSkeleton.append(ch);
796c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++yCount;
797c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
798c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_G:
799c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_Y:
800c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_U:
801c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_Q:
802c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_Q:
803c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_L:
804c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_L:
805c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_W:
806c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_W:
807c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_D:
808c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_F:
809c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_G:
810c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_E:
811c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_C:
812fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          case CAP_U:
813fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          case LOW_R:
814c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            normalizedDateSkeleton.append(ch);
815c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            dateSkeleton.append(ch);
816c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
817c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_A:
818c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // 'a' is implicitly handled
819c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            timeSkeleton.append(ch);
820c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
821c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_H:
822c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            timeSkeleton.append(ch);
823c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++hCount;
824c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
82550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho          case CAP_H:
82650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            timeSkeleton.append(ch);
82750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            ++HCount;
82850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            break;
829c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_M:
830c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            timeSkeleton.append(ch);
831c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++mCount;
832c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
833c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_Z:
834c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++zCount;
835c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            timeSkeleton.append(ch);
836c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
837c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_V:
838c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++vCount;
839c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            timeSkeleton.append(ch);
840c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
841c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_V:
842c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_Z:
843c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_K:
844c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_K:
845c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_J:
846c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_S:
847c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_S:
848c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_A:
849c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            timeSkeleton.append(ch);
850c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            normalizedTimeSkeleton.append(ch);
851c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
852c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
853c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
854c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
855c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* generate normalized form for date*/
856c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( yCount != 0 ) {
85759d709d503bab6e2b61931737e662dd293b40578ccornelius        for (i = 0; i < yCount; ++i) {
85859d709d503bab6e2b61931737e662dd293b40578ccornelius            normalizedDateSkeleton.append(LOW_Y);
85959d709d503bab6e2b61931737e662dd293b40578ccornelius        }
860c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
861c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( MCount != 0 ) {
862c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( MCount < 3 ) {
863c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            normalizedDateSkeleton.append(CAP_M);
864c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
865c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            int32_t i;
866c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            for ( i = 0; i < MCount && i < MAX_M_COUNT; ++i ) {
867c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 normalizedDateSkeleton.append(CAP_M);
868c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
869c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
870c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
871c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( ECount != 0 ) {
872c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( ECount <= 3 ) {
873c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            normalizedDateSkeleton.append(CAP_E);
874c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
875c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            int32_t i;
876c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            for ( i = 0; i < ECount && i < MAX_E_COUNT; ++i ) {
877c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 normalizedDateSkeleton.append(CAP_E);
878c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
879c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
880c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
881c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( dCount != 0 ) {
882c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        normalizedDateSkeleton.append(LOW_D);
883c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
884c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
885c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* generate normalized form for time */
88650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if ( HCount != 0 ) {
88750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        normalizedTimeSkeleton.append(CAP_H);
88850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
88950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    else if ( hCount != 0 ) {
890c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        normalizedTimeSkeleton.append(LOW_H);
891c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
892c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( mCount != 0 ) {
893c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        normalizedTimeSkeleton.append(LOW_M);
894c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
895c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( zCount != 0 ) {
896c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        normalizedTimeSkeleton.append(LOW_Z);
897c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
898c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( vCount != 0 ) {
899c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        normalizedTimeSkeleton.append(LOW_V);
900c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
901c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
902c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
903c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
904c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru/**
905c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * Generate date or time interval pattern from resource,
906c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * and set them into the interval pattern locale to this formatter.
907c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
908c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * It needs to handle the following:
909c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * 1. need to adjust field width.
910c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    For example, the interval patterns saved in DateIntervalInfo
911c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    includes "dMMMy", but not "dMMMMy".
912c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    Need to get interval patterns for dMMMMy from dMMMy.
913c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    Another example, the interval patterns saved in DateIntervalInfo
914c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    includes "hmv", but not "hmz".
915c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    Need to get interval patterns for "hmz' from 'hmv'
916c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
917c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * 2. there might be no pattern for 'y' differ for skeleton "Md",
918c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    in order to get interval patterns for 'y' differ,
919c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    need to look for it from skeleton 'yMd'
920c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
921c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param dateSkeleton   normalized date skeleton
922c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param timeSkeleton   normalized time skeleton
923c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @return               whether the resource is found for the skeleton.
924c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *                       TRUE if interval pattern found for the skeleton,
925c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *                       FALSE otherwise.
926b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * @stable ICU 4.0
927c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru */
928c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUBool
929c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::setSeparateDateTimePtn(
930c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                 const UnicodeString& dateSkeleton,
931c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                 const UnicodeString& timeSkeleton) {
932c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const UnicodeString* skeleton;
933c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // if both date and time skeleton present,
934c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // the final interval pattern might include time interval patterns
935c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // ( when, am_pm, hour, minute differ ),
936c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // but not date interval patterns ( when year, month, day differ ).
937c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // For year/month/day differ, it falls back to fall-back pattern.
938c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( timeSkeleton.length() != 0  ) {
939c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        skeleton = &timeSkeleton;
940c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
941c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        skeleton = &dateSkeleton;
942c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
943c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
944c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* interval patterns for skeleton "dMMMy" (but not "dMMMMy")
945c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * are defined in resource,
946c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * interval patterns for skeleton "dMMMMy" are calculated by
947c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * 1. get the best match skeleton for "dMMMMy", which is "dMMMy"
948c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * 2. get the interval patterns for "dMMMy",
949c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * 3. extend "MMM" to "MMMM" in above interval patterns for "dMMMMy"
950c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * getBestSkeleton() is step 1.
951c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     */
952c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // best skeleton, and the difference information
953c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int8_t differenceInfo = 0;
954c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const UnicodeString* bestSkeleton = fInfo->getBestSkeleton(*skeleton,
955c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                                               differenceInfo);
956c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* best skeleton could be NULL.
957c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru       For example: in "ca" resource file,
958c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru       interval format is defined as following
959c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru           intervalFormats{
960c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                fallback{"{0} - {1}"}
961c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
962c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru       there is no skeletons/interval patterns defined,
963c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru       and the best skeleton match could be NULL
964c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     */
965c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( bestSkeleton == NULL ) {
966c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return false;
967c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
968c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
969c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // difference:
970c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // 0 means the best matched skeleton is the same as input skeleton
971c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // 1 means the fields are the same, but field width are different
972c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // 2 means the only difference between fields are v/z,
973c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // -1 means there are other fields difference
974c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( differenceInfo == -1 ) {
975c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // skeleton has different fields, not only  v/z difference
976c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return false;
977c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
978c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
979c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( timeSkeleton.length() == 0 ) {
980c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UnicodeString extendedSkeleton;
981c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UnicodeString extendedBestSkeleton;
982c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // only has date skeleton
983c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        setIntervalPattern(UCAL_DATE, skeleton, bestSkeleton, differenceInfo,
984c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           &extendedSkeleton, &extendedBestSkeleton);
985c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
986c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UBool extended = setIntervalPattern(UCAL_MONTH, skeleton, bestSkeleton,
987c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                     differenceInfo,
988c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                     &extendedSkeleton, &extendedBestSkeleton);
989c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
990c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( extended ) {
991c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            bestSkeleton = &extendedBestSkeleton;
992c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            skeleton = &extendedSkeleton;
993c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
994c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        setIntervalPattern(UCAL_YEAR, skeleton, bestSkeleton, differenceInfo,
995c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           &extendedSkeleton, &extendedBestSkeleton);
996c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
997c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        setIntervalPattern(UCAL_MINUTE, skeleton, bestSkeleton, differenceInfo);
998c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        setIntervalPattern(UCAL_HOUR, skeleton, bestSkeleton, differenceInfo);
999c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        setIntervalPattern(UCAL_AM_PM, skeleton, bestSkeleton, differenceInfo);
1000c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1001c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return true;
1002c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1003c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1004c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1005c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1006c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
1007c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::setFallbackPattern(UCalendarDateFields field,
1008c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       const UnicodeString& skeleton,
1009c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       UErrorCode& status) {
1010c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
1011c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
1012c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1013b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UnicodeString pattern = fDtpng->getBestPattern(skeleton, status);
1014c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
1015c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
1016c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1017c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setPatternInfo(field, NULL, &pattern, fInfo->getDefaultOrder());
1018c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1019c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1020c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1021c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1022c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1023c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
1024c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::setPatternInfo(UCalendarDateFields field,
1025c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   const UnicodeString* firstPart,
1026c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   const UnicodeString* secondPart,
1027c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   UBool laterDateFirst) {
1028c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // for fall back interval patterns,
1029c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // the first part of the pattern is empty,
1030c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // the second part of the pattern is the full-pattern
1031c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // should be used in fall-back.
1032c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
1033c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // following should not set any wrong status.
1034c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t itvPtnIndex = DateIntervalInfo::calendarFieldToIntervalIndex(field,
1035c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                                                        status);
1036c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
1037c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
1038c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1039c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    PatternInfo& ptn = fIntervalPatterns[itvPtnIndex];
1040c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( firstPart ) {
1041c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        ptn.firstPart = *firstPart;
1042c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1043c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( secondPart ) {
1044c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        ptn.secondPart = *secondPart;
1045c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1046c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    ptn.laterDateFirst = laterDateFirst;
1047c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1048c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1049c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
1050c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::setIntervalPattern(UCalendarDateFields field,
1051c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       const UnicodeString& intervalPattern) {
1052c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UBool order = fInfo->getDefaultOrder();
1053c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setIntervalPattern(field, intervalPattern, order);
1054c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1055c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1056c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1057c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
1058c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::setIntervalPattern(UCalendarDateFields field,
1059c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       const UnicodeString& intervalPattern,
1060c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       UBool laterDateFirst) {
1061c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const UnicodeString* pattern = &intervalPattern;
1062c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UBool order = laterDateFirst;
1063c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // check for "latestFirst:" or "earliestFirst:" prefix
1064c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int8_t prefixLength = sizeof(gLaterFirstPrefix)/sizeof(gLaterFirstPrefix[0]);
1065c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int8_t earliestFirstLength = sizeof(gEarlierFirstPrefix)/sizeof(gEarlierFirstPrefix[0]);
1066c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString realPattern;
1067c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( intervalPattern.startsWith(gLaterFirstPrefix, prefixLength) ) {
1068c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        order = true;
1069c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        intervalPattern.extract(prefixLength,
1070c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                intervalPattern.length() - prefixLength,
1071c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                realPattern);
1072c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        pattern = &realPattern;
1073c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if ( intervalPattern.startsWith(gEarlierFirstPrefix,
1074c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                           earliestFirstLength) ) {
1075c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        order = false;
1076c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        intervalPattern.extract(earliestFirstLength,
1077c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                intervalPattern.length() - earliestFirstLength,
1078c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                realPattern);
1079c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        pattern = &realPattern;
1080c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1081c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1082c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t splitPoint = splitPatternInto2Part(*pattern);
1083c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1084c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString firstPart;
1085c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString secondPart;
1086c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    pattern->extract(0, splitPoint, firstPart);
1087c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( splitPoint < pattern->length() ) {
1088c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        pattern->extract(splitPoint, pattern->length()-splitPoint, secondPart);
1089c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1090c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setPatternInfo(field, &firstPart, &secondPart, order);
1091c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1092c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1093c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1094c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1095c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1096c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru/**
1097c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * Generate interval pattern from existing resource
1098c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
1099c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * It not only save the interval patterns,
1100c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * but also return the extended skeleton and its best match skeleton.
1101c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
1102c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param field           largest different calendar field
1103c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param skeleton        skeleton
1104c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param bestSkeleton    the best match skeleton which has interval pattern
1105c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *                        defined in resource
1106c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param differenceInfo  the difference between skeleton and best skeleton
1107c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *         0 means the best matched skeleton is the same as input skeleton
1108c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *         1 means the fields are the same, but field width are different
1109c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *         2 means the only difference between fields are v/z,
1110c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *        -1 means there are other fields difference
1111c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
1112c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param extendedSkeleton      extended skeleton
1113c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param extendedBestSkeleton  extended best match skeleton
1114c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @return                      whether the interval pattern is found
1115c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *                              through extending skeleton or not.
1116c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *                              TRUE if interval pattern is found by
1117c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *                              extending skeleton, FALSE otherwise.
1118b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * @stable ICU 4.0
1119c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru */
1120c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUBool
1121c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::setIntervalPattern(UCalendarDateFields field,
1122c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       const UnicodeString* skeleton,
1123c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       const UnicodeString* bestSkeleton,
1124c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       int8_t differenceInfo,
1125c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       UnicodeString* extendedSkeleton,
1126c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       UnicodeString* extendedBestSkeleton) {
1127c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
1128c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // following getIntervalPattern() should not generate error status
1129c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString pattern;
1130c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fInfo->getIntervalPattern(*bestSkeleton, field, pattern, status);
1131c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( pattern.isEmpty() ) {
1132c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // single date
1133c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( SimpleDateFormat::isFieldUnitIgnored(*bestSkeleton, field) ) {
1134c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // do nothing, format will handle it
1135c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return false;
1136c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1137c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1138c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // for 24 hour system, interval patterns in resource file
1139c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // might not include pattern when am_pm differ,
1140c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // which should be the same as hour differ.
1141c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // add it here for simplicity
1142c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( field == UCAL_AM_PM ) {
1143c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fInfo->getIntervalPattern(*bestSkeleton, UCAL_HOUR, pattern,status);
1144c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if ( !pattern.isEmpty() ) {
1145c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                setIntervalPattern(field, pattern);
1146c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1147c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return false;
1148c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1149c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // else, looking for pattern when 'y' differ for 'dMMMM' skeleton,
1150c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // first, get best match pattern "MMMd",
1151c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // since there is no pattern for 'y' differs for skeleton 'MMMd',
1152c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // need to look for it from skeleton 'yMMMd',
1153c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // if found, adjust field width in interval pattern from
1154c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // "MMM" to "MMMM".
1155c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UChar fieldLetter = fgCalendarFieldToPatternLetter[field];
1156c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( extendedSkeleton ) {
1157c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            *extendedSkeleton = *skeleton;
1158c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            *extendedBestSkeleton = *bestSkeleton;
1159c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            extendedSkeleton->insert(0, fieldLetter);
1160c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            extendedBestSkeleton->insert(0, fieldLetter);
1161c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // for example, looking for patterns when 'y' differ for
1162c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // skeleton "MMMM".
1163c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fInfo->getIntervalPattern(*extendedBestSkeleton,field,pattern,status);
1164c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if ( pattern.isEmpty() && differenceInfo == 0 ) {
1165c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // if there is no skeleton "yMMMM" defined,
1166c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // look for the best match skeleton, for example: "yMMM"
1167c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                const UnicodeString* tmpBest = fInfo->getBestSkeleton(
1168c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                        *extendedBestSkeleton, differenceInfo);
1169c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                if ( tmpBest != 0 && differenceInfo != -1 ) {
1170c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    fInfo->getIntervalPattern(*tmpBest, field, pattern, status);
1171c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    bestSkeleton = tmpBest;
1172c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                }
1173c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1174c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1175c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1176c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( !pattern.isEmpty() ) {
1177c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( differenceInfo != 0 ) {
1178c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            UnicodeString adjustIntervalPattern;
1179c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            adjustFieldWidth(*skeleton, *bestSkeleton, pattern, differenceInfo,
1180c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                              adjustIntervalPattern);
1181c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            setIntervalPattern(field, adjustIntervalPattern);
1182c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
1183c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            setIntervalPattern(field, pattern);
1184c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1185c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( extendedSkeleton && !extendedSkeleton->isEmpty() ) {
1186c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return TRUE;
1187c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1188c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1189c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return FALSE;
1190c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1191c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1192c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1193c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1194c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruint32_t  U_EXPORT2
1195c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::splitPatternInto2Part(const UnicodeString& intervalPattern) {
1196c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UBool inQuote = false;
1197c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar prevCh = 0;
1198c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t count = 0;
1199c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1200c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* repeatedPattern used to record whether a pattern has already seen.
1201c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru       It is a pattern applies to first calendar if it is first time seen,
1202c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru       otherwise, it is a pattern applies to the second calendar
1203c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     */
1204c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UBool patternRepeated[] =
1205c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {
1206c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
1207c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
1208c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //   P   Q   R   S   T   U   V   W   X   Y   Z
1209c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
1210c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
1211c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
1212c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //   p   q   r   s   t   u   v   w   x   y   z
1213c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
1214c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    };
1215c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1216c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int8_t PATTERN_CHAR_BASE = 0x41;
1217c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1218c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* loop through the pattern string character by character looking for
1219c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * the first repeated pattern letter, which breaks the interval pattern
1220c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * into 2 parts.
1221c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     */
1222c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t i;
1223c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UBool foundRepetition = false;
1224c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for (i = 0; i < intervalPattern.length(); ++i) {
1225c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UChar ch = intervalPattern.charAt(i);
1226c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1227c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (ch != prevCh && count > 0) {
1228c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // check the repeativeness of pattern letter
1229c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            UBool repeated = patternRepeated[(int)(prevCh - PATTERN_CHAR_BASE)];
1230c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if ( repeated == FALSE ) {
1231c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                patternRepeated[prevCh - PATTERN_CHAR_BASE] = TRUE;
1232c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            } else {
1233c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                foundRepetition = true;
1234c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                break;
1235c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1236c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            count = 0;
1237c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1238c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (ch == '\'') {
1239c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // Consecutive single quotes are a single quote literal,
1240c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // either outside of quotes or between quotes
1241c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if ((i+1) < intervalPattern.length() &&
1242c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                intervalPattern.charAt(i+1) == '\'') {
1243c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                ++i;
1244c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            } else {
1245c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                inQuote = ! inQuote;
1246c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1247c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1248c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        else if (!inQuote && ((ch >= 0x0061 /*'a'*/ && ch <= 0x007A /*'z'*/)
1249c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    || (ch >= 0x0041 /*'A'*/ && ch <= 0x005A /*'Z'*/))) {
1250c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // ch is a date-time pattern character
1251c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            prevCh = ch;
1252c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++count;
1253c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1254c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1255c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // check last pattern char, distinguish
1256c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // "dd MM" ( no repetition ),
1257c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // "d-d"(last char repeated ), and
1258c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // "d-d MM" ( repetition found )
1259c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( count > 0 && foundRepetition == FALSE ) {
1260c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( patternRepeated[(int)(prevCh - PATTERN_CHAR_BASE)] == FALSE ) {
1261c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            count = 0;
1262c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1263c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1264c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (i - count);
1265c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1266c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1267c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1268c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1269c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
1270c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::fallbackFormat(Calendar& fromCalendar,
1271c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   Calendar& toCalendar,
1272c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   UnicodeString& appendTo,
1273c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   FieldPosition& pos,
1274c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   UErrorCode& status) const {
1275c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
1276c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return appendTo;
1277c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1278c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // the fall back
1279c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // no need delete earlierDate and laterDate since they are adopted
1280c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString* earlierDate = new UnicodeString();
1281c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    *earlierDate = fDateFormat->format(fromCalendar, *earlierDate, pos);
1282c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString* laterDate = new UnicodeString();
1283c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    *laterDate = fDateFormat->format(toCalendar, *laterDate, pos);
1284c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString fallbackPattern;
1285c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fInfo->getFallbackIntervalPattern(fallbackPattern);
1286c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    Formattable fmtArray[2];
1287c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fmtArray[0].adoptString(earlierDate);
1288c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fmtArray[1].adoptString(laterDate);
1289c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1290c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString fallback;
1291c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    MessageFormat::format(fallbackPattern, fmtArray, 2, fallback, status);
1292c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_SUCCESS(status) ) {
1293c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        appendTo.append(fallback);
1294c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1295c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return appendTo;
1296c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1297c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1298c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1299c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1300c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1301c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUBool  U_EXPORT2
1302c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::fieldExistsInSkeleton(UCalendarDateFields field,
1303c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                          const UnicodeString& skeleton)
1304c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
1305c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const UChar fieldChar = fgCalendarFieldToPatternLetter[field];
1306c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return ( (skeleton.indexOf(fieldChar) == -1)?FALSE:TRUE ) ;
1307c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1308c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1309c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1310c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1311c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid  U_EXPORT2
1312c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::adjustFieldWidth(const UnicodeString& inputSkeleton,
1313c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 const UnicodeString& bestMatchSkeleton,
1314c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 const UnicodeString& bestIntervalPattern,
1315c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 int8_t differenceInfo,
1316c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 UnicodeString& adjustedPtn) {
1317c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    adjustedPtn = bestIntervalPattern;
1318c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t inputSkeletonFieldWidth[] =
1319c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {
1320c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
1321c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
1322c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //   P   Q   R   S   T   U   V   W   X   Y   Z
1323c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
1324c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
1325c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
1326c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //   p   q   r   s   t   u   v   w   x   y   z
1327c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
1328c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    };
1329c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1330c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t bestMatchSkeletonFieldWidth[] =
1331c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {
1332c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
1333c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
1334c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //   P   Q   R   S   T   U   V   W   X   Y   Z
1335c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
1336c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
1337c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
1338c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //   p   q   r   s   t   u   v   w   x   y   z
1339c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
1340c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    };
1341c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1342c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    DateIntervalInfo::parseSkeleton(inputSkeleton, inputSkeletonFieldWidth);
1343c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    DateIntervalInfo::parseSkeleton(bestMatchSkeleton, bestMatchSkeletonFieldWidth);
1344c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( differenceInfo == 2 ) {
1345b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        adjustedPtn.findAndReplace(UnicodeString((UChar)0x76 /* v */),
1346b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                   UnicodeString((UChar)0x7a /* z */));
1347c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1348c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1349c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UBool inQuote = false;
1350c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar prevCh = 0;
1351c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t count = 0;
1352c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1353c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const int8_t PATTERN_CHAR_BASE = 0x41;
1354c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1355c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // loop through the pattern string character by character
1356c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t adjustedPtnLength = adjustedPtn.length();
1357c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t i;
1358c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for (i = 0; i < adjustedPtnLength; ++i) {
1359c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UChar ch = adjustedPtn.charAt(i);
1360c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (ch != prevCh && count > 0) {
1361c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // check the repeativeness of pattern letter
1362c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            UChar skeletonChar = prevCh;
1363c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if ( skeletonChar ==  CAP_L ) {
1364c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // there is no "L" (always be "M") in skeleton,
1365c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // but there is "L" in pattern.
1366c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // for skeleton "M+", the pattern might be "...L..."
1367c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                skeletonChar = CAP_M;
1368c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1369c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            int32_t fieldCount = bestMatchSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
1370c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            int32_t inputFieldCount = inputSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
1371c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if ( fieldCount == count && inputFieldCount > fieldCount ) {
1372c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                count = inputFieldCount - fieldCount;
1373c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                int32_t j;
1374c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                for ( j = 0; j < count; ++j ) {
1375c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    adjustedPtn.insert(i, prevCh);
1376c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                }
1377c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                i += count;
1378c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                adjustedPtnLength += count;
1379c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1380c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            count = 0;
1381c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1382c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (ch == '\'') {
1383c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // Consecutive single quotes are a single quote literal,
1384c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // either outside of quotes or between quotes
1385c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if ((i+1) < adjustedPtn.length() && adjustedPtn.charAt(i+1) == '\'') {
1386c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                ++i;
1387c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            } else {
1388c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                inQuote = ! inQuote;
1389c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1390c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1391c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        else if ( ! inQuote && ((ch >= 0x0061 /*'a'*/ && ch <= 0x007A /*'z'*/)
1392c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    || (ch >= 0x0041 /*'A'*/ && ch <= 0x005A /*'Z'*/))) {
1393c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // ch is a date-time pattern character
1394c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            prevCh = ch;
1395c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++count;
1396c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1397c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1398c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( count > 0 ) {
1399c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // last item
1400c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // check the repeativeness of pattern letter
1401c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UChar skeletonChar = prevCh;
1402c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( skeletonChar == CAP_L ) {
1403c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // there is no "L" (always be "M") in skeleton,
1404c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // but there is "L" in pattern.
1405c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // for skeleton "M+", the pattern might be "...L..."
1406c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            skeletonChar = CAP_M;
1407c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1408c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t fieldCount = bestMatchSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
1409c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t inputFieldCount = inputSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
1410c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( fieldCount == count && inputFieldCount > fieldCount ) {
1411c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            count = inputFieldCount - fieldCount;
1412c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            int32_t j;
1413c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            for ( j = 0; j < count; ++j ) {
1414c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                adjustedPtn.append(prevCh);
1415c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1416c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1417c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1418c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1419c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1420c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1421c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1422c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
1423c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::concatSingleDate2TimeInterval(const UChar* format,
1424c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                              int32_t formatLen,
1425c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                              const UnicodeString& datePattern,
1426c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                              UCalendarDateFields field,
1427c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                              UErrorCode& status) {
1428c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // following should not set wrong status
1429c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t itvPtnIndex = DateIntervalInfo::calendarFieldToIntervalIndex(field,
1430c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                                                        status);
1431c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
1432c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
1433c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1434c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    PatternInfo&  timeItvPtnInfo = fIntervalPatterns[itvPtnIndex];
1435c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( !timeItvPtnInfo.firstPart.isEmpty() ) {
1436c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // UnicodeString allocated here is adopted, so no need to delete
1437c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UnicodeString* timeIntervalPattern = new UnicodeString(timeItvPtnInfo.firstPart);
1438c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        timeIntervalPattern->append(timeItvPtnInfo.secondPart);
1439c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UnicodeString* dateStr = new UnicodeString(datePattern);
1440c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        Formattable fmtArray[2];
1441c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fmtArray[0].adoptString(timeIntervalPattern);
1442c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fmtArray[1].adoptString(dateStr);
1443c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UnicodeString combinedPattern;
1444c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        MessageFormat::format(UnicodeString(TRUE, format, formatLen),
1445c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                              fmtArray, 2, combinedPattern, status);
1446c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( U_FAILURE(status) ) {
1447c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return;
1448c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1449c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        setIntervalPattern(field, combinedPattern, timeItvPtnInfo.laterDateFirst);
1450c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1451c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // else: fall back
1452c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // it should not happen if the interval format defined is valid
1453c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1454c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1455c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1456c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1457c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruconst UChar
1458c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::fgCalendarFieldToPatternLetter[] =
1459c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
1460c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /*GyM*/ CAP_G, LOW_Y, CAP_M,
1461c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /*wWd*/ LOW_W, CAP_W, LOW_D,
1462c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /*DEF*/ CAP_D, CAP_E, CAP_F,
1463c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /*ahH*/ LOW_A, LOW_H, CAP_H,
1464fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    /*msS*/ LOW_M, LOW_S, CAP_S, // MINUTE, SECOND, MILLISECOND
1465fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    /*z.Y*/ LOW_Z, SPACE, CAP_Y, // ZONE_OFFSET, DST_OFFSET, YEAR_WOY,
1466fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    /*eug*/ LOW_E, LOW_U, LOW_G, // DOW_LOCAL, EXTENDED_YEAR, JULIAN_DAY,
1467fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    /*A..*/ CAP_A, SPACE, SPACE, // MILLISECONDS_IN_DAY, IS_LEAP_MONTH, FIELD_COUNT
1468c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru};
1469c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1470c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1471c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruU_NAMESPACE_END
1472c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1473c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#endif
1474