]> git.saurik.com Git - apple/icu.git/blame_incremental - icuSources/i18n/udat.cpp
ICU-6.2.14.tar.gz
[apple/icu.git] / icuSources / i18n / udat.cpp
... / ...
CommitLineData
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
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{
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
89U_CAPI void U_EXPORT2
90udat_close(UDateFormat* format)
91{
92 delete (DateFormat*)format;
93}
94
95U_CAPI UDateFormat* U_EXPORT2
96udat_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
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{
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
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{
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
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{
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
203U_CAPI UBool U_EXPORT2
204udat_isLenient(const UDateFormat* fmt)
205{
206 return ((DateFormat*)fmt)->isLenient();
207}
208
209U_CAPI void U_EXPORT2
210udat_setLenient( UDateFormat* fmt,
211 UBool isLenient)
212{
213 ((DateFormat*)fmt)->setLenient(isLenient);
214}
215
216U_CAPI const UCalendar* U_EXPORT2
217udat_getCalendar(const UDateFormat* fmt)
218{
219 return (const UCalendar*) ((DateFormat*)fmt)->getCalendar();
220}
221
222U_CAPI void U_EXPORT2
223udat_setCalendar(UDateFormat* fmt,
224 const UCalendar* calendarToSet)
225{
226 ((DateFormat*)fmt)->setCalendar(*((Calendar*)calendarToSet));
227}
228
229U_CAPI const UNumberFormat* U_EXPORT2
230udat_getNumberFormat(const UDateFormat* fmt)
231{
232 return (const UNumberFormat*) ((DateFormat*)fmt)->getNumberFormat();
233}
234
235U_CAPI void U_EXPORT2
236udat_setNumberFormat(UDateFormat* fmt,
237 const UNumberFormat* numberFormatToSet)
238{
239 ((DateFormat*)fmt)->setNumberFormat(*((NumberFormat*)numberFormatToSet));
240}
241
242U_CAPI const char* U_EXPORT2
243udat_getAvailable(int32_t index)
244{
245 return uloc_getAvailable(index);
246}
247
248U_CAPI int32_t U_EXPORT2
249udat_countAvailable()
250{
251 return uloc_countAvailable();
252}
253
254U_CAPI UDate U_EXPORT2
255udat_get2DigitYearStart( const UDateFormat *fmt,
256 UErrorCode *status)
257{
258 if(U_FAILURE(*status)) return (UDate)0;
259 return ((SimpleDateFormat*)fmt)->get2DigitYearStart(*status);
260}
261
262U_CAPI void U_EXPORT2
263udat_set2DigitYearStart( UDateFormat *fmt,
264 UDate d,
265 UErrorCode *status)
266{
267 if(U_FAILURE(*status)) return;
268 ((SimpleDateFormat*)fmt)->set2DigitYearStart(d, *status);
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{
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?
296U_CAPI void U_EXPORT2
297udat_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
311U_CAPI int32_t U_EXPORT2
312udat_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
385U_CAPI int32_t U_EXPORT2
386udat_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
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:
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
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{
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
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}
577#endif /* #if !UCONFIG_NO_FORMATTING */