1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
3b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* Copyright (C) 2007-2009, International Business Machines Corporation and    *
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* others. All Rights Reserved.                                                *
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//#define DEBUG_RELDTFMT
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <stdio.h>
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <stdlib.h>
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "reldtfmt.h"
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/msgfmt.h"
19b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/smpdtfmt.h"
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "gregoimp.h" // for CalendarData
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * An array of URelativeString structs is used to store the resource data loaded out of the bundle.
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct URelativeString {
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offset;         /** offset of this item, such as, the relative date **/
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t len;            /** length of the string **/
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar* string;    /** string, or NULL if not set **/
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
36b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char DT_DateTimePatternsTag[]="DateTimePatterns";
37b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(RelativeDateFormat)
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRelativeDateFormat::RelativeDateFormat(const RelativeDateFormat& other) :
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateFormat(other), fDateFormat(NULL), fTimeFormat(NULL), fCombinedFormat(NULL),
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufDateStyle(other.fDateStyle), fTimeStyle(other.fTimeStyle), fLocale(other.fLocale),
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufDayMin(other.fDayMin), fDayMax(other.fDayMax),
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufDatesLen(other.fDatesLen), fDates(NULL)
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(other.fDateFormat != NULL) {
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fDateFormat = (DateFormat*)other.fDateFormat->clone();
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fDateFormat = NULL;
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fDatesLen > 0) {
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*fDatesLen);
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_memcpy(fDates, other.fDates, sizeof(fDates[0])*fDatesLen);
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //fCalendar = other.fCalendar->clone();
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(other.fTimeFormat != NULL) {
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fTimeFormat = (DateFormat*)other.fTimeFormat->clone();
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fTimeFormat = NULL;
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRelativeDateFormat::RelativeDateFormat( UDateFormatStyle timeStyle, UDateFormatStyle dateStyle, const Locale& locale, UErrorCode& status)
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru : DateFormat(), fDateFormat(NULL), fTimeFormat(NULL), fCombinedFormat(NULL),
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufDateStyle(dateStyle), fTimeStyle(timeStyle), fLocale(locale), fDatesLen(0), fDates(NULL)
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru {
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(status) ) {
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(fDateStyle != UDAT_NONE) {
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        EStyle newStyle = (EStyle)(fDateStyle & ~UDAT_RELATIVE);
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Create a DateFormat in the non-relative style requested.
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fDateFormat = createDateInstance(newStyle, locale);
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
79b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(fTimeStyle >= UDAT_FULL && fTimeStyle <= UDAT_SHORT) {
80b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        fTimeFormat = createTimeInstance((EStyle)fTimeStyle, locale);
81b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    } else if(fTimeStyle != UDAT_NONE) {
82b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // don't support other time styles (e.g. relative styles), for now
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_ILLEGAL_ARGUMENT_ERROR;
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Initialize the parent fCalendar, so that parse() works correctly.
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    initializeCalendar(NULL, locale, status);
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    loadDates(status);
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRelativeDateFormat::~RelativeDateFormat() {
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete fDateFormat;
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete fTimeFormat;
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete fCombinedFormat;
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(fDates);
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruFormat* RelativeDateFormat::clone(void) const {
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return new RelativeDateFormat(*this);
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool RelativeDateFormat::operator==(const Format& other) const {
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(DateFormat::operator==(other)) {
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // DateFormat::operator== guarantees following cast is safe
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        RelativeDateFormat* that = (RelativeDateFormat*)&other;
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return (fDateStyle==that->fDateStyle   &&
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fTimeStyle==that->fTimeStyle   &&
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fLocale==that->fLocale);
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString& RelativeDateFormat::format(  Calendar& cal,
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                UnicodeString& appendTo,
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                FieldPosition& pos) const {
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
120b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UChar emptyStr = 0;
121b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UnicodeString dateString(&emptyStr);
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // calculate the difference, in days, between 'cal' and now.
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int dayDiff = dayDifference(cal, status);
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // look up string
12750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t len = 0;
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar *theString = getStringForDay(dayDiff, len, status);
129b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(U_SUCCESS(status) && (theString!=NULL)) {
130b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // found a relative string
131b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        dateString.setTo(theString, len);
132b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
134b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(fTimeFormat == NULL || fCombinedFormat == 0) {
135b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (dateString.length() > 0) {
136b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            appendTo.append(dateString);
137b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        } else if(fDateFormat != NULL) {
138b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fDateFormat->format(cal,appendTo,pos);
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
141b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (dateString.length() == 0 && fDateFormat != NULL) {
142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fDateFormat->format(cal,dateString,pos);
143b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
144b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UnicodeString timeString(&emptyStr);
145b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        FieldPosition timepos = pos;
146b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        fTimeFormat->format(cal,timeString,timepos);
147b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        Formattable timeDateStrings[] = { timeString, dateString };
148b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        fCombinedFormat->format(timeDateStrings, 2, appendTo, pos, status); // pos is ignored by this
149b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        int32_t offset;
150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (pos.getEndIndex() > 0 && (offset = appendTo.indexOf(dateString)) >= 0) {
151b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // pos.field was found in dateString, offset start & end based on final position of dateString
152b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            pos.setBeginIndex( pos.getBeginIndex() + offset );
153b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            pos.setEndIndex( pos.getEndIndex() + offset );
154b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        } else if (timepos.getEndIndex() > 0 && (offset = appendTo.indexOf(timeString)) >= 0) {
155b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // pos.field was found in timeString, offset start & end based on final position of timeString
156b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            pos.setBeginIndex( timepos.getBeginIndex() + offset );
157b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            pos.setEndIndex( timepos.getEndIndex() + offset );
158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return appendTo;
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRelativeDateFormat::format(const Formattable& obj,
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         UnicodeString& appendTo,
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         FieldPosition& pos,
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         UErrorCode& status) const
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // this is just here to get around the hiding problem
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // (the previous format() override would hide the version of
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // format() on DateFormat that this function correspond to, so we
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // have to redefine it here)
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return DateFormat::format(obj, appendTo, pos, status);
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid RelativeDateFormat::parse( const UnicodeString& text,
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    Calendar& cal,
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ParsePosition& pos) const {
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Can the fDateFormat parse it?
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(fDateFormat != NULL) {
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ParsePosition aPos(pos);
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fDateFormat->parse(text,cal,aPos);
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if((aPos.getIndex() != pos.getIndex()) &&
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            (aPos.getErrorIndex()==-1)) {
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos=aPos; // copy the sub parse
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return; // parsed subfmt OK
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Linear search the relative strings
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(int n=0;n<fDatesLen;n++) {
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(fDates[n].string != NULL &&
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            (0==text.compare(pos.getIndex(),
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         fDates[n].len,
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         fDates[n].string))) {
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UErrorCode status = U_ZERO_ERROR;
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Set the calendar to now+offset
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            cal.setTime(Calendar::getNow(),status);
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            cal.add(UCAL_DATE,fDates[n].offset, status);
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(U_FAILURE(status)) {
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // failure in setting calendar fields
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setErrorIndex(pos.getIndex()+fDates[n].len);
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setIndex(pos.getIndex()+fDates[n].len);
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // parse failed
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUDate
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRelativeDateFormat::parse( const UnicodeString& text,
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         ParsePosition& pos) const {
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // redefined here because the other parse() function hides this function's
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // cunterpart on DateFormat
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return DateFormat::parse(text, pos);
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUDate
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRelativeDateFormat::parse(const UnicodeString& text, UErrorCode& status) const
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // redefined here because the other parse() function hides this function's
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // counterpart on DateFormat
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return DateFormat::parse(text, status);
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UChar *RelativeDateFormat::getStringForDay(int32_t day, int32_t &len, UErrorCode &status) const {
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(status)) {
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Is it outside the resource bundle's range?
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(day < fDayMin || day > fDayMax) {
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL; // don't have it.
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Linear search the held strings
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(int n=0;n<fDatesLen;n++) {
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(fDates[n].offset == day) {
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            len = fDates[n].len;
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return fDates[n].string;
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return NULL;  // not found.
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
258b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString&
259b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruRelativeDateFormat::toPattern(UnicodeString& result, UErrorCode& status) const
260b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru{
261b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (!U_FAILURE(status)) {
262b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        result.remove();
263b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (fTimeFormat == NULL || fCombinedFormat == 0) {
264b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (fDateFormat != NULL) {
265b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                UnicodeString datePattern;
266b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                this->toPatternDate(datePattern, status);
267b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (!U_FAILURE(status)) {
268b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    result.setTo(datePattern);
269b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
270b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
271b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        } else {
272b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            UnicodeString datePattern, timePattern;
273b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            this->toPatternDate(datePattern, status);
274b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            this->toPatternTime(timePattern, status);
275b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (!U_FAILURE(status)) {
276b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                Formattable timeDatePatterns[] = { timePattern, datePattern };
277b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                FieldPosition pos;
278b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                fCombinedFormat->format(timeDatePatterns, 2, result, pos, status);
279b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
280b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
281b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
282b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return result;
283b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
284b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
285b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString&
286b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruRelativeDateFormat::toPatternDate(UnicodeString& result, UErrorCode& status) const
287b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru{
288b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (!U_FAILURE(status)) {
289b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        result.remove();
290b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if ( fDateFormat ) {
291b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if ( fDateFormat->getDynamicClassID()==SimpleDateFormat::getStaticClassID() ) {
292b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                ((SimpleDateFormat*)fDateFormat)->toPattern(result);
293b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else {
294b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                status = U_UNSUPPORTED_ERROR;
295b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
296b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
297b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
298b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return result;
299b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
300b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString&
302b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruRelativeDateFormat::toPatternTime(UnicodeString& result, UErrorCode& status) const
303b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru{
304b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (!U_FAILURE(status)) {
305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        result.remove();
306b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if ( fTimeFormat ) {
307b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if ( fTimeFormat->getDynamicClassID()==SimpleDateFormat::getStaticClassID() ) {
308b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                ((SimpleDateFormat*)fTimeFormat)->toPattern(result);
309b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else {
310b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                status = U_UNSUPPORTED_ERROR;
311b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
312b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
313b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
314b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return result;
315b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
316b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
317b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid
318b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruRelativeDateFormat::applyPatterns(const UnicodeString& datePattern, const UnicodeString& timePattern, UErrorCode &status)
319b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru{
320b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (!U_FAILURE(status)) {
321b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if ( fDateFormat && fDateFormat->getDynamicClassID()!=SimpleDateFormat::getStaticClassID() ) {
322b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            status = U_UNSUPPORTED_ERROR;
323b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return;
324b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
325b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if ( fTimeFormat && fTimeFormat->getDynamicClassID()!=SimpleDateFormat::getStaticClassID() ) {
326b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            status = U_UNSUPPORTED_ERROR;
327b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return;
328b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
329b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if ( fDateFormat ) {
330b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ((SimpleDateFormat*)fDateFormat)->applyPattern(datePattern);
331b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
332b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if ( fTimeFormat ) {
333b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ((SimpleDateFormat*)fTimeFormat)->applyPattern(timePattern);
334b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
335b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
336b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
337b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid RelativeDateFormat::loadDates(UErrorCode &status) {
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CalendarData calData(fLocale, "gregorian", status);
340b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
341b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode tempStatus = status;
342b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UResourceBundle *dateTimePatterns = calData.getByKey(DT_DateTimePatternsTag, tempStatus);
343b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(U_SUCCESS(tempStatus)) {
344b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        int32_t patternsSize = ures_getSize(dateTimePatterns);
345b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (patternsSize > kDateTime) {
346b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            int32_t resStrLen = 0;
347b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
348b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            int32_t glueIndex = kDateTime;
349b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (patternsSize >= (DateFormat::kDateTimeOffset + DateFormat::kShort + 1)) {
350b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // Get proper date time format
351b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                switch (fDateStyle) {
352b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	            case kFullRelative:
353b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	            case kFull:
354b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	                glueIndex = kDateTimeOffset + kFull;
355b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	                break;
356b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	            case kLongRelative:
357b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	            case kLong:
358b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	                glueIndex = kDateTimeOffset + kLong;
359b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	                break;
360b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	            case kMediumRelative:
361b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	            case kMedium:
362b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	                glueIndex = kDateTimeOffset + kMedium;
363b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	                break;
364b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	            case kShortRelative:
365b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	            case kShort:
366b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	                glueIndex = kDateTimeOffset + kShort;
367b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	                break;
368b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	            default:
369b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	                break;
370b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 	            }
371b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
372b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
373b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            const UChar *resStr = ures_getStringByIndex(dateTimePatterns, glueIndex, &resStrLen, &tempStatus);
374b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            fCombinedFormat = new MessageFormat(UnicodeString(TRUE, resStr, resStrLen), fLocale, tempStatus);
375b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
376b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
377b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle *strings = calData.getByKey3("fields", "day", "relative", status);
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // set up min/max
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fDayMin=-1;
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fDayMax=1;
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(status)) {
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fDatesLen=0;
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fDatesLen = ures_getSize(strings);
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*fDatesLen);
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Load in each item into the array...
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int n = 0;
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle *subString = NULL;
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(ures_hasNext(strings) && U_SUCCESS(status)) {  // iterate over items
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        subString = ures_getNextResource(strings, subString, &status);
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(U_FAILURE(status) || (subString==NULL)) break;
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // key = offset #
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const char *key = ures_getKey(subString);
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // load the string and length
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t aLen;
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const UChar* aString = ures_getString(subString, &aLen, &status);
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(U_FAILURE(status) || aString == NULL) break;
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // calculate the offset
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t offset = atoi(key);
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // set min/max
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(offset < fDayMin) {
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fDayMin = offset;
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(offset > fDayMax) {
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fDayMax = offset;
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // copy the string pointer
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fDates[n].offset = offset;
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fDates[n].string = aString;
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fDates[n].len = aLen;
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        n++;
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(subString);
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // the fDates[] array could be sorted here, for direct access.
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// this should to be in DateFormat, instead it was copied from SimpleDateFormat.
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar*
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRelativeDateFormat::initializeCalendar(TimeZone* adoptZone, const Locale& locale, UErrorCode& status)
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!U_FAILURE(status)) {
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fCalendar = Calendar::createInstance(adoptZone?adoptZone:TimeZone::createDefault(), locale, status);
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(status) && fCalendar == NULL) {
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fCalendar;
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t RelativeDateFormat::dayDifference(Calendar &cal, UErrorCode &status) {
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(status)) {
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
452c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // TODO: Cache the nowCal to avoid heap allocs? Would be difficult, don't know the calendar type
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Calendar *nowCal = cal.clone();
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    nowCal->setTime(Calendar::getNow(), status);
455c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
456c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // For the day difference, we are interested in the difference in the (modified) julian day number
457c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // which is midnight to midnight.  Using fieldDifference() is NOT correct here, because
458c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // 6pm Jan 4th  to 10am Jan 5th should be considered "tomorrow".
459c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t dayDiff = cal.get(UCAL_JULIAN_DAY, status) - nowCal->get(UCAL_JULIAN_DAY, status);
460c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete nowCal;
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return dayDiff;
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
469