]>
Commit | Line | Data |
---|---|---|
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 | ||
39 | U_NAMESPACE_BEGIN | |
40 | ||
41 | DateFormat::DateFormat() | |
42 | : fCalendar(0), | |
43 | fNumberFormat(0) | |
44 | { | |
45 | } | |
46 | ||
47 | //---------------------------------------------------------------------- | |
48 | ||
49 | DateFormat::DateFormat(const DateFormat& other) | |
50 | : Format(other), | |
51 | fCalendar(0), | |
52 | fNumberFormat(0) | |
53 | { | |
54 | *this = other; | |
55 | } | |
56 | ||
57 | //---------------------------------------------------------------------- | |
58 | ||
59 | DateFormat& 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 | ||
81 | DateFormat::~DateFormat() | |
82 | { | |
83 | delete fCalendar; | |
84 | delete fNumberFormat; | |
85 | } | |
86 | ||
87 | //---------------------------------------------------------------------- | |
88 | ||
89 | UBool | |
90 | DateFormat::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 | ||
107 | UnicodeString& | |
108 | DateFormat::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 | ||
142 | UnicodeString& | |
143 | DateFormat::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 | ||
157 | UnicodeString& | |
158 | DateFormat::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 | ||
168 | UDate | |
169 | DateFormat::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 | ||
194 | UDate | |
195 | DateFormat::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 | ||
214 | void | |
215 | DateFormat::parseObject(const UnicodeString& source, | |
216 | Formattable& result, | |
217 | ParsePosition& pos) const | |
218 | { | |
219 | result.setDate(parse(source, pos)); | |
220 | } | |
221 | ||
222 | //---------------------------------------------------------------------- | |
223 | ||
374ca955 | 224 | DateFormat* U_EXPORT2 |
b75a7d8f A |
225 | DateFormat::createTimeInstance(DateFormat::EStyle style, |
226 | const Locale& aLocale) | |
227 | { | |
228 | return create(style, kNone, aLocale); | |
229 | } | |
230 | ||
231 | //---------------------------------------------------------------------- | |
232 | ||
374ca955 | 233 | DateFormat* U_EXPORT2 |
b75a7d8f A |
234 | DateFormat::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 | 248 | DateFormat* U_EXPORT2 |
b75a7d8f A |
249 | DateFormat::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 | 262 | DateFormat* U_EXPORT2 |
b75a7d8f A |
263 | DateFormat::createInstance() |
264 | { | |
265 | return create(kShort, (EStyle) (kShort + kDateOffset), Locale::getDefault()); | |
266 | } | |
267 | ||
268 | //---------------------------------------------------------------------- | |
269 | ||
374ca955 | 270 | DateFormat* U_EXPORT2 |
b75a7d8f A |
271 | DateFormat::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 | 311 | const Locale* U_EXPORT2 |
b75a7d8f A |
312 | DateFormat::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 | ||
322 | void | |
323 | DateFormat::adoptCalendar(Calendar* newCalendar) | |
324 | { | |
325 | delete fCalendar; | |
326 | fCalendar = newCalendar; | |
327 | } | |
328 | ||
329 | //---------------------------------------------------------------------- | |
330 | void | |
331 | DateFormat::setCalendar(const Calendar& newCalendar) | |
332 | { | |
333 | adoptCalendar(newCalendar.clone()); | |
334 | } | |
335 | ||
336 | //---------------------------------------------------------------------- | |
337 | ||
338 | const Calendar* | |
339 | DateFormat::getCalendar() const | |
340 | { | |
341 | return fCalendar; | |
342 | } | |
343 | ||
344 | //---------------------------------------------------------------------- | |
345 | ||
346 | void | |
347 | DateFormat::adoptNumberFormat(NumberFormat* newNumberFormat) | |
348 | { | |
349 | delete fNumberFormat; | |
350 | fNumberFormat = newNumberFormat; | |
351 | newNumberFormat->setParseIntegerOnly(TRUE); | |
352 | } | |
353 | //---------------------------------------------------------------------- | |
354 | ||
355 | void | |
356 | DateFormat::setNumberFormat(const NumberFormat& newNumberFormat) | |
357 | { | |
358 | adoptNumberFormat((NumberFormat*)newNumberFormat.clone()); | |
359 | } | |
360 | ||
361 | //---------------------------------------------------------------------- | |
362 | ||
363 | const NumberFormat* | |
364 | DateFormat::getNumberFormat() const | |
365 | { | |
366 | return fNumberFormat; | |
367 | } | |
368 | ||
369 | //---------------------------------------------------------------------- | |
370 | ||
371 | void | |
372 | DateFormat::adoptTimeZone(TimeZone* zone) | |
373 | { | |
374 | fCalendar->adoptTimeZone(zone); | |
375 | } | |
376 | //---------------------------------------------------------------------- | |
377 | ||
378 | void | |
379 | DateFormat::setTimeZone(const TimeZone& zone) | |
380 | { | |
381 | fCalendar->setTimeZone(zone); | |
382 | } | |
383 | ||
384 | //---------------------------------------------------------------------- | |
385 | ||
386 | const TimeZone& | |
387 | DateFormat::getTimeZone() const | |
388 | { | |
389 | return fCalendar->getTimeZone(); | |
390 | } | |
391 | ||
392 | //---------------------------------------------------------------------- | |
393 | ||
394 | void | |
395 | DateFormat::setLenient(UBool lenient) | |
396 | { | |
397 | fCalendar->setLenient(lenient); | |
398 | } | |
399 | ||
400 | //---------------------------------------------------------------------- | |
401 | ||
402 | UBool | |
403 | DateFormat::isLenient() const | |
404 | { | |
405 | return fCalendar->isLenient(); | |
406 | } | |
407 | ||
408 | U_NAMESPACE_END | |
409 | ||
410 | #endif /* #if !UCONFIG_NO_FORMATTING */ | |
411 | ||
412 | //eof |