164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// Copyright (C) 2016 and later: Unicode, Inc. and others.
264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html
3c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru/*******************************************************************************
48de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert* Copyright (C) 2008-2016, International Business Machines Corporation and
5c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru* others. All Rights Reserved.
6c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru*******************************************************************************
7c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru*
864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert* File DTITVFMT.CPP
9c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru*
10c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru*******************************************************************************
11c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru*/
12c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "utypeinfo.h"  // for 'typeid' to work
1427f654740f2a26ad62a5c155af9199af9e69b889claireho
15c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "unicode/dtitvfmt.h"
16c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
17c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
18c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
19b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//TODO: put in compilation
20c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru//#define DTITVFMT_DEBUG 1
21c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
228de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert#include "unicode/calendar.h"
23c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "unicode/dtptngen.h"
24c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "unicode/dtitvinf.h"
258de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert#include "unicode/simpleformatter.h"
268de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert#include "cmemory.h"
278de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert#include "cstring.h"
28c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "dtitv_impl.h"
298de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert#include "mutex.h"
3064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#include "uresimp.h"
31c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
3264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#ifdef DTITVFMT_DEBUG
33c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include <iostream>
34c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#endif
35c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
36c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruU_NAMESPACE_BEGIN
37c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
38c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
39c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
4064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#ifdef DTITVFMT_DEBUG
41c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#define PRINTMESG(msg) { std::cout << "(" << __FILE__ << ":" << __LINE__ << ") " << msg << "\n"; }
42c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#endif
43c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
44c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
45c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic const UChar gDateFormatSkeleton[][11] = {
46c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru//yMMMMEEEEd
47c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{LOW_Y, CAP_M, CAP_M, CAP_M, CAP_M, CAP_E, CAP_E, CAP_E, CAP_E, LOW_D, 0},
48c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru//yMMMMd
49c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{LOW_Y, CAP_M, CAP_M, CAP_M, CAP_M, LOW_D, 0},
50c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru//yMMMd
51c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{LOW_Y, CAP_M, CAP_M, CAP_M, LOW_D, 0},
52c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru//yMd
53c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{LOW_Y, CAP_M, LOW_D, 0} };
54c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
55c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
5664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertstatic const char gCalendarTag[] = "calendar";
5764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertstatic const char gGregorianTag[] = "gregorian";
5864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertstatic const char gDateTimePatternsTag[] = "DateTimePatterns";
59c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
60c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
61c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru// latestFirst:
62b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-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};
63c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
64c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru// earliestFirst:
65b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-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};
66c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
67c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
68c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateIntervalFormat)
69c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
7064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// Mutex, protects access to fDateFormat, fFromCalendar and fToCalendar.
718de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert//        Needed because these data members are modified by const methods of DateIntervalFormat.
72c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
738de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubertstatic UMutex gFormatterMutex = U_MUTEX_INITIALIZER;
74c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
75c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat* U_EXPORT2
7664339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertDateIntervalFormat::createInstance(const UnicodeString& skeleton,
77c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   UErrorCode& status) {
78c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return createInstance(skeleton, Locale::getDefault(), status);
79c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
80c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
81c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
82c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat* U_EXPORT2
8364339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertDateIntervalFormat::createInstance(const UnicodeString& skeleton,
8464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                                   const Locale& locale,
85c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   UErrorCode& status) {
86c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#ifdef DTITVFMT_DEBUG
87c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char result[1000];
88c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char result_1[1000];
89c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char mesg[2000];
90c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    skeleton.extract(0,  skeleton.length(), result, "UTF-8");
91c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString pat;
92c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    ((SimpleDateFormat*)dtfmt)->toPattern(pat);
93c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    pat.extract(0,  pat.length(), result_1, "UTF-8");
94c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    sprintf(mesg, "skeleton: %s; pattern: %s\n", result, result_1);
95c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    PRINTMESG(mesg)
96c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#endif
97c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
98c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    DateIntervalInfo* dtitvinf = new DateIntervalInfo(locale, status);
99b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return create(locale, dtitvinf, &skeleton, status);
100c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
101c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
102c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
103c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
104c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat* U_EXPORT2
105c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::createInstance(const UnicodeString& skeleton,
106c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   const DateIntervalInfo& dtitvinf,
107c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   UErrorCode& status) {
108c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return createInstance(skeleton, Locale::getDefault(), dtitvinf, status);
109c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
110c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
111c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
112c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat* U_EXPORT2
113c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::createInstance(const UnicodeString& skeleton,
114c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   const Locale& locale,
115c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   const DateIntervalInfo& dtitvinf,
116c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   UErrorCode& status) {
117c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    DateIntervalInfo* ptn = dtitvinf.clone();
118b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return create(locale, ptn, &skeleton, status);
119c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
120c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
121c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
122c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::DateIntervalFormat()
123c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru:   fInfo(NULL),
124c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fDateFormat(NULL),
125c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fFromCalendar(NULL),
126b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fToCalendar(NULL),
127c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    fLocale(Locale::getRoot()),
128c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    fDatePattern(NULL),
129c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    fTimePattern(NULL),
130c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    fDateTimeFormat(NULL)
131c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{}
132c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
133c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
134c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::DateIntervalFormat(const DateIntervalFormat& itvfmt)
135c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru:   Format(itvfmt),
136c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fInfo(NULL),
137c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fDateFormat(NULL),
138c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fFromCalendar(NULL),
139b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fToCalendar(NULL),
140c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    fLocale(itvfmt.fLocale),
141c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    fDatePattern(NULL),
142c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    fTimePattern(NULL),
143c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    fDateTimeFormat(NULL) {
144c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    *this = itvfmt;
145c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
146c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
147c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
148c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat&
149c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::operator=(const DateIntervalFormat& itvfmt) {
150c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( this != &itvfmt ) {
151c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete fDateFormat;
152c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete fInfo;
153c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete fFromCalendar;
154c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete fToCalendar;
155c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        delete fDatePattern;
156c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        delete fTimePattern;
157c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        delete fDateTimeFormat;
1588de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        {
1598de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            Mutex lock(&gFormatterMutex);
1608de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            if ( itvfmt.fDateFormat ) {
1618de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                fDateFormat = (SimpleDateFormat*)itvfmt.fDateFormat->clone();
1628de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            } else {
1638de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                fDateFormat = NULL;
1648de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            }
1658de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            if ( itvfmt.fFromCalendar ) {
1668de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                fFromCalendar = itvfmt.fFromCalendar->clone();
1678de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            } else {
1688de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                fFromCalendar = NULL;
1698de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            }
1708de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            if ( itvfmt.fToCalendar ) {
1718de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                fToCalendar = itvfmt.fToCalendar->clone();
1728de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            } else {
1738de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                fToCalendar = NULL;
1748de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            }
175c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
176c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( itvfmt.fInfo ) {
177c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fInfo = itvfmt.fInfo->clone();
178c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
179c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fInfo = NULL;
180c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
181c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fSkeleton = itvfmt.fSkeleton;
182c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int8_t i;
183c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        for ( i = 0; i< DateIntervalInfo::kIPI_MAX_INDEX; ++i ) {
184c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fIntervalPatterns[i] = itvfmt.fIntervalPatterns[i];
185c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
186c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fLocale = itvfmt.fLocale;
187c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fDatePattern    = (itvfmt.fDatePattern)?    (UnicodeString*)itvfmt.fDatePattern->clone(): NULL;
188c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fTimePattern    = (itvfmt.fTimePattern)?    (UnicodeString*)itvfmt.fTimePattern->clone(): NULL;
189c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fDateTimeFormat = (itvfmt.fDateTimeFormat)? (UnicodeString*)itvfmt.fDateTimeFormat->clone(): NULL;
190c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
191c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return *this;
192c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
193c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
194c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
195c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::~DateIntervalFormat() {
196c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    delete fInfo;
197c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    delete fDateFormat;
198c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    delete fFromCalendar;
199c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    delete fToCalendar;
200c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    delete fDatePattern;
201c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    delete fTimePattern;
202c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    delete fDateTimeFormat;
203c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
204c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
205c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
206c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruFormat*
207c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::clone(void) const {
208c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return new DateIntervalFormat(*this);
209c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
210c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
211c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
212c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUBool
213c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::operator==(const Format& other) const {
2148de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (typeid(*this) != typeid(other)) {return FALSE;}
2158de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    const DateIntervalFormat* fmt = (DateIntervalFormat*)&other;
2168de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (this == fmt) {return TRUE;}
2178de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (!Format::operator==(other)) {return FALSE;}
2188de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if ((fInfo != fmt->fInfo) && (fInfo == NULL || fmt->fInfo == NULL)) {return FALSE;}
2198de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (fInfo && fmt->fInfo && (*fInfo != *fmt->fInfo )) {return FALSE;}
2208de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    {
2218de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        Mutex lock(&gFormatterMutex);
2228de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        if (fDateFormat != fmt->fDateFormat && (fDateFormat == NULL || fmt->fDateFormat == NULL)) {return FALSE;}
2238de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        if (fDateFormat && fmt->fDateFormat && (*fDateFormat != *fmt->fDateFormat)) {return FALSE;}
2248de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    }
22564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // note: fFromCalendar and fToCalendar hold no persistent state, and therefore do not participate in operator ==.
22664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    //       fDateFormat has the master calendar for the DateIntervalFormat.
2278de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (fSkeleton != fmt->fSkeleton) {return FALSE;}
2288de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (fDatePattern != fmt->fDatePattern && (fDatePattern == NULL || fmt->fDatePattern == NULL)) {return FALSE;}
2298de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (fDatePattern && fmt->fDatePattern && (*fDatePattern != *fmt->fDatePattern)) {return FALSE;}
2308de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (fTimePattern != fmt->fTimePattern && (fTimePattern == NULL || fmt->fTimePattern == NULL)) {return FALSE;}
2318de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (fTimePattern && fmt->fTimePattern && (*fTimePattern != *fmt->fTimePattern)) {return FALSE;}
2328de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (fDateTimeFormat != fmt->fDateTimeFormat && (fDateTimeFormat == NULL || fmt->fDateTimeFormat == NULL)) {return FALSE;}
2338de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (fDateTimeFormat && fmt->fDateTimeFormat && (*fDateTimeFormat != *fmt->fDateTimeFormat)) {return FALSE;}
2348de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (fLocale != fmt->fLocale) {return FALSE;}
2358de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
2368de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    for (int32_t i = 0; i< DateIntervalInfo::kIPI_MAX_INDEX; ++i ) {
2378de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        if (fIntervalPatterns[i].firstPart != fmt->fIntervalPatterns[i].firstPart) {return FALSE;}
2388de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        if (fIntervalPatterns[i].secondPart != fmt->fIntervalPatterns[i].secondPart ) {return FALSE;}
2398de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        if (fIntervalPatterns[i].laterDateFirst != fmt->fIntervalPatterns[i].laterDateFirst) {return FALSE;}
2408de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    }
2418de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    return TRUE;
242c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
243c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
244c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
245c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
246c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::format(const Formattable& obj,
247c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           UnicodeString& appendTo,
248c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           FieldPosition& fieldPosition,
249c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           UErrorCode& status) const {
250c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
251c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return appendTo;
252c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
253c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
254c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( obj.getType() == Formattable::kObject ) {
255c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        const UObject* formatObj = obj.getObject();
25627f654740f2a26ad62a5c155af9199af9e69b889claireho        const DateInterval* interval = dynamic_cast<const DateInterval*>(formatObj);
2578de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        if (interval != NULL) {
25827f654740f2a26ad62a5c155af9199af9e69b889claireho            return format(interval, appendTo, fieldPosition, status);
259c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
260c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
261c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    status = U_ILLEGAL_ARGUMENT_ERROR;
262c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return appendTo;
263c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
264c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
265c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
266c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
267c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::format(const DateInterval* dtInterval,
268c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           UnicodeString& appendTo,
269c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           FieldPosition& fieldPosition,
270c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           UErrorCode& status) const {
271c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
272c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return appendTo;
273c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
2748de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (fFromCalendar == NULL || fToCalendar == NULL || fDateFormat == NULL || fInfo == NULL) {
2758de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        status = U_INVALID_STATE_ERROR;
2768de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        return appendTo;
277c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
2788de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
2798de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    Mutex lock(&gFormatterMutex);
2808de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    fFromCalendar->setTime(dtInterval->getFromDate(), status);
2818de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    fToCalendar->setTime(dtInterval->getToDate(), status);
2828de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    return formatImpl(*fFromCalendar, *fToCalendar, appendTo,fieldPosition, status);
283c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
284c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
285c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
286c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
287c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::format(Calendar& fromCalendar,
288c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           Calendar& toCalendar,
289c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           UnicodeString& appendTo,
290c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           FieldPosition& pos,
291c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           UErrorCode& status) const {
2928de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    Mutex lock(&gFormatterMutex);
2938de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    return formatImpl(fromCalendar, toCalendar, appendTo, pos, status);
2948de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert}
29564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
2968de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
2978de051c3d18a56cc126f0f44e368495a52f9148cFredrik RoubertUnicodeString&
2988de051c3d18a56cc126f0f44e368495a52f9148cFredrik RoubertDateIntervalFormat::formatImpl(Calendar& fromCalendar,
2998de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                           Calendar& toCalendar,
3008de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                           UnicodeString& appendTo,
3018de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                           FieldPosition& pos,
3028de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                           UErrorCode& status) const {
303c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
304c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return appendTo;
305c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
306c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
307c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // not support different calendar types and time zones
308c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //if ( fromCalendar.getType() != toCalendar.getType() ) {
30950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if ( !fromCalendar.isEquivalentTo(toCalendar) ) {
310c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        status = U_ILLEGAL_ARGUMENT_ERROR;
311c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return appendTo;
312c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
313c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
314c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // First, find the largest different calendar field.
315c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UCalendarDateFields field = UCAL_FIELD_COUNT;
316c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
317c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( fromCalendar.get(UCAL_ERA,status) != toCalendar.get(UCAL_ERA,status)) {
318c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        field = UCAL_ERA;
31964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    } else if ( fromCalendar.get(UCAL_YEAR, status) !=
320c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                toCalendar.get(UCAL_YEAR, status) ) {
321c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        field = UCAL_YEAR;
322c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if ( fromCalendar.get(UCAL_MONTH, status) !=
323c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                toCalendar.get(UCAL_MONTH, status) ) {
324c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        field = UCAL_MONTH;
325c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if ( fromCalendar.get(UCAL_DATE, status) !=
326c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                toCalendar.get(UCAL_DATE, status) ) {
327c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        field = UCAL_DATE;
328c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if ( fromCalendar.get(UCAL_AM_PM, status) !=
329c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                toCalendar.get(UCAL_AM_PM, status) ) {
330c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        field = UCAL_AM_PM;
331c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if ( fromCalendar.get(UCAL_HOUR, status) !=
332c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                toCalendar.get(UCAL_HOUR, status) ) {
333c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        field = UCAL_HOUR;
334c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if ( fromCalendar.get(UCAL_MINUTE, status) !=
335c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                toCalendar.get(UCAL_MINUTE, status) ) {
336c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        field = UCAL_MINUTE;
337c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    } else if ( fromCalendar.get(UCAL_SECOND, status) !=
338c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                toCalendar.get(UCAL_SECOND, status) ) {
339c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        field = UCAL_SECOND;
340c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
341c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
342c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
343c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return appendTo;
344c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
345c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( field == UCAL_FIELD_COUNT ) {
346c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        /* ignore the millisecond etc. small fields' difference.
347c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         * use single date when all the above are the same.
348c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         */
349c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return fDateFormat->format(fromCalendar, appendTo, pos);
350c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
351c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    UBool fromToOnSameDay = (field==UCAL_AM_PM || field==UCAL_HOUR || field==UCAL_MINUTE || field==UCAL_SECOND);
35264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
353c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // following call should not set wrong status,
354c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // all the pass-in fields are valid till here
355c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t itvPtnIndex = DateIntervalInfo::calendarFieldToIntervalIndex(field,
356c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                                                        status);
357c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const PatternInfo& intervalPattern = fIntervalPatterns[itvPtnIndex];
358c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
359c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( intervalPattern.firstPart.isEmpty() &&
360c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         intervalPattern.secondPart.isEmpty() ) {
361c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( fDateFormat->isFieldUnitIgnored(field) ) {
362c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            /* the largest different calendar field is small than
363c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru             * the smallest calendar field in pattern,
364c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru             * return single date format.
365c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru             */
366c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return fDateFormat->format(fromCalendar, appendTo, pos);
367c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
368c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return fallbackFormat(fromCalendar, toCalendar, fromToOnSameDay, appendTo, pos, status);
369c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
37064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // If the first part in interval pattern is empty,
371c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // the 2nd part of it saves the full-pattern used in fall-back.
372c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // For a 'real' interval pattern, the first part will never be empty.
373c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( intervalPattern.firstPart.isEmpty() ) {
374c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // fall back
375c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UnicodeString originalPattern;
376c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fDateFormat->toPattern(originalPattern);
377c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fDateFormat->applyPattern(intervalPattern.secondPart);
378c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        appendTo = fallbackFormat(fromCalendar, toCalendar, fromToOnSameDay, appendTo, pos, status);
379c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fDateFormat->applyPattern(originalPattern);
380c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return appendTo;
381c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
382c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    Calendar* firstCal;
383c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    Calendar* secondCal;
384c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( intervalPattern.laterDateFirst ) {
385c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        firstCal = &toCalendar;
386c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        secondCal = &fromCalendar;
387c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
388c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        firstCal = &fromCalendar;
389c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        secondCal = &toCalendar;
390c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
391c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // break the interval pattern into 2 parts,
39264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // first part should not be empty,
393c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString originalPattern;
394c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fDateFormat->toPattern(originalPattern);
395c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fDateFormat->applyPattern(intervalPattern.firstPart);
396c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fDateFormat->format(*firstCal, appendTo, pos);
397c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( !intervalPattern.secondPart.isEmpty() ) {
398c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fDateFormat->applyPattern(intervalPattern.secondPart);
399c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        FieldPosition otherPos;
400c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        otherPos.setField(pos.getField());
401c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fDateFormat->format(*secondCal, appendTo, otherPos);
402c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        if (pos.getEndIndex() == 0 && otherPos.getEndIndex() > 0) {
403c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            pos = otherPos;
404c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        }
405c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
406c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fDateFormat->applyPattern(originalPattern);
407c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return appendTo;
408c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
409c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
410c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
411c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
412c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
41364339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertDateIntervalFormat::parseObject(const UnicodeString& /* source */,
414c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                Formattable& /* result */,
415c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                ParsePosition& /* parse_pos */) const {
416c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // parseObject(const UnicodeString&, Formattable&, UErrorCode&) const
41764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // will set status as U_INVALID_FORMAT_ERROR if
418c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // parse_pos is still 0
419c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
420c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
421c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
422c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
423c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
424c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruconst DateIntervalInfo*
425c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::getDateIntervalInfo() const {
426c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return fInfo;
427c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
428c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
429c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
430c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
431c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::setDateIntervalInfo(const DateIntervalInfo& newItvPattern,
432c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                        UErrorCode& status) {
433c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    delete fInfo;
434c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fInfo = new DateIntervalInfo(newItvPattern);
435c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert
436c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    // Delete patterns that get reset by initializePattern
437c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    delete fDatePattern;
438c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    fDatePattern = NULL;
439c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    delete fTimePattern;
440c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    fTimePattern = NULL;
441c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    delete fDateTimeFormat;
442c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    fDateTimeFormat = NULL;
443c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert
4448de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (fDateFormat) {
445c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        initializePattern(status);
446c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
447c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
448c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
449c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
45064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
451c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruconst DateFormat*
452c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::getDateFormat() const {
453c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return fDateFormat;
454c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
455c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
456c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
457b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
458b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoDateIntervalFormat::adoptTimeZone(TimeZone* zone)
459b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho{
460b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fDateFormat != NULL) {
461b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fDateFormat->adoptTimeZone(zone);
462b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
463b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // The fDateFormat has the master calendar for the DateIntervalFormat and has
464b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // ownership of any adopted TimeZone; fFromCalendar and fToCalendar are internal
465b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // work clones of that calendar (and should not also be given ownership of the
466b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // adopted TimeZone).
467b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fFromCalendar) {
468c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fFromCalendar->setTimeZone(*zone);
469b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
470b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fToCalendar) {
471c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fToCalendar->setTimeZone(*zone);
472b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
473b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
474b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
475b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
476b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoDateIntervalFormat::setTimeZone(const TimeZone& zone)
477b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho{
478b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fDateFormat != NULL) {
479b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fDateFormat->setTimeZone(zone);
480b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
481b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // The fDateFormat has the master calendar for the DateIntervalFormat;
482b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // fFromCalendar and fToCalendar are internal work clones of that calendar.
483b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fFromCalendar) {
484c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fFromCalendar->setTimeZone(zone);
485b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
486b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fToCalendar) {
487c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fToCalendar->setTimeZone(zone);
488b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
489b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
490b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
491b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst TimeZone&
492b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoDateIntervalFormat::getTimeZone() const
493b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho{
494b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fDateFormat != NULL) {
4958de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        Mutex lock(&gFormatterMutex);
496b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return fDateFormat->getTimeZone();
497b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
498b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // If fDateFormat is NULL (unexpected), create default timezone.
499b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return *(TimeZone::createDefault());
500b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
501b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
502b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruDateIntervalFormat::DateIntervalFormat(const Locale& locale,
503c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       DateIntervalInfo* dtItvInfo,
504c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       const UnicodeString* skeleton,
50564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                                       UErrorCode& status)
506b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru:   fInfo(NULL),
507b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fDateFormat(NULL),
508b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fFromCalendar(NULL),
509b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fToCalendar(NULL),
510c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    fLocale(locale),
511c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    fDatePattern(NULL),
512c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    fTimePattern(NULL),
513c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    fDateTimeFormat(NULL)
514c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
5158de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    LocalPointer<DateIntervalInfo> info(dtItvInfo, status);
5168de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    LocalPointer<SimpleDateFormat> dtfmt(static_cast<SimpleDateFormat *>(
5178de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            DateFormat::createInstanceForSkeleton(*skeleton, locale, status)), status);
5188de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (U_FAILURE(status)) {
519c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
520c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
5218de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
522c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( skeleton ) {
523c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fSkeleton = *skeleton;
524c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
5258de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    fInfo = info.orphan();
5268de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    fDateFormat = dtfmt.orphan();
5278de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if ( fDateFormat->getCalendar() ) {
5288de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        fFromCalendar = fDateFormat->getCalendar()->clone();
5298de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        fToCalendar = fDateFormat->getCalendar()->clone();
530c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
531c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    initializePattern(status);
532c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
533c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
534c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat* U_EXPORT2
535b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruDateIntervalFormat::create(const Locale& locale,
536c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           DateIntervalInfo* dtitvinf,
537c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           const UnicodeString* skeleton,
538c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           UErrorCode& status) {
53964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    DateIntervalFormat* f = new DateIntervalFormat(locale, dtitvinf,
540c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                                   skeleton, status);
541c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( f == NULL ) {
542c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
543c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete dtitvinf;
544c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if ( U_FAILURE(status) ) {
545c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // safe to delete f, although nothing acutally is saved
546c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete f;
547c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        f = 0;
548c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
549c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return f;
550c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
551c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
552c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
553c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
55464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert/**
555c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * Initialize interval patterns locale to this formatter
55664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *
55764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert * This code is a bit complicated since
558c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * 1. the interval patterns saved in resource bundle files are interval
559c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    patterns based on date or time only.
560c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    It does not have interval patterns based on both date and time.
561c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    Interval patterns on both date and time are algorithm generated.
562c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
563c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    For example, it has interval patterns on skeleton "dMy" and "hm",
564c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    but it does not have interval patterns on skeleton "dMyhm".
56564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *
566c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    The rule to genearte interval patterns for both date and time skeleton are
56764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *    1) when the year, month, or day differs, concatenate the two original
56864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *    expressions with a separator between,
56964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *    For example, interval pattern from "Jan 10, 2007 10:10 am"
57064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *    to "Jan 11, 2007 10:10am" is
57164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *    "Jan 10, 2007 10:10 am - Jan 11, 2007 10:10am"
572c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
57364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *    2) otherwise, present the date followed by the range expression
574c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    for the time.
57564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *    For example, interval pattern from "Jan 10, 2007 10:10 am"
57664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *    to "Jan 10, 2007 11:10am" is
57764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *    "Jan 10, 2007 10:10 am - 11:10am"
578c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
579c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * 2. even a pattern does not request a certion calendar field,
580c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    the interval pattern needs to include such field if such fields are
581c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    different between 2 dates.
58264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *    For example, a pattern/skeleton is "hm", but the interval pattern
583c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    includes year, month, and date when year, month, and date differs.
58464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *
585c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param status          output param set to success/failure code on exit
58664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert * @stable ICU 4.0
587c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru */
58864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertvoid
589c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::initializePattern(UErrorCode& status) {
590c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
591c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
592c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
593c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const Locale& locale = fDateFormat->getSmpFmtLocale();
594c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( fSkeleton.isEmpty() ) {
595c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UnicodeString fullPattern;
596c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fDateFormat->toPattern(fullPattern);
597c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#ifdef DTITVFMT_DEBUG
598c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char result[1000];
599c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char result_1[1000];
600c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char mesg[2000];
601c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fSkeleton.extract(0,  fSkeleton.length(), result, "UTF-8");
602c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    sprintf(mesg, "in getBestSkeleton: fSkeleton: %s; \n", result);
603c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    PRINTMESG(mesg)
604c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#endif
605c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // fSkeleton is already set by createDateIntervalInstance()
606c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // or by createInstance(UnicodeString skeleton, .... )
607c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fSkeleton = DateTimePatternGenerator::staticGetSkeleton(
608c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                fullPattern, status);
609c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( U_FAILURE(status) ) {
61064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            return;
611c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
612c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
613c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
614c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // initialize the fIntervalPattern ordering
615c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int8_t i;
616c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for ( i = 0; i < DateIntervalInfo::kIPI_MAX_INDEX; ++i ) {
617c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fIntervalPatterns[i].laterDateFirst = fInfo->getDefaultOrder();
618c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
619c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
620c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* Check whether the skeleton is a combination of date and time.
621c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * For the complication reason 1 explained above.
622c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     */
623c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString dateSkeleton;
624c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString timeSkeleton;
625c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString normalizedTimeSkeleton;
626c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString normalizedDateSkeleton;
627c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
628c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
629c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* the difference between time skeleton and normalizedTimeSkeleton are:
63050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * 1. (Formerly, normalized time skeleton folded 'H' to 'h'; no longer true)
631c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * 2. 'a' is omitted in normalized time skeleton.
63264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert     * 3. there is only one appearance for 'h' or 'H', 'm','v', 'z' in normalized
633c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     *    time skeleton
634c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     *
635c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * The difference between date skeleton and normalizedDateSkeleton are:
636c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * 1. both 'y' and 'd' appear only once in normalizeDateSkeleton
637c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * 2. 'E' and 'EE' are normalized into 'EEE'
638c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * 3. 'MM' is normalized into 'M'
639c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     */
640c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    getDateTimeSkeleton(fSkeleton, dateSkeleton, normalizedDateSkeleton,
641c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                        timeSkeleton, normalizedTimeSkeleton);
642c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
643c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#ifdef DTITVFMT_DEBUG
644c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char result[1000];
645c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char result_1[1000];
646c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char mesg[2000];
647c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fSkeleton.extract(0,  fSkeleton.length(), result, "UTF-8");
648c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    sprintf(mesg, "in getBestSkeleton: fSkeleton: %s; \n", result);
649c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    PRINTMESG(mesg)
650c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#endif
651c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
652c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    // move this up here since we need it for fallbacks
653c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if ( timeSkeleton.length() > 0 && dateSkeleton.length() > 0 ) {
654c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        // Need the Date/Time pattern for concatenation of the date
655c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        // with the time interval.
656c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        // The date/time pattern ( such as {0} {1} ) is saved in
657c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        // calendar, that is why need to get the CalendarData here.
65864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        LocalUResourceBundlePointer dateTimePatternsRes(ures_open(NULL, locale.getBaseName(), &status));
65964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        ures_getByKey(dateTimePatternsRes.getAlias(), gCalendarTag,
66064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                      dateTimePatternsRes.getAlias(), &status);
66164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        ures_getByKeyWithFallback(dateTimePatternsRes.getAlias(), gGregorianTag,
66264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                                  dateTimePatternsRes.getAlias(), &status);
66364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        ures_getByKeyWithFallback(dateTimePatternsRes.getAlias(), gDateTimePatternsTag,
66464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                                  dateTimePatternsRes.getAlias(), &status);
66564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
666c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        int32_t dateTimeFormatLength;
667c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        const UChar* dateTimeFormat = ures_getStringByIndex(
66864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                                            dateTimePatternsRes.getAlias(),
669c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                                            (int32_t)DateFormat::kDateTime,
670c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                                            &dateTimeFormatLength, &status);
671c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        if ( U_SUCCESS(status) && dateTimeFormatLength >= 3 ) {
672c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            fDateTimeFormat = new UnicodeString(dateTimeFormat, dateTimeFormatLength);
673c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        }
674c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
675c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
67664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    UBool found = setSeparateDateTimePtn(normalizedDateSkeleton,
677c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                         normalizedTimeSkeleton);
678c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
679c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    // for skeletons with seconds, found is false and we enter this block
680c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( found == false ) {
681c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // use fallback
682c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // TODO: if user asks "m"(minute), but "d"(day) differ
683c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( timeSkeleton.length() != 0 ) {
684c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if ( dateSkeleton.length() == 0 ) {
685c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // prefix with yMd
686b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                timeSkeleton.insert(0, gDateFormatSkeleton[DateFormat::kShort], -1);
687c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                UnicodeString pattern = DateFormat::getBestPattern(
688c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                        locale, timeSkeleton, status);
689c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                if ( U_FAILURE(status) ) {
69064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    return;
691c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                }
692c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // for fall back interval patterns,
693c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // the first part of the pattern is empty,
694c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // the second part of the pattern is the full-pattern
695c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // should be used in fall-back.
69664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                setPatternInfo(UCAL_DATE, NULL, &pattern, fInfo->getDefaultOrder());
69764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                setPatternInfo(UCAL_MONTH, NULL, &pattern, fInfo->getDefaultOrder());
69864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                setPatternInfo(UCAL_YEAR, NULL, &pattern, fInfo->getDefaultOrder());
699c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            } else {
700c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // TODO: fall back
701c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
702c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
703c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // TODO: fall back
704c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
705c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
706c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } // end of skeleton not found
70764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // interval patterns for skeleton are found in resource
708c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( timeSkeleton.length() == 0 ) {
709c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // done
710c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if ( dateSkeleton.length() == 0 ) {
711c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // prefix with yMd
712b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        timeSkeleton.insert(0, gDateFormatSkeleton[DateFormat::kShort], -1);
713c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        UnicodeString pattern = DateFormat::getBestPattern(
714c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                locale, timeSkeleton, status);
715c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( U_FAILURE(status) ) {
71664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            return;
717c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
718c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // for fall back interval patterns,
719c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // the first part of the pattern is empty,
720c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // the second part of the pattern is the full-pattern
721c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // should be used in fall-back.
72264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        setPatternInfo(UCAL_DATE, NULL, &pattern, fInfo->getDefaultOrder());
72364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        setPatternInfo(UCAL_MONTH, NULL, &pattern, fInfo->getDefaultOrder());
72464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        setPatternInfo(UCAL_YEAR, NULL, &pattern, fInfo->getDefaultOrder());
725c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
726c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        /* if both present,
72764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert         * 1) when the year, month, or day differs,
72864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert         * concatenate the two original expressions with a separator between,
72964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert         * 2) otherwise, present the date followed by the
73064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert         * range expression for the time.
731c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         */
732c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        /*
73364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert         * 1) when the year, month, or day differs,
73464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert         * concatenate the two original expressions with a separator between,
735c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         */
736c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // if field exists, use fall back
737c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UnicodeString skeleton = fSkeleton;
738c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( !fieldExistsInSkeleton(UCAL_DATE, dateSkeleton) ) {
739c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // prefix skeleton with 'd'
740c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            skeleton.insert(0, LOW_D);
741b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            setFallbackPattern(UCAL_DATE, skeleton, status);
742c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
743c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( !fieldExistsInSkeleton(UCAL_MONTH, dateSkeleton) ) {
744c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // then prefix skeleton with 'M'
745c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            skeleton.insert(0, CAP_M);
746b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            setFallbackPattern(UCAL_MONTH, skeleton, status);
747c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
748c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( !fieldExistsInSkeleton(UCAL_YEAR, dateSkeleton) ) {
749c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // then prefix skeleton with 'y'
750c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            skeleton.insert(0, LOW_Y);
751b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            setFallbackPattern(UCAL_YEAR, skeleton, status);
752c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
75364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
754c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        /*
75564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert         * 2) otherwise, present the date followed by the
75664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert         * range expression for the time.
757c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         */
758c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
7598de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        if ( fDateTimeFormat == NULL ) {
760c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            // earlier failure getting dateTimeFormat
761c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return;
762c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
763c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
764c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        UnicodeString datePattern = DateFormat::getBestPattern(
765c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                locale, dateSkeleton, status);
766c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
767c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        concatSingleDate2TimeInterval(*fDateTimeFormat, datePattern, UCAL_AM_PM, status);
768c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        concatSingleDate2TimeInterval(*fDateTimeFormat, datePattern, UCAL_HOUR, status);
769c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        concatSingleDate2TimeInterval(*fDateTimeFormat, datePattern, UCAL_MINUTE, status);
770c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
771c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
772c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
773c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
774c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
77564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertvoid  U_EXPORT2
77664339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertDateIntervalFormat::getDateTimeSkeleton(const UnicodeString& skeleton,
77764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                                        UnicodeString& dateSkeleton,
77864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                                        UnicodeString& normalizedDateSkeleton,
779c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                        UnicodeString& timeSkeleton,
780c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                        UnicodeString& normalizedTimeSkeleton) {
781c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // dateSkeleton follows the sequence of y*M*E*d*
782c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // timeSkeleton follows the sequence of hm*[v|z]?
783c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t ECount = 0;
784c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t dCount = 0;
785c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t MCount = 0;
786c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t yCount = 0;
787c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t hCount = 0;
78850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t HCount = 0;
789c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t mCount = 0;
790c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t vCount = 0;
791c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t zCount = 0;
792c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t i;
793c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
794c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for (i = 0; i < skeleton.length(); ++i) {
795c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UChar ch = skeleton[i];
796c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        switch ( ch ) {
797c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_E:
798c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            dateSkeleton.append(ch);
799c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++ECount;
800c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
801c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_D:
802c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            dateSkeleton.append(ch);
803c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++dCount;
804c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
805c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_M:
806c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            dateSkeleton.append(ch);
807c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++MCount;
808c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
809c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_Y:
810c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            dateSkeleton.append(ch);
811c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++yCount;
812c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
813c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_G:
814c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_Y:
815c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_U:
816c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_Q:
817c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_Q:
818c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_L:
819c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_L:
820c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_W:
821c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_W:
822c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_D:
823c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_F:
824c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_G:
825c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_E:
826c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_C:
827fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          case CAP_U:
828fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          case LOW_R:
829c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            normalizedDateSkeleton.append(ch);
830c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            dateSkeleton.append(ch);
831c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
832c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_A:
83364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            // 'a' is implicitly handled
834c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            timeSkeleton.append(ch);
835c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
836c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_H:
837c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            timeSkeleton.append(ch);
838c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++hCount;
839c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
84050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho          case CAP_H:
84150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            timeSkeleton.append(ch);
84250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            ++HCount;
84350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            break;
844c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_M:
845c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            timeSkeleton.append(ch);
846c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++mCount;
847c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
848c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_Z:
849c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++zCount;
850c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            timeSkeleton.append(ch);
851c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
852c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_V:
853c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++vCount;
854c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            timeSkeleton.append(ch);
855c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
856c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_V:
857c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_Z:
858c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_K:
859c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_K:
860c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_J:
861c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case LOW_S:
862c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_S:
863c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          case CAP_A:
864c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            timeSkeleton.append(ch);
865c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            normalizedTimeSkeleton.append(ch);
86664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            break;
867c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
868c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
869c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
870c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* generate normalized form for date*/
871c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( yCount != 0 ) {
87259d709d503bab6e2b61931737e662dd293b40578ccornelius        for (i = 0; i < yCount; ++i) {
87359d709d503bab6e2b61931737e662dd293b40578ccornelius            normalizedDateSkeleton.append(LOW_Y);
87459d709d503bab6e2b61931737e662dd293b40578ccornelius        }
875c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
876c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( MCount != 0 ) {
877c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( MCount < 3 ) {
878c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            normalizedDateSkeleton.append(CAP_M);
879c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
880c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            int32_t i;
881c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            for ( i = 0; i < MCount && i < MAX_M_COUNT; ++i ) {
882c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 normalizedDateSkeleton.append(CAP_M);
883c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
884c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
885c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
886c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( ECount != 0 ) {
887c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( ECount <= 3 ) {
888c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            normalizedDateSkeleton.append(CAP_E);
889c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
890c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            int32_t i;
891c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            for ( i = 0; i < ECount && i < MAX_E_COUNT; ++i ) {
892c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 normalizedDateSkeleton.append(CAP_E);
893c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
894c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
895c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
896c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( dCount != 0 ) {
897c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        normalizedDateSkeleton.append(LOW_D);
898c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
899c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
900c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* generate normalized form for time */
90150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if ( HCount != 0 ) {
90250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        normalizedTimeSkeleton.append(CAP_H);
90350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
90450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    else if ( hCount != 0 ) {
905c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        normalizedTimeSkeleton.append(LOW_H);
906c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
907c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( mCount != 0 ) {
908c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        normalizedTimeSkeleton.append(LOW_M);
909c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
910c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( zCount != 0 ) {
911c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        normalizedTimeSkeleton.append(LOW_Z);
912c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
913c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( vCount != 0 ) {
914c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        normalizedTimeSkeleton.append(LOW_V);
915c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
916c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
917c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
918c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
919c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru/**
920c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * Generate date or time interval pattern from resource,
921c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * and set them into the interval pattern locale to this formatter.
922c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
92364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert * It needs to handle the following:
924c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * 1. need to adjust field width.
925c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    For example, the interval patterns saved in DateIntervalInfo
926c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    includes "dMMMy", but not "dMMMMy".
927c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    Need to get interval patterns for dMMMMy from dMMMy.
928c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    Another example, the interval patterns saved in DateIntervalInfo
929c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    includes "hmv", but not "hmz".
930c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    Need to get interval patterns for "hmz' from 'hmv'
931c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
932c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * 2. there might be no pattern for 'y' differ for skeleton "Md",
933c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    in order to get interval patterns for 'y' differ,
934c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *    need to look for it from skeleton 'yMd'
935c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
936c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param dateSkeleton   normalized date skeleton
937c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param timeSkeleton   normalized time skeleton
938c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @return               whether the resource is found for the skeleton.
939c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *                       TRUE if interval pattern found for the skeleton,
940c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *                       FALSE otherwise.
941b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * @stable ICU 4.0
942c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru */
94364339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertUBool
944c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::setSeparateDateTimePtn(
945c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                 const UnicodeString& dateSkeleton,
946c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                 const UnicodeString& timeSkeleton) {
947c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const UnicodeString* skeleton;
948c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // if both date and time skeleton present,
949c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // the final interval pattern might include time interval patterns
950c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // ( when, am_pm, hour, minute differ ),
951c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // but not date interval patterns ( when year, month, day differ ).
952c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // For year/month/day differ, it falls back to fall-back pattern.
953c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( timeSkeleton.length() != 0  ) {
954c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        skeleton = &timeSkeleton;
955c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
956c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        skeleton = &dateSkeleton;
957c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
958c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
95964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    /* interval patterns for skeleton "dMMMy" (but not "dMMMMy")
960c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * are defined in resource,
961c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * interval patterns for skeleton "dMMMMy" are calculated by
962c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * 1. get the best match skeleton for "dMMMMy", which is "dMMMy"
963c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * 2. get the interval patterns for "dMMMy",
96464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert     * 3. extend "MMM" to "MMMM" in above interval patterns for "dMMMMy"
965c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * getBestSkeleton() is step 1.
966c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     */
967c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // best skeleton, and the difference information
968c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int8_t differenceInfo = 0;
96964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    const UnicodeString* bestSkeleton = fInfo->getBestSkeleton(*skeleton,
970c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                                               differenceInfo);
971c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* best skeleton could be NULL.
972c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru       For example: in "ca" resource file,
973c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru       interval format is defined as following
974c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru           intervalFormats{
975c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                fallback{"{0} - {1}"}
976c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
977c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru       there is no skeletons/interval patterns defined,
978c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru       and the best skeleton match could be NULL
979c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     */
980c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( bestSkeleton == NULL ) {
98164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        return false;
98264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    }
98364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
984c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    // Set patterns for fallback use, need to do this
985c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    // before returning if differenceInfo == -1
986c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    UErrorCode status;
987c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if ( dateSkeleton.length() != 0) {
988c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        status = U_ZERO_ERROR;
989c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fDatePattern = new UnicodeString(DateFormat::getBestPattern(
990c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                fLocale, dateSkeleton, status));
991c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
992c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if ( timeSkeleton.length() != 0) {
993c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        status = U_ZERO_ERROR;
994c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fTimePattern = new UnicodeString(DateFormat::getBestPattern(
995c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                fLocale, timeSkeleton, status));
996c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
997c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert
998c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // difference:
999c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // 0 means the best matched skeleton is the same as input skeleton
1000c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // 1 means the fields are the same, but field width are different
1001c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // 2 means the only difference between fields are v/z,
100264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // -1 means there are other fields difference
1003c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    // (this will happen, for instance, if the supplied skeleton has seconds,
1004c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    //  but no skeletons in the intervalFormats data do)
100564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    if ( differenceInfo == -1 ) {
1006c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // skeleton has different fields, not only  v/z difference
1007c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return false;
1008c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1009c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1010c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( timeSkeleton.length() == 0 ) {
1011c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UnicodeString extendedSkeleton;
1012c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UnicodeString extendedBestSkeleton;
1013c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // only has date skeleton
1014c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        setIntervalPattern(UCAL_DATE, skeleton, bestSkeleton, differenceInfo,
1015c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           &extendedSkeleton, &extendedBestSkeleton);
1016c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
101764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        UBool extended = setIntervalPattern(UCAL_MONTH, skeleton, bestSkeleton,
1018c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                     differenceInfo,
1019c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                     &extendedSkeleton, &extendedBestSkeleton);
102064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
1021c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( extended ) {
1022c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            bestSkeleton = &extendedBestSkeleton;
1023c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            skeleton = &extendedSkeleton;
1024c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1025c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        setIntervalPattern(UCAL_YEAR, skeleton, bestSkeleton, differenceInfo,
1026c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                           &extendedSkeleton, &extendedBestSkeleton);
1027c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
1028c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        setIntervalPattern(UCAL_MINUTE, skeleton, bestSkeleton, differenceInfo);
1029c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        setIntervalPattern(UCAL_HOUR, skeleton, bestSkeleton, differenceInfo);
1030c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        setIntervalPattern(UCAL_AM_PM, skeleton, bestSkeleton, differenceInfo);
1031c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1032c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return true;
1033c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1034c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1035c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1036c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1037c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
1038c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::setFallbackPattern(UCalendarDateFields field,
1039c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       const UnicodeString& skeleton,
1040c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       UErrorCode& status) {
1041c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
1042c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
1043c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1044c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    UnicodeString pattern = DateFormat::getBestPattern(
1045c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            fLocale, skeleton, status);
1046c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
1047c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
1048c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1049c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setPatternInfo(field, NULL, &pattern, fInfo->getDefaultOrder());
1050c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1051c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1052c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1053c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1054c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1055c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
105664339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertDateIntervalFormat::setPatternInfo(UCalendarDateFields field,
1057c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   const UnicodeString* firstPart,
105864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                                   const UnicodeString* secondPart,
1059c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   UBool laterDateFirst) {
1060c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // for fall back interval patterns,
1061c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // the first part of the pattern is empty,
1062c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // the second part of the pattern is the full-pattern
1063c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // should be used in fall-back.
1064c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
1065c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // following should not set any wrong status.
1066c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t itvPtnIndex = DateIntervalInfo::calendarFieldToIntervalIndex(field,
1067c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                                                        status);
1068c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
1069c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
1070c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1071c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    PatternInfo& ptn = fIntervalPatterns[itvPtnIndex];
1072c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( firstPart ) {
1073c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        ptn.firstPart = *firstPart;
1074c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1075c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( secondPart ) {
1076c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        ptn.secondPart = *secondPart;
1077c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1078c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    ptn.laterDateFirst = laterDateFirst;
1079c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1080c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1081c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
1082c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::setIntervalPattern(UCalendarDateFields field,
1083c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       const UnicodeString& intervalPattern) {
1084c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UBool order = fInfo->getDefaultOrder();
1085c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setIntervalPattern(field, intervalPattern, order);
1086c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1087c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1088c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1089c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
1090c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::setIntervalPattern(UCalendarDateFields field,
1091c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       const UnicodeString& intervalPattern,
1092c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       UBool laterDateFirst) {
1093c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const UnicodeString* pattern = &intervalPattern;
1094c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UBool order = laterDateFirst;
1095c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // check for "latestFirst:" or "earliestFirst:" prefix
10968de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    int8_t prefixLength = UPRV_LENGTHOF(gLaterFirstPrefix);
10978de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    int8_t earliestFirstLength = UPRV_LENGTHOF(gEarlierFirstPrefix);
1098c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString realPattern;
1099c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( intervalPattern.startsWith(gLaterFirstPrefix, prefixLength) ) {
1100c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        order = true;
110164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        intervalPattern.extract(prefixLength,
1102c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                intervalPattern.length() - prefixLength,
1103c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                realPattern);
1104c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        pattern = &realPattern;
1105c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if ( intervalPattern.startsWith(gEarlierFirstPrefix,
1106c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                           earliestFirstLength) ) {
1107c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        order = false;
1108c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        intervalPattern.extract(earliestFirstLength,
1109c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                intervalPattern.length() - earliestFirstLength,
1110c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                realPattern);
1111c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        pattern = &realPattern;
1112c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1113c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1114c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t splitPoint = splitPatternInto2Part(*pattern);
111564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
1116c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString firstPart;
1117c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString secondPart;
1118c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    pattern->extract(0, splitPoint, firstPart);
1119c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( splitPoint < pattern->length() ) {
1120c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        pattern->extract(splitPoint, pattern->length()-splitPoint, secondPart);
1121c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1122c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setPatternInfo(field, &firstPart, &secondPart, order);
1123c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1124c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1125c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1126c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1127c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1128c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru/**
1129c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * Generate interval pattern from existing resource
1130c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
1131c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * It not only save the interval patterns,
1132c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * but also return the extended skeleton and its best match skeleton.
1133c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
1134c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param field           largest different calendar field
1135c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param skeleton        skeleton
1136c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param bestSkeleton    the best match skeleton which has interval pattern
1137c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *                        defined in resource
1138c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param differenceInfo  the difference between skeleton and best skeleton
1139c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *         0 means the best matched skeleton is the same as input skeleton
1140c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *         1 means the fields are the same, but field width are different
1141c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *         2 means the only difference between fields are v/z,
114264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert *        -1 means there are other fields difference
1143c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *
1144c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param extendedSkeleton      extended skeleton
1145c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * @param extendedBestSkeleton  extended best match skeleton
114664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert * @return                      whether the interval pattern is found
1147c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *                              through extending skeleton or not.
1148c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *                              TRUE if interval pattern is found by
1149c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru *                              extending skeleton, FALSE otherwise.
1150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * @stable ICU 4.0
1151c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru */
1152c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUBool
1153c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::setIntervalPattern(UCalendarDateFields field,
1154c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       const UnicodeString* skeleton,
1155c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       const UnicodeString* bestSkeleton,
1156c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       int8_t differenceInfo,
1157c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       UnicodeString* extendedSkeleton,
1158c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                       UnicodeString* extendedBestSkeleton) {
1159c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
1160c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // following getIntervalPattern() should not generate error status
1161c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString pattern;
1162c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fInfo->getIntervalPattern(*bestSkeleton, field, pattern, status);
1163c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( pattern.isEmpty() ) {
1164c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // single date
1165c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( SimpleDateFormat::isFieldUnitIgnored(*bestSkeleton, field) ) {
1166c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // do nothing, format will handle it
1167c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return false;
1168c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1169c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1170c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // for 24 hour system, interval patterns in resource file
117164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        // might not include pattern when am_pm differ,
1172c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // which should be the same as hour differ.
1173c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // add it here for simplicity
1174c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( field == UCAL_AM_PM ) {
1175c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fInfo->getIntervalPattern(*bestSkeleton, UCAL_HOUR, pattern,status);
1176c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if ( !pattern.isEmpty() ) {
1177c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                setIntervalPattern(field, pattern);
1178c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1179c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return false;
118064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        }
1181c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // else, looking for pattern when 'y' differ for 'dMMMM' skeleton,
1182c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // first, get best match pattern "MMMd",
1183c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // since there is no pattern for 'y' differs for skeleton 'MMMd',
1184c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // need to look for it from skeleton 'yMMMd',
1185c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // if found, adjust field width in interval pattern from
1186c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // "MMM" to "MMMM".
1187c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UChar fieldLetter = fgCalendarFieldToPatternLetter[field];
1188c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( extendedSkeleton ) {
1189c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            *extendedSkeleton = *skeleton;
1190c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            *extendedBestSkeleton = *bestSkeleton;
1191c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            extendedSkeleton->insert(0, fieldLetter);
1192c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            extendedBestSkeleton->insert(0, fieldLetter);
1193c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // for example, looking for patterns when 'y' differ for
119464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            // skeleton "MMMM".
1195c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fInfo->getIntervalPattern(*extendedBestSkeleton,field,pattern,status);
1196c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if ( pattern.isEmpty() && differenceInfo == 0 ) {
1197c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // if there is no skeleton "yMMMM" defined,
119864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                // look for the best match skeleton, for example: "yMMM"
1199c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                const UnicodeString* tmpBest = fInfo->getBestSkeleton(
1200c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                        *extendedBestSkeleton, differenceInfo);
1201c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                if ( tmpBest != 0 && differenceInfo != -1 ) {
1202c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    fInfo->getIntervalPattern(*tmpBest, field, pattern, status);
1203c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    bestSkeleton = tmpBest;
1204c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                }
1205c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1206c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
120764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    }
1208c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( !pattern.isEmpty() ) {
1209c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( differenceInfo != 0 ) {
1210c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            UnicodeString adjustIntervalPattern;
1211c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            adjustFieldWidth(*skeleton, *bestSkeleton, pattern, differenceInfo,
1212c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                              adjustIntervalPattern);
1213c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            setIntervalPattern(field, adjustIntervalPattern);
1214c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
1215c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            setIntervalPattern(field, pattern);
1216c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1217c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( extendedSkeleton && !extendedSkeleton->isEmpty() ) {
1218c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return TRUE;
1219c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1220c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1221c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return FALSE;
1222c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1223c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1224c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1225c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
122664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertint32_t  U_EXPORT2
1227c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::splitPatternInto2Part(const UnicodeString& intervalPattern) {
1228c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UBool inQuote = false;
1229c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar prevCh = 0;
1230c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t count = 0;
1231c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1232c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* repeatedPattern used to record whether a pattern has already seen.
1233c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru       It is a pattern applies to first calendar if it is first time seen,
1234c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru       otherwise, it is a pattern applies to the second calendar
1235c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     */
123664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    UBool patternRepeated[] =
1237c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {
1238c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
1239c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
1240c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //   P   Q   R   S   T   U   V   W   X   Y   Z
1241c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
1242c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
1243c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
1244c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //   p   q   r   s   t   u   v   w   x   y   z
1245c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
1246c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    };
1247c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1248c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int8_t PATTERN_CHAR_BASE = 0x41;
124964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
1250c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* loop through the pattern string character by character looking for
1251c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     * the first repeated pattern letter, which breaks the interval pattern
125264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert     * into 2 parts.
1253c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     */
1254c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t i;
1255c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UBool foundRepetition = false;
1256c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for (i = 0; i < intervalPattern.length(); ++i) {
1257c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UChar ch = intervalPattern.charAt(i);
125864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
1259c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (ch != prevCh && count > 0) {
1260c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // check the repeativeness of pattern letter
1261c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            UBool repeated = patternRepeated[(int)(prevCh - PATTERN_CHAR_BASE)];
1262c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if ( repeated == FALSE ) {
1263c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                patternRepeated[prevCh - PATTERN_CHAR_BASE] = TRUE;
1264c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            } else {
1265c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                foundRepetition = true;
1266c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                break;
1267c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1268c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            count = 0;
1269c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
127064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        if (ch == 0x0027 /*'*/) {
1271c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // Consecutive single quotes are a single quote literal,
1272c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // either outside of quotes or between quotes
127364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            if ((i+1) < intervalPattern.length() &&
127464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                intervalPattern.charAt(i+1) == 0x0027 /*'*/) {
1275c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                ++i;
1276c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            } else {
1277c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                inQuote = ! inQuote;
1278c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
127964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        }
1280c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        else if (!inQuote && ((ch >= 0x0061 /*'a'*/ && ch <= 0x007A /*'z'*/)
1281c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    || (ch >= 0x0041 /*'A'*/ && ch <= 0x005A /*'Z'*/))) {
128264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            // ch is a date-time pattern character
1283c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            prevCh = ch;
1284c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++count;
1285c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1286c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1287c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // check last pattern char, distinguish
128864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // "dd MM" ( no repetition ),
128964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // "d-d"(last char repeated ), and
1290c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // "d-d MM" ( repetition found )
1291c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( count > 0 && foundRepetition == FALSE ) {
1292c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( patternRepeated[(int)(prevCh - PATTERN_CHAR_BASE)] == FALSE ) {
1293c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            count = 0;
1294c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1295c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1296c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (i - count);
1297c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1298c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1299c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertstatic const UChar bracketedZero[] = {0x7B,0x30,0x7D};
1300c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertstatic const UChar bracketedOne[]  = {0x7B,0x31,0x7D};
1301c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1302c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertvoid
1303c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDateIntervalFormat::adjustPosition(UnicodeString& combiningPattern, // has {0} and {1} in it
1304c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                                   UnicodeString& pat0, FieldPosition& pos0, // pattern and pos corresponding to {0}
1305c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                                   UnicodeString& pat1, FieldPosition& pos1, // pattern and pos corresponding to {1}
1306c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                                   FieldPosition& posResult)  {
1307c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    int32_t index0 = combiningPattern.indexOf(bracketedZero, 3, 0);
1308c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    int32_t index1 = combiningPattern.indexOf(bracketedOne,  3, 0);
1309c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (index0 < 0 || index1 < 0) {
1310c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return;
1311c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
1312c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    int32_t placeholderLen = 3; // length of "{0}" or "{1}"
1313c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (index0 < index1) {
1314c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        if (pos0.getEndIndex() > 0) {
1315c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            posResult.setBeginIndex(pos0.getBeginIndex() + index0);
1316c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            posResult.setEndIndex(pos0.getEndIndex() + index0);
1317c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        } else if (pos1.getEndIndex() > 0) {
1318c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            // here index1 >= 3
1319c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            index1 += pat0.length() - placeholderLen; // adjust for pat0 replacing {0}
1320c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            posResult.setBeginIndex(pos1.getBeginIndex() + index1);
1321c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            posResult.setEndIndex(pos1.getEndIndex() + index1);
1322c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        }
1323c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    } else {
1324c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        if (pos1.getEndIndex() > 0) {
1325c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            posResult.setBeginIndex(pos1.getBeginIndex() + index1);
1326c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            posResult.setEndIndex(pos1.getEndIndex() + index1);
1327c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        } else if (pos0.getEndIndex() > 0) {
1328c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            // here index0 >= 3
1329c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            index0 += pat1.length() - placeholderLen; // adjust for pat1 replacing {1}
1330c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            posResult.setBeginIndex(pos0.getBeginIndex() + index0);
1331c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            posResult.setEndIndex(pos0.getEndIndex() + index0);
1332c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        }
1333c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
1334c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert}
1335c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
133664339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertUnicodeString&
1337c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::fallbackFormat(Calendar& fromCalendar,
1338c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   Calendar& toCalendar,
1339c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                                   UBool fromToOnSameDay, // new
1340c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   UnicodeString& appendTo,
1341c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   FieldPosition& pos,
1342c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                   UErrorCode& status) const {
1343c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
1344c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return appendTo;
1345c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1346c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    UnicodeString fullPattern; // for saving the pattern in fDateFormat
1347c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    UBool formatDatePlusTimeRange = (fromToOnSameDay && fDatePattern && fTimePattern);
1348c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // the fall back
1349c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (formatDatePlusTimeRange) {
1350c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fDateFormat->toPattern(fullPattern); // save current pattern, restore later
1351c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fDateFormat->applyPattern(*fTimePattern);
1352c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
1353c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    FieldPosition otherPos;
1354c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    otherPos.setField(pos.getField());
13558de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    UnicodeString earlierDate;
13568de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    fDateFormat->format(fromCalendar, earlierDate, pos);
13578de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    UnicodeString laterDate;
13588de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    fDateFormat->format(toCalendar, laterDate, otherPos);
1359c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString fallbackPattern;
1360c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fInfo->getFallbackIntervalPattern(fallbackPattern);
13618de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    adjustPosition(fallbackPattern, earlierDate, pos, laterDate, otherPos, pos);
1362c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    UnicodeString fallbackRange;
13638de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    SimpleFormatter(fallbackPattern, 2, 2, status).
13648de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            format(earlierDate, laterDate, fallbackRange, status);
1365c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if ( U_SUCCESS(status) && formatDatePlusTimeRange ) {
1366c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        // fallbackRange has just the time range, need to format the date part and combine that
1367c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fDateFormat->applyPattern(*fDatePattern);
13688de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        UnicodeString datePortion;
1369c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        otherPos.setBeginIndex(0);
1370c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        otherPos.setEndIndex(0);
13718de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        fDateFormat->format(fromCalendar, datePortion, otherPos);
13728de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        adjustPosition(*fDateTimeFormat, fallbackRange, pos, datePortion, otherPos, pos);
13738de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        const UnicodeString *values[2] = {
13748de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            &fallbackRange,  // {0} is time range
13758de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            &datePortion,  // {1} is single date portion
13768de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        };
13778de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        SimpleFormatter(*fDateTimeFormat, 2, 2, status).
13788de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                formatAndReplace(values, 2, fallbackRange, NULL, 0, status);
1379c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
1380c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_SUCCESS(status) ) {
1381c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        appendTo.append(fallbackRange);
1382c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
1383c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (formatDatePlusTimeRange) {
1384c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        // restore full pattern
1385c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fDateFormat->applyPattern(fullPattern);
1386c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1387c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return appendTo;
1388c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1389c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1390c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1391c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1392c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
139364339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertUBool  U_EXPORT2
1394c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::fieldExistsInSkeleton(UCalendarDateFields field,
1395c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                          const UnicodeString& skeleton)
1396c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
1397c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const UChar fieldChar = fgCalendarFieldToPatternLetter[field];
1398c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return ( (skeleton.indexOf(fieldChar) == -1)?FALSE:TRUE ) ;
1399c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1400c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1401c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1402c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
140364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertvoid  U_EXPORT2
1404c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::adjustFieldWidth(const UnicodeString& inputSkeleton,
1405c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 const UnicodeString& bestMatchSkeleton,
1406c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 const UnicodeString& bestIntervalPattern,
1407c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 int8_t differenceInfo,
1408c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 UnicodeString& adjustedPtn) {
1409c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    adjustedPtn = bestIntervalPattern;
141064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    int32_t inputSkeletonFieldWidth[] =
1411c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {
1412c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
1413c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
1414c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //   P   Q   R   S   T   U   V   W   X   Y   Z
1415c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
1416c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
1417c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
1418c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //   p   q   r   s   t   u   v   w   x   y   z
1419c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
1420c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    };
1421c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
142264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    int32_t bestMatchSkeletonFieldWidth[] =
1423c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {
1424c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
1425c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
1426c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //   P   Q   R   S   T   U   V   W   X   Y   Z
1427c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
1428c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
1429c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
1430c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //   p   q   r   s   t   u   v   w   x   y   z
1431c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
1432c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    };
1433c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1434c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    DateIntervalInfo::parseSkeleton(inputSkeleton, inputSkeletonFieldWidth);
1435c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    DateIntervalInfo::parseSkeleton(bestMatchSkeleton, bestMatchSkeletonFieldWidth);
1436c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( differenceInfo == 2 ) {
1437b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        adjustedPtn.findAndReplace(UnicodeString((UChar)0x76 /* v */),
1438b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                   UnicodeString((UChar)0x7a /* z */));
1439c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1440c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1441c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UBool inQuote = false;
1442c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar prevCh = 0;
1443c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t count = 0;
1444c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1445c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const int8_t PATTERN_CHAR_BASE = 0x41;
144664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
144764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // loop through the pattern string character by character
1448c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t adjustedPtnLength = adjustedPtn.length();
1449c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t i;
1450c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for (i = 0; i < adjustedPtnLength; ++i) {
1451c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UChar ch = adjustedPtn.charAt(i);
1452c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (ch != prevCh && count > 0) {
1453c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // check the repeativeness of pattern letter
1454c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            UChar skeletonChar = prevCh;
1455c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if ( skeletonChar ==  CAP_L ) {
145664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                // there is no "L" (always be "M") in skeleton,
1457c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // but there is "L" in pattern.
145864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                // for skeleton "M+", the pattern might be "...L..."
1459c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                skeletonChar = CAP_M;
1460c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1461c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            int32_t fieldCount = bestMatchSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
1462c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            int32_t inputFieldCount = inputSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
1463c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if ( fieldCount == count && inputFieldCount > fieldCount ) {
1464c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                count = inputFieldCount - fieldCount;
1465c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                int32_t j;
1466c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                for ( j = 0; j < count; ++j ) {
146764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    adjustedPtn.insert(i, prevCh);
146864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                }
1469c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                i += count;
1470c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                adjustedPtnLength += count;
1471c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1472c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            count = 0;
1473c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
147464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        if (ch == 0x0027 /*'*/) {
1475c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // Consecutive single quotes are a single quote literal,
1476c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // either outside of quotes or between quotes
147764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            if ((i+1) < adjustedPtn.length() && adjustedPtn.charAt(i+1) == 0x0027 /* ' */) {
1478c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                ++i;
1479c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            } else {
1480c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                inQuote = ! inQuote;
1481c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
148264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        }
148364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        else if ( ! inQuote && ((ch >= 0x0061 /*'a'*/ && ch <= 0x007A /*'z'*/)
1484c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    || (ch >= 0x0041 /*'A'*/ && ch <= 0x005A /*'Z'*/))) {
148564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            // ch is a date-time pattern character
1486c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            prevCh = ch;
1487c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ++count;
1488c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1489c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1490c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( count > 0 ) {
1491c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // last item
1492c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // check the repeativeness of pattern letter
1493c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UChar skeletonChar = prevCh;
1494c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( skeletonChar == CAP_L ) {
149564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            // there is no "L" (always be "M") in skeleton,
1496c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // but there is "L" in pattern.
149764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            // for skeleton "M+", the pattern might be "...L..."
1498c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            skeletonChar = CAP_M;
1499c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1500c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t fieldCount = bestMatchSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
1501c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t inputFieldCount = inputSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
1502c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( fieldCount == count && inputFieldCount > fieldCount ) {
1503c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            count = inputFieldCount - fieldCount;
1504c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            int32_t j;
1505c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            for ( j = 0; j < count; ++j ) {
150664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                adjustedPtn.append(prevCh);
150764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            }
1508c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1509c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1510c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1511c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1512c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1513c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
151464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertvoid
1515c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDateIntervalFormat::concatSingleDate2TimeInterval(UnicodeString& format,
1516c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                              const UnicodeString& datePattern,
1517c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                              UCalendarDateFields field,
1518c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                              UErrorCode& status) {
1519c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // following should not set wrong status
1520c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t itvPtnIndex = DateIntervalInfo::calendarFieldToIntervalIndex(field,
1521c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                                                        status);
1522c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( U_FAILURE(status) ) {
1523c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
1524c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1525c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    PatternInfo&  timeItvPtnInfo = fIntervalPatterns[itvPtnIndex];
1526c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if ( !timeItvPtnInfo.firstPart.isEmpty() ) {
15278de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        UnicodeString timeIntervalPattern(timeItvPtnInfo.firstPart);
15288de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        timeIntervalPattern.append(timeItvPtnInfo.secondPart);
1529c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UnicodeString combinedPattern;
15308de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        SimpleFormatter(format, 2, 2, status).
15318de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                format(timeIntervalPattern, datePattern, combinedPattern, status);
1532c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if ( U_FAILURE(status) ) {
1533c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return;
1534c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1535c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        setIntervalPattern(field, combinedPattern, timeItvPtnInfo.laterDateFirst);
153664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    }
1537c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // else: fall back
1538c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // it should not happen if the interval format defined is valid
1539c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1540c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1541c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1542c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1543c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruconst UChar
1544c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateIntervalFormat::fgCalendarFieldToPatternLetter[] =
1545c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
1546c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /*GyM*/ CAP_G, LOW_Y, CAP_M,
1547c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /*wWd*/ LOW_W, CAP_W, LOW_D,
1548c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /*DEF*/ CAP_D, CAP_E, CAP_F,
1549c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /*ahH*/ LOW_A, LOW_H, CAP_H,
1550fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    /*msS*/ LOW_M, LOW_S, CAP_S, // MINUTE, SECOND, MILLISECOND
1551fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    /*z.Y*/ LOW_Z, SPACE, CAP_Y, // ZONE_OFFSET, DST_OFFSET, YEAR_WOY,
1552fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    /*eug*/ LOW_E, LOW_U, LOW_G, // DOW_LOCAL, EXTENDED_YEAR, JULIAN_DAY,
1553fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    /*A..*/ CAP_A, SPACE, SPACE, // MILLISECONDS_IN_DAY, IS_LEAP_MONTH, FIELD_COUNT
1554c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru};
1555c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1556c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1557c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruU_NAMESPACE_END
1558c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1559c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#endif
1560