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