]> git.saurik.com Git - apple/icu.git/blob - icuSources/i18n/udat.cpp
ICU-6.2.15.tar.gz
[apple/icu.git] / icuSources / i18n / udat.cpp
1 /*
2 *******************************************************************************
3 * Copyright (C) 1996-2004, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 *******************************************************************************
6 */
7
8 #include "unicode/utypes.h"
9
10 #if !UCONFIG_NO_FORMATTING
11
12 #include "unicode/udat.h"
13
14 #include "unicode/uloc.h"
15 #include "unicode/datefmt.h"
16 #include "unicode/timezone.h"
17 #include "unicode/smpdtfmt.h"
18 #include "unicode/fieldpos.h"
19 #include "unicode/parsepos.h"
20 #include "unicode/calendar.h"
21 #include "unicode/numfmt.h"
22 #include "unicode/dtfmtsym.h"
23 #include "unicode/ustring.h"
24 #include "cpputils.h"
25
26 U_NAMESPACE_USE
27
28 U_CAPI UDateFormat* U_EXPORT2
29 udat_open(UDateFormatStyle timeStyle,
30 UDateFormatStyle dateStyle,
31 const char *locale,
32 const UChar *tzID,
33 int32_t tzIDLength,
34 const UChar *pattern,
35 int32_t patternLength,
36 UErrorCode *status)
37 {
38 if(U_FAILURE(*status))
39 {
40 return 0;
41 }
42 if(timeStyle != UDAT_IGNORE)
43 {
44 DateFormat *fmt;
45 if(locale == 0)
46 fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle,
47 (DateFormat::EStyle)timeStyle);
48 else
49 fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle,
50 (DateFormat::EStyle)timeStyle,
51 Locale(locale));
52
53 if(fmt == 0) {
54 *status = U_MEMORY_ALLOCATION_ERROR;
55 return 0;
56 }
57
58 if(tzID != 0) {
59 TimeZone *zone = TimeZone::createTimeZone(UnicodeString((UBool)(tzIDLength == -1), tzID, tzIDLength));
60 if(zone == 0) {
61 *status = U_MEMORY_ALLOCATION_ERROR;
62 delete fmt;
63 return 0;
64 }
65 fmt->adoptTimeZone(zone);
66 }
67
68 return (UDateFormat*)fmt;
69 }
70 else
71 {
72 const UnicodeString pat = UnicodeString((UBool)(patternLength == -1), pattern, patternLength);
73 UDateFormat *retVal = 0;
74
75 if(locale == 0)
76 retVal = (UDateFormat*)new SimpleDateFormat(pat, *status);
77 else
78 retVal = (UDateFormat*)new SimpleDateFormat(pat, Locale(locale), *status);
79
80 if(retVal == 0) {
81 *status = U_MEMORY_ALLOCATION_ERROR;
82 return 0;
83 }
84 return retVal;
85 }
86 }
87
88
89 U_CAPI void U_EXPORT2
90 udat_close(UDateFormat* format)
91 {
92 delete (DateFormat*)format;
93 }
94
95 U_CAPI UDateFormat* U_EXPORT2
96 udat_clone(const UDateFormat *fmt,
97 UErrorCode *status)
98 {
99 if(U_FAILURE(*status)) return 0;
100
101 Format *res = ((SimpleDateFormat*)fmt)->clone();
102
103 if(res == 0) {
104 *status = U_MEMORY_ALLOCATION_ERROR;
105 return 0;
106 }
107
108 return (UDateFormat*) res;
109 }
110
111 U_CAPI int32_t U_EXPORT2
112 udat_format( const UDateFormat* format,
113 UDate dateToFormat,
114 UChar* result,
115 int32_t resultLength,
116 UFieldPosition* position,
117 UErrorCode* status)
118 {
119 if(U_FAILURE(*status)) return -1;
120
121 UnicodeString res;
122 if(!(result==NULL && resultLength==0)) {
123 // NULL destination for pure preflighting: empty dummy string
124 // otherwise, alias the destination buffer
125 res.setTo(result, 0, resultLength);
126 }
127
128 FieldPosition fp;
129
130 if(position != 0)
131 fp.setField(position->field);
132
133 ((DateFormat*)format)->format(dateToFormat, res, fp);
134
135 if(position != 0) {
136 position->beginIndex = fp.getBeginIndex();
137 position->endIndex = fp.getEndIndex();
138 }
139
140 return res.extract(result, resultLength, *status);
141 }
142
143 U_CAPI UDate U_EXPORT2
144 udat_parse( const UDateFormat* format,
145 const UChar* text,
146 int32_t textLength,
147 int32_t *parsePos,
148 UErrorCode *status)
149 {
150 if(U_FAILURE(*status)) return (UDate)0;
151
152 const UnicodeString src((UBool)(textLength == -1), text, textLength);
153 ParsePosition pp;
154 int32_t stackParsePos = 0;
155 UDate res;
156
157 if(parsePos == NULL) {
158 parsePos = &stackParsePos;
159 }
160
161 pp.setIndex(*parsePos);
162
163 res = ((DateFormat*)format)->parse(src, pp);
164
165 if(pp.getErrorIndex() == -1)
166 *parsePos = pp.getIndex();
167 else {
168 *parsePos = pp.getErrorIndex();
169 *status = U_PARSE_ERROR;
170 }
171
172 return res;
173 }
174
175 U_CAPI void U_EXPORT2
176 udat_parseCalendar(const UDateFormat* format,
177 UCalendar* calendar,
178 const UChar* text,
179 int32_t textLength,
180 int32_t *parsePos,
181 UErrorCode *status)
182 {
183 if(U_FAILURE(*status)) return;
184
185 const UnicodeString src((UBool)(textLength == -1), text, textLength);
186 ParsePosition pp;
187
188 if(parsePos != 0)
189 pp.setIndex(*parsePos);
190
191 ((DateFormat*)format)->parse(src, *(Calendar*)calendar, pp);
192
193 if(parsePos != 0) {
194 if(pp.getErrorIndex() == -1)
195 *parsePos = pp.getIndex();
196 else {
197 *parsePos = pp.getErrorIndex();
198 *status = U_PARSE_ERROR;
199 }
200 }
201 }
202
203 U_CAPI UBool U_EXPORT2
204 udat_isLenient(const UDateFormat* fmt)
205 {
206 return ((DateFormat*)fmt)->isLenient();
207 }
208
209 U_CAPI void U_EXPORT2
210 udat_setLenient( UDateFormat* fmt,
211 UBool isLenient)
212 {
213 ((DateFormat*)fmt)->setLenient(isLenient);
214 }
215
216 U_CAPI const UCalendar* U_EXPORT2
217 udat_getCalendar(const UDateFormat* fmt)
218 {
219 return (const UCalendar*) ((DateFormat*)fmt)->getCalendar();
220 }
221
222 U_CAPI void U_EXPORT2
223 udat_setCalendar(UDateFormat* fmt,
224 const UCalendar* calendarToSet)
225 {
226 ((DateFormat*)fmt)->setCalendar(*((Calendar*)calendarToSet));
227 }
228
229 U_CAPI const UNumberFormat* U_EXPORT2
230 udat_getNumberFormat(const UDateFormat* fmt)
231 {
232 return (const UNumberFormat*) ((DateFormat*)fmt)->getNumberFormat();
233 }
234
235 U_CAPI void U_EXPORT2
236 udat_setNumberFormat(UDateFormat* fmt,
237 const UNumberFormat* numberFormatToSet)
238 {
239 ((DateFormat*)fmt)->setNumberFormat(*((NumberFormat*)numberFormatToSet));
240 }
241
242 U_CAPI const char* U_EXPORT2
243 udat_getAvailable(int32_t index)
244 {
245 return uloc_getAvailable(index);
246 }
247
248 U_CAPI int32_t U_EXPORT2
249 udat_countAvailable()
250 {
251 return uloc_countAvailable();
252 }
253
254 U_CAPI UDate U_EXPORT2
255 udat_get2DigitYearStart( const UDateFormat *fmt,
256 UErrorCode *status)
257 {
258 if(U_FAILURE(*status)) return (UDate)0;
259 return ((SimpleDateFormat*)fmt)->get2DigitYearStart(*status);
260 }
261
262 U_CAPI void U_EXPORT2
263 udat_set2DigitYearStart( UDateFormat *fmt,
264 UDate d,
265 UErrorCode *status)
266 {
267 if(U_FAILURE(*status)) return;
268 ((SimpleDateFormat*)fmt)->set2DigitYearStart(d, *status);
269 }
270
271 U_CAPI int32_t U_EXPORT2
272 udat_toPattern( const UDateFormat *fmt,
273 UBool localized,
274 UChar *result,
275 int32_t resultLength,
276 UErrorCode *status)
277 {
278 if(U_FAILURE(*status)) return -1;
279
280 UnicodeString res;
281 if(!(result==NULL && resultLength==0)) {
282 // NULL destination for pure preflighting: empty dummy string
283 // otherwise, alias the destination buffer
284 res.setTo(result, 0, resultLength);
285 }
286
287 if(localized)
288 ((SimpleDateFormat*)fmt)->toLocalizedPattern(res, *status);
289 else
290 ((SimpleDateFormat*)fmt)->toPattern(res);
291
292 return res.extract(result, resultLength, *status);
293 }
294
295 // TBD: should this take an UErrorCode?
296 U_CAPI void U_EXPORT2
297 udat_applyPattern( UDateFormat *format,
298 UBool localized,
299 const UChar *pattern,
300 int32_t patternLength)
301 {
302 const UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength);
303 UErrorCode status = U_ZERO_ERROR;
304
305 if(localized)
306 ((SimpleDateFormat*)format)->applyLocalizedPattern(pat, status);
307 else
308 ((SimpleDateFormat*)format)->applyPattern(pat);
309 }
310
311 U_CAPI int32_t U_EXPORT2
312 udat_getSymbols(const UDateFormat *fmt,
313 UDateFormatSymbolType type,
314 int32_t index,
315 UChar *result,
316 int32_t resultLength,
317 UErrorCode *status)
318 {
319 if(U_FAILURE(*status)) return -1;
320
321 const DateFormatSymbols *syms =
322 ((SimpleDateFormat*)fmt)->getDateFormatSymbols();
323 int32_t count;
324 const UnicodeString *res;
325
326 switch(type) {
327 case UDAT_ERAS:
328 res = syms->getEras(count);
329 if(index < count) {
330 return res[index].extract(result, resultLength, *status);
331 }
332 break;
333
334 case UDAT_MONTHS:
335 res = syms->getMonths(count);
336 if(index < count) {
337 return res[index].extract(result, resultLength, *status);
338 }
339 break;
340
341 case UDAT_SHORT_MONTHS:
342 res = syms->getShortMonths(count);
343 if(index < count) {
344 return res[index].extract(result, resultLength, *status);
345 }
346 break;
347
348 case UDAT_WEEKDAYS:
349 res = syms->getWeekdays(count);
350 if(index < count) {
351 return res[index].extract(result, resultLength, *status);
352 }
353 break;
354
355 case UDAT_SHORT_WEEKDAYS:
356 res = syms->getShortWeekdays(count);
357 if(index < count) {
358 return res[index].extract(result, resultLength, *status);
359 }
360 break;
361
362 case UDAT_AM_PMS:
363 res = syms->getAmPmStrings(count);
364 if(index < count) {
365 return res[index].extract(result, resultLength, *status);
366 }
367 break;
368
369 case UDAT_LOCALIZED_CHARS:
370 {
371 UnicodeString res1;
372 if(!(result==NULL && resultLength==0)) {
373 // NULL destination for pure preflighting: empty dummy string
374 // otherwise, alias the destination buffer
375 res1.setTo(result, 0, resultLength);
376 }
377 syms->getLocalPatternChars(res1);
378 return res1.extract(result, resultLength, *status);
379 }
380 }
381
382 return 0;
383 }
384
385 U_CAPI int32_t U_EXPORT2
386 udat_countSymbols( const UDateFormat *fmt,
387 UDateFormatSymbolType type)
388 {
389 const DateFormatSymbols *syms =
390 ((SimpleDateFormat*)fmt)->getDateFormatSymbols();
391 int32_t count = 0;
392
393 switch(type) {
394 case UDAT_ERAS:
395 syms->getEras(count);
396 break;
397
398 case UDAT_MONTHS:
399 syms->getMonths(count);
400 break;
401
402 case UDAT_SHORT_MONTHS:
403 syms->getShortMonths(count);
404 break;
405
406 case UDAT_WEEKDAYS:
407 syms->getWeekdays(count);
408 break;
409
410 case UDAT_SHORT_WEEKDAYS:
411 syms->getShortWeekdays(count);
412 break;
413
414 case UDAT_AM_PMS:
415 syms->getAmPmStrings(count);
416 break;
417
418 case UDAT_LOCALIZED_CHARS:
419 count = 1;
420 break;
421 }
422
423 return count;
424 }
425
426 U_NAMESPACE_BEGIN
427
428 /*
429 * This DateFormatSymbolsSingleSetter class is a friend of DateFormatSymbols
430 * solely for the purpose of avoiding to clone the array of strings
431 * just to modify one of them and then setting all of them back.
432 * For example, the old code looked like this:
433 * case UDAT_MONTHS:
434 * res = syms->getMonths(count);
435 * array = new UnicodeString[count];
436 * if(array == 0) {
437 * *status = U_MEMORY_ALLOCATION_ERROR;
438 * return;
439 * }
440 * uprv_arrayCopy(res, array, count);
441 * if(index < count)
442 * array[index] = val;
443 * syms->setMonths(array, count);
444 * break;
445 *
446 * Even worse, the old code actually cloned the entire DateFormatSymbols object,
447 * cloned one value array, changed one value, and then made the SimpleDateFormat
448 * replace its DateFormatSymbols object with the new one.
449 *
450 * markus 2002-oct-14
451 */
452 class DateFormatSymbolsSingleSetter /* not : public UObject because all methods are static */ {
453 public:
454 static void
455 setSymbol(UnicodeString *array, int32_t count, int32_t index,
456 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
457 {
458 if(array!=NULL) {
459 if(index>=count) {
460 errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
461 } else if(value==NULL) {
462 errorCode=U_ILLEGAL_ARGUMENT_ERROR;
463 } else {
464 array[index].setTo(value, valueLength);
465 }
466 }
467 }
468
469 static void
470 setEra(DateFormatSymbols *syms, int32_t index,
471 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
472 {
473 setSymbol(syms->fEras, syms->fErasCount, index, value, valueLength, errorCode);
474 }
475
476 static void
477 setMonth(DateFormatSymbols *syms, int32_t index,
478 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
479 {
480 setSymbol(syms->fMonths, syms->fMonthsCount, index, value, valueLength, errorCode);
481 }
482
483 static void
484 setShortMonth(DateFormatSymbols *syms, int32_t index,
485 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
486 {
487 setSymbol(syms->fShortMonths, syms->fShortMonthsCount, index, value, valueLength, errorCode);
488 }
489
490 static void
491 setWeekday(DateFormatSymbols *syms, int32_t index,
492 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
493 {
494 setSymbol(syms->fWeekdays, syms->fWeekdaysCount, index, value, valueLength, errorCode);
495 }
496
497 static void
498 setShortWeekday(DateFormatSymbols *syms, int32_t index,
499 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
500 {
501 setSymbol(syms->fShortWeekdays, syms->fShortWeekdaysCount, index, value, valueLength, errorCode);
502 }
503
504 static void
505 setAmPm(DateFormatSymbols *syms, int32_t index,
506 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
507 {
508 setSymbol(syms->fAmPms, syms->fAmPmsCount, index, value, valueLength, errorCode);
509 }
510
511 static void
512 setLocalPatternChars(DateFormatSymbols *syms,
513 const UChar *value, int32_t valueLength, UErrorCode &errorCode)
514 {
515 setSymbol(&syms->fLocalPatternChars, 1, 0, value, valueLength, errorCode);
516 }
517 };
518
519 U_NAMESPACE_END
520
521 U_CAPI void U_EXPORT2
522 udat_setSymbols( UDateFormat *format,
523 UDateFormatSymbolType type,
524 int32_t index,
525 UChar *value,
526 int32_t valueLength,
527 UErrorCode *status)
528 {
529 if(U_FAILURE(*status)) return;
530
531 DateFormatSymbols *syms = (DateFormatSymbols *)((SimpleDateFormat *)format)->getDateFormatSymbols();
532
533 switch(type) {
534 case UDAT_ERAS:
535 DateFormatSymbolsSingleSetter::setEra(syms, index, value, valueLength, *status);
536 break;
537
538 case UDAT_MONTHS:
539 DateFormatSymbolsSingleSetter::setMonth(syms, index, value, valueLength, *status);
540 break;
541
542 case UDAT_SHORT_MONTHS:
543 DateFormatSymbolsSingleSetter::setShortMonth(syms, index, value, valueLength, *status);
544 break;
545
546 case UDAT_WEEKDAYS:
547 DateFormatSymbolsSingleSetter::setWeekday(syms, index, value, valueLength, *status);
548 break;
549
550 case UDAT_SHORT_WEEKDAYS:
551 DateFormatSymbolsSingleSetter::setShortWeekday(syms, index, value, valueLength, *status);
552 break;
553
554 case UDAT_AM_PMS:
555 DateFormatSymbolsSingleSetter::setAmPm(syms, index, value, valueLength, *status);
556 break;
557
558 case UDAT_LOCALIZED_CHARS:
559 DateFormatSymbolsSingleSetter::setLocalPatternChars(syms, value, valueLength, *status);
560 break;
561 }
562 }
563
564 U_CAPI const char* U_EXPORT2
565 udat_getLocaleByType(const UDateFormat *fmt,
566 ULocDataLocaleType type,
567 UErrorCode* status)
568 {
569 if (fmt == NULL) {
570 if (U_SUCCESS(*status)) {
571 *status = U_ILLEGAL_ARGUMENT_ERROR;
572 }
573 return NULL;
574 }
575 return ((Format*)fmt)->getLocaleID(type, *status);
576 }
577 #endif /* #if !UCONFIG_NO_FORMATTING */