]> git.saurik.com Git - apple/icu.git/blob - icuSources/i18n/datefmt.cpp
ICU-6.2.9.tar.gz
[apple/icu.git] / icuSources / i18n / datefmt.cpp
1 /*
2 *******************************************************************************
3 * Copyright (C) 1997-2004, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
6 *
7 * File DATEFMT.CPP
8 *
9 * Modification History:
10 *
11 * Date Name Description
12 * 02/19/97 aliu Converted from java.
13 * 03/31/97 aliu Modified extensively to work with 50 locales.
14 * 04/01/97 aliu Added support for centuries.
15 * 08/12/97 aliu Fixed operator== to use Calendar::equivalentTo.
16 * 07/20/98 stephen Changed ParsePosition initialization
17 ********************************************************************************
18 */
19
20 #include "unicode/utypes.h"
21
22 #if !UCONFIG_NO_FORMATTING
23
24 #include "unicode/ures.h"
25 #include "unicode/datefmt.h"
26 #include "unicode/smpdtfmt.h"
27
28 #if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
29 #include <stdio.h>
30 #endif
31
32 // *****************************************************************************
33 // class DateFormat
34 // *****************************************************************************
35
36 U_NAMESPACE_BEGIN
37
38 DateFormat::DateFormat()
39 : fCalendar(0),
40 fNumberFormat(0)
41 {
42 }
43
44 //----------------------------------------------------------------------
45
46 DateFormat::DateFormat(const DateFormat& other)
47 : Format(other),
48 fCalendar(0),
49 fNumberFormat(0)
50 {
51 *this = other;
52 }
53
54 //----------------------------------------------------------------------
55
56 DateFormat& DateFormat::operator=(const DateFormat& other)
57 {
58 if (this != &other)
59 {
60 delete fCalendar;
61 delete fNumberFormat;
62 if(other.fCalendar) {
63 fCalendar = other.fCalendar->clone();
64 } else {
65 fCalendar = NULL;
66 }
67 if(other.fNumberFormat) {
68 fNumberFormat = (NumberFormat*)other.fNumberFormat->clone();
69 } else {
70 fNumberFormat = NULL;
71 }
72 }
73 return *this;
74 }
75
76 //----------------------------------------------------------------------
77
78 DateFormat::~DateFormat()
79 {
80 delete fCalendar;
81 delete fNumberFormat;
82 }
83
84 //----------------------------------------------------------------------
85
86 UBool
87 DateFormat::operator==(const Format& other) const
88 {
89 // This protected comparison operator should only be called by subclasses
90 // which have confirmed that the other object being compared against is
91 // an instance of a sublcass of DateFormat. THIS IS IMPORTANT.
92
93 // Format::operator== guarantees that this cast is safe
94 DateFormat* fmt = (DateFormat*)&other;
95
96 return (this == fmt) ||
97 (Format::operator==(other) &&
98 fCalendar&&(fCalendar->isEquivalentTo(*fmt->fCalendar)) &&
99 (fNumberFormat && *fNumberFormat == *fmt->fNumberFormat));
100 }
101
102 //----------------------------------------------------------------------
103
104 UnicodeString&
105 DateFormat::format(const Formattable& obj,
106 UnicodeString& appendTo,
107 FieldPosition& fieldPosition,
108 UErrorCode& status) const
109 {
110 if (U_FAILURE(status)) return appendTo;
111
112 // if the type of the Formattable is double or long, treat it as if it were a Date
113 UDate date = 0;
114 switch (obj.getType())
115 {
116 case Formattable::kDate:
117 date = obj.getDate();
118 break;
119 case Formattable::kDouble:
120 date = (UDate)obj.getDouble();
121 break;
122 case Formattable::kLong:
123 date = (UDate)obj.getLong();
124 break;
125 default:
126 status = U_ILLEGAL_ARGUMENT_ERROR;
127 return appendTo;
128 }
129
130 // Is this right?
131 //if (fieldPosition.getBeginIndex() == fieldPosition.getEndIndex())
132 // status = U_ILLEGAL_ARGUMENT_ERROR;
133
134 return format(date, appendTo, fieldPosition);
135 }
136
137 //----------------------------------------------------------------------
138
139 UnicodeString&
140 DateFormat::format(UDate date, UnicodeString& appendTo, FieldPosition& fieldPosition) const {
141 if (fCalendar != NULL) {
142 // Use our calendar instance
143 UErrorCode ec = U_ZERO_ERROR;
144 fCalendar->setTime(date, ec);
145 if (U_SUCCESS(ec)) {
146 return format(*fCalendar, appendTo, fieldPosition);
147 }
148 }
149 return appendTo;
150 }
151
152 //----------------------------------------------------------------------
153
154 UnicodeString&
155 DateFormat::format(UDate date, UnicodeString& appendTo) const
156 {
157 // Note that any error information is just lost. That's okay
158 // for this convenience method.
159 FieldPosition fpos(0);
160 return format(date, appendTo, fpos);
161 }
162
163 //----------------------------------------------------------------------
164
165 UDate
166 DateFormat::parse(const UnicodeString& text,
167 ParsePosition& pos) const
168 {
169 if (fCalendar != NULL) {
170 int32_t start = pos.getIndex();
171 fCalendar->clear();
172 parse(text, *fCalendar, pos);
173 if (pos.getIndex() != start) {
174 UErrorCode ec = U_ZERO_ERROR;
175 UDate d = fCalendar->getTime(ec);
176 if (U_SUCCESS(ec)) {
177 return d; // Successful function exit
178 }
179 // We arrive here if fCalendar is non-lenient and there
180 // is an out-of-range field. We don't know which field
181 // was illegal so we set the error index to the start.
182 pos.setIndex(start);
183 pos.setErrorIndex(start);
184 }
185 }
186 return 0; // Error return UDate is 0 (the epoch)
187 }
188
189 //----------------------------------------------------------------------
190
191 UDate
192 DateFormat::parse(const UnicodeString& text,
193 UErrorCode& status) const
194 {
195 if (U_FAILURE(status)) return 0;
196
197 ParsePosition pos(0);
198 UDate result = parse(text, pos);
199 if (pos.getIndex() == 0) {
200 #if defined (U_DEBUG_CAL)
201 fprintf(stderr, "%s:%d - - failed to parse - err index %d\n"
202 , __FILE__, __LINE__, pos.getErrorIndex() );
203 #endif
204 status = U_ILLEGAL_ARGUMENT_ERROR;
205 }
206 return result;
207 }
208
209 //----------------------------------------------------------------------
210
211 void
212 DateFormat::parseObject(const UnicodeString& source,
213 Formattable& result,
214 ParsePosition& pos) const
215 {
216 result.setDate(parse(source, pos));
217 }
218
219 //----------------------------------------------------------------------
220
221 DateFormat* U_EXPORT2
222 DateFormat::createTimeInstance(DateFormat::EStyle style,
223 const Locale& aLocale)
224 {
225 return create(style, kNone, aLocale);
226 }
227
228 //----------------------------------------------------------------------
229
230 DateFormat* U_EXPORT2
231 DateFormat::createDateInstance(DateFormat::EStyle style,
232 const Locale& aLocale)
233 {
234 // +4 to set the correct index for getting data out of
235 // LocaleElements.
236 if(style != kNone)
237 {
238 style = (EStyle) (style + kDateOffset);
239 }
240 return create(kNone, (EStyle) (style), aLocale);
241 }
242
243 //----------------------------------------------------------------------
244
245 DateFormat* U_EXPORT2
246 DateFormat::createDateTimeInstance(EStyle dateStyle,
247 EStyle timeStyle,
248 const Locale& aLocale)
249 {
250 if(dateStyle != kNone)
251 {
252 dateStyle = (EStyle) (dateStyle + kDateOffset);
253 }
254 return create(timeStyle, dateStyle, aLocale);
255 }
256
257 //----------------------------------------------------------------------
258
259 DateFormat* U_EXPORT2
260 DateFormat::createInstance()
261 {
262 return create(kShort, (EStyle) (kShort + kDateOffset), Locale::getDefault());
263 }
264
265 //----------------------------------------------------------------------
266
267 DateFormat* U_EXPORT2
268 DateFormat::create(EStyle timeStyle, EStyle dateStyle, const Locale& locale)
269 {
270 // Try to create a SimpleDateFormat of the desired style.
271 UErrorCode status = U_ZERO_ERROR;
272 SimpleDateFormat *f = new SimpleDateFormat(timeStyle, dateStyle, locale, status);
273 if (U_SUCCESS(status)) return f;
274 delete f;
275
276 // If that fails, try to create a format using the default pattern and
277 // the DateFormatSymbols for this locale.
278 status = U_ZERO_ERROR;
279 f = new SimpleDateFormat(locale, status);
280 if (U_SUCCESS(status)) return f;
281 delete f;
282
283 // This should never really happen, because the preceding constructor
284 // should always succeed. If the resource data is unavailable, a last
285 // resort object should be returned.
286 return 0;
287 }
288
289 //----------------------------------------------------------------------
290
291 const Locale* U_EXPORT2
292 DateFormat::getAvailableLocales(int32_t& count)
293 {
294 // Get the list of installed locales.
295 // Even if root has the correct date format for this locale,
296 // it's still a valid locale (we don't worry about data fallbacks).
297 return Locale::getAvailableLocales(count);
298 }
299
300 //----------------------------------------------------------------------
301
302 void
303 DateFormat::adoptCalendar(Calendar* newCalendar)
304 {
305 delete fCalendar;
306 fCalendar = newCalendar;
307 }
308
309 //----------------------------------------------------------------------
310 void
311 DateFormat::setCalendar(const Calendar& newCalendar)
312 {
313 adoptCalendar(newCalendar.clone());
314 }
315
316 //----------------------------------------------------------------------
317
318 const Calendar*
319 DateFormat::getCalendar() const
320 {
321 return fCalendar;
322 }
323
324 //----------------------------------------------------------------------
325
326 void
327 DateFormat::adoptNumberFormat(NumberFormat* newNumberFormat)
328 {
329 delete fNumberFormat;
330 fNumberFormat = newNumberFormat;
331 newNumberFormat->setParseIntegerOnly(TRUE);
332 }
333 //----------------------------------------------------------------------
334
335 void
336 DateFormat::setNumberFormat(const NumberFormat& newNumberFormat)
337 {
338 adoptNumberFormat((NumberFormat*)newNumberFormat.clone());
339 }
340
341 //----------------------------------------------------------------------
342
343 const NumberFormat*
344 DateFormat::getNumberFormat() const
345 {
346 return fNumberFormat;
347 }
348
349 //----------------------------------------------------------------------
350
351 void
352 DateFormat::adoptTimeZone(TimeZone* zone)
353 {
354 fCalendar->adoptTimeZone(zone);
355 }
356 //----------------------------------------------------------------------
357
358 void
359 DateFormat::setTimeZone(const TimeZone& zone)
360 {
361 fCalendar->setTimeZone(zone);
362 }
363
364 //----------------------------------------------------------------------
365
366 const TimeZone&
367 DateFormat::getTimeZone() const
368 {
369 return fCalendar->getTimeZone();
370 }
371
372 //----------------------------------------------------------------------
373
374 void
375 DateFormat::setLenient(UBool lenient)
376 {
377 fCalendar->setLenient(lenient);
378 }
379
380 //----------------------------------------------------------------------
381
382 UBool
383 DateFormat::isLenient() const
384 {
385 return fCalendar->isLenient();
386 }
387
388 U_NAMESPACE_END
389
390 #endif /* #if !UCONFIG_NO_FORMATTING */
391
392 //eof