]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/udat.cpp
ICU-6.2.14.tar.gz
[apple/icu.git] / icuSources / i18n / udat.cpp
CommitLineData
b75a7d8f
A
1/*
2*******************************************************************************
374ca955 3* Copyright (C) 1996-2004, International Business Machines
b75a7d8f
A
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
26U_NAMESPACE_USE
27
28U_CAPI UDateFormat* U_EXPORT2
29udat_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{
374ca955
A
38 if(U_FAILURE(*status))
39 {
b75a7d8f 40 return 0;
374ca955
A
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;
b75a7d8f 56 }
374ca955
A
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 }
b75a7d8f
A
86}
87
88
89U_CAPI void U_EXPORT2
90udat_close(UDateFormat* format)
91{
374ca955 92 delete (DateFormat*)format;
b75a7d8f
A
93}
94
95U_CAPI UDateFormat* U_EXPORT2
96udat_clone(const UDateFormat *fmt,
97 UErrorCode *status)
98{
374ca955 99 if(U_FAILURE(*status)) return 0;
b75a7d8f 100
374ca955 101 Format *res = ((SimpleDateFormat*)fmt)->clone();
b75a7d8f 102
374ca955
A
103 if(res == 0) {
104 *status = U_MEMORY_ALLOCATION_ERROR;
105 return 0;
106 }
b75a7d8f 107
374ca955 108 return (UDateFormat*) res;
b75a7d8f
A
109}
110
111U_CAPI int32_t U_EXPORT2
112udat_format( const UDateFormat* format,
113 UDate dateToFormat,
114 UChar* result,
115 int32_t resultLength,
116 UFieldPosition* position,
117 UErrorCode* status)
118{
374ca955
A
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;
b75a7d8f 129
374ca955
A
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);
b75a7d8f
A
141}
142
143U_CAPI UDate U_EXPORT2
144udat_parse( const UDateFormat* format,
145 const UChar* text,
146 int32_t textLength,
147 int32_t *parsePos,
148 UErrorCode *status)
149{
374ca955 150 if(U_FAILURE(*status)) return (UDate)0;
b75a7d8f 151
374ca955
A
152 const UnicodeString src((UBool)(textLength == -1), text, textLength);
153 ParsePosition pp;
154 int32_t stackParsePos = 0;
155 UDate res;
b75a7d8f 156
374ca955
A
157 if(parsePos == NULL) {
158 parsePos = &stackParsePos;
159 }
b75a7d8f 160
b75a7d8f
A
161 pp.setIndex(*parsePos);
162
374ca955 163 res = ((DateFormat*)format)->parse(src, pp);
b75a7d8f 164
b75a7d8f 165 if(pp.getErrorIndex() == -1)
374ca955 166 *parsePos = pp.getIndex();
b75a7d8f 167 else {
374ca955
A
168 *parsePos = pp.getErrorIndex();
169 *status = U_PARSE_ERROR;
b75a7d8f 170 }
374ca955
A
171
172 return res;
b75a7d8f
A
173}
174
175U_CAPI void U_EXPORT2
176udat_parseCalendar(const UDateFormat* format,
177 UCalendar* calendar,
178 const UChar* text,
179 int32_t textLength,
180 int32_t *parsePos,
181 UErrorCode *status)
182{
374ca955 183 if(U_FAILURE(*status)) return;
b75a7d8f 184
374ca955
A
185 const UnicodeString src((UBool)(textLength == -1), text, textLength);
186 ParsePosition pp;
b75a7d8f 187
374ca955
A
188 if(parsePos != 0)
189 pp.setIndex(*parsePos);
b75a7d8f 190
374ca955 191 ((DateFormat*)format)->parse(src, *(Calendar*)calendar, pp);
b75a7d8f 192
374ca955
A
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 }
b75a7d8f 200 }
b75a7d8f
A
201}
202
203U_CAPI UBool U_EXPORT2
204udat_isLenient(const UDateFormat* fmt)
205{
374ca955 206 return ((DateFormat*)fmt)->isLenient();
b75a7d8f
A
207}
208
209U_CAPI void U_EXPORT2
210udat_setLenient( UDateFormat* fmt,
211 UBool isLenient)
212{
374ca955 213 ((DateFormat*)fmt)->setLenient(isLenient);
b75a7d8f
A
214}
215
216U_CAPI const UCalendar* U_EXPORT2
217udat_getCalendar(const UDateFormat* fmt)
218{
374ca955 219 return (const UCalendar*) ((DateFormat*)fmt)->getCalendar();
b75a7d8f
A
220}
221
222U_CAPI void U_EXPORT2
374ca955
A
223udat_setCalendar(UDateFormat* fmt,
224 const UCalendar* calendarToSet)
b75a7d8f 225{
374ca955 226 ((DateFormat*)fmt)->setCalendar(*((Calendar*)calendarToSet));
b75a7d8f
A
227}
228
229U_CAPI const UNumberFormat* U_EXPORT2
230udat_getNumberFormat(const UDateFormat* fmt)
231{
374ca955 232 return (const UNumberFormat*) ((DateFormat*)fmt)->getNumberFormat();
b75a7d8f
A
233}
234
235U_CAPI void U_EXPORT2
374ca955
A
236udat_setNumberFormat(UDateFormat* fmt,
237 const UNumberFormat* numberFormatToSet)
b75a7d8f 238{
374ca955 239 ((DateFormat*)fmt)->setNumberFormat(*((NumberFormat*)numberFormatToSet));
b75a7d8f
A
240}
241
242U_CAPI const char* U_EXPORT2
243udat_getAvailable(int32_t index)
244{
374ca955 245 return uloc_getAvailable(index);
b75a7d8f
A
246}
247
248U_CAPI int32_t U_EXPORT2
249udat_countAvailable()
250{
374ca955 251 return uloc_countAvailable();
b75a7d8f
A
252}
253
254U_CAPI UDate U_EXPORT2
255udat_get2DigitYearStart( const UDateFormat *fmt,
374ca955 256 UErrorCode *status)
b75a7d8f 257{
374ca955
A
258 if(U_FAILURE(*status)) return (UDate)0;
259 return ((SimpleDateFormat*)fmt)->get2DigitYearStart(*status);
b75a7d8f
A
260}
261
262U_CAPI void U_EXPORT2
263udat_set2DigitYearStart( UDateFormat *fmt,
374ca955
A
264 UDate d,
265 UErrorCode *status)
b75a7d8f 266{
374ca955
A
267 if(U_FAILURE(*status)) return;
268 ((SimpleDateFormat*)fmt)->set2DigitYearStart(d, *status);
b75a7d8f
A
269}
270
271U_CAPI int32_t U_EXPORT2
272udat_toPattern( const UDateFormat *fmt,
273 UBool localized,
274 UChar *result,
275 int32_t resultLength,
276 UErrorCode *status)
277{
374ca955 278 if(U_FAILURE(*status)) return -1;
b75a7d8f 279
374ca955
A
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 }
b75a7d8f 286
374ca955
A
287 if(localized)
288 ((SimpleDateFormat*)fmt)->toLocalizedPattern(res, *status);
289 else
290 ((SimpleDateFormat*)fmt)->toPattern(res);
b75a7d8f 291
374ca955 292 return res.extract(result, resultLength, *status);
b75a7d8f
A
293}
294
295// TBD: should this take an UErrorCode?
296U_CAPI void U_EXPORT2
374ca955 297udat_applyPattern( UDateFormat *format,
b75a7d8f
A
298 UBool localized,
299 const UChar *pattern,
300 int32_t patternLength)
301{
374ca955
A
302 const UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength);
303 UErrorCode status = U_ZERO_ERROR;
b75a7d8f 304
374ca955
A
305 if(localized)
306 ((SimpleDateFormat*)format)->applyLocalizedPattern(pat, status);
307 else
308 ((SimpleDateFormat*)format)->applyPattern(pat);
b75a7d8f
A
309}
310
311U_CAPI int32_t U_EXPORT2
374ca955
A
312udat_getSymbols(const UDateFormat *fmt,
313 UDateFormatSymbolType type,
314 int32_t index,
315 UChar *result,
316 int32_t resultLength,
317 UErrorCode *status)
b75a7d8f 318{
374ca955
A
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;
b75a7d8f 333
374ca955
A
334 case UDAT_MONTHS:
335 res = syms->getMonths(count);
336 if(index < count) {
337 return res[index].extract(result, resultLength, *status);
338 }
339 break;
b75a7d8f 340
374ca955
A
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;
b75a7d8f 347
374ca955
A
348 case UDAT_WEEKDAYS:
349 res = syms->getWeekdays(count);
350 if(index < count) {
351 return res[index].extract(result, resultLength, *status);
352 }
353 break;
b75a7d8f 354
374ca955
A
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;
b75a7d8f 361
374ca955
A
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 }
b75a7d8f 380 }
b75a7d8f 381
374ca955 382 return 0;
b75a7d8f
A
383}
384
385U_CAPI int32_t U_EXPORT2
386udat_countSymbols( const UDateFormat *fmt,
387 UDateFormatSymbolType type)
388{
374ca955
A
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 }
b75a7d8f 422
374ca955 423 return count;
b75a7d8f
A
424}
425
426U_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 */
452class DateFormatSymbolsSingleSetter /* not : public UObject because all methods are static */ {
453public:
374ca955
A
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);
b75a7d8f 516 }
b75a7d8f
A
517};
518
519U_NAMESPACE_END
520
521U_CAPI void U_EXPORT2
522udat_setSymbols( UDateFormat *format,
523 UDateFormatSymbolType type,
524 int32_t index,
525 UChar *value,
526 int32_t valueLength,
527 UErrorCode *status)
528{
374ca955 529 if(U_FAILURE(*status)) return;
b75a7d8f 530
374ca955 531 DateFormatSymbols *syms = (DateFormatSymbols *)((SimpleDateFormat *)format)->getDateFormatSymbols();
b75a7d8f 532
374ca955
A
533 switch(type) {
534 case UDAT_ERAS:
535 DateFormatSymbolsSingleSetter::setEra(syms, index, value, valueLength, *status);
536 break;
b75a7d8f 537
374ca955
A
538 case UDAT_MONTHS:
539 DateFormatSymbolsSingleSetter::setMonth(syms, index, value, valueLength, *status);
540 break;
b75a7d8f 541
374ca955
A
542 case UDAT_SHORT_MONTHS:
543 DateFormatSymbolsSingleSetter::setShortMonth(syms, index, value, valueLength, *status);
544 break;
b75a7d8f 545
374ca955
A
546 case UDAT_WEEKDAYS:
547 DateFormatSymbolsSingleSetter::setWeekday(syms, index, value, valueLength, *status);
548 break;
b75a7d8f 549
374ca955
A
550 case UDAT_SHORT_WEEKDAYS:
551 DateFormatSymbolsSingleSetter::setShortWeekday(syms, index, value, valueLength, *status);
552 break;
b75a7d8f 553
374ca955
A
554 case UDAT_AM_PMS:
555 DateFormatSymbolsSingleSetter::setAmPm(syms, index, value, valueLength, *status);
556 break;
b75a7d8f 557
374ca955
A
558 case UDAT_LOCALIZED_CHARS:
559 DateFormatSymbolsSingleSetter::setLocalPatternChars(syms, value, valueLength, *status);
560 break;
561 }
b75a7d8f
A
562}
563
374ca955
A
564U_CAPI const char* U_EXPORT2
565udat_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}
b75a7d8f 577#endif /* #if !UCONFIG_NO_FORMATTING */