Imported Upstream version 58.1
[platform/upstream/icu.git] / source / i18n / udat.cpp
1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 *******************************************************************************
5 *   Copyright (C) 1996-2015, International Business Machines
6 *   Corporation and others.  All Rights Reserved.
7 *******************************************************************************
8 */
9
10 #include "unicode/utypes.h"
11
12 #if !UCONFIG_NO_FORMATTING
13
14 #include "unicode/udat.h"
15
16 #include "unicode/uloc.h"
17 #include "unicode/datefmt.h"
18 #include "unicode/timezone.h"
19 #include "unicode/smpdtfmt.h"
20 #include "unicode/fieldpos.h"
21 #include "unicode/parsepos.h"
22 #include "unicode/calendar.h"
23 #include "unicode/numfmt.h"
24 #include "unicode/dtfmtsym.h"
25 #include "unicode/ustring.h"
26 #include "unicode/udisplaycontext.h"
27 #include "unicode/ufieldpositer.h"
28 #include "cpputils.h"
29 #include "reldtfmt.h"
30 #include "umutex.h"
31
32 U_NAMESPACE_USE
33
34 /**
35  * Verify that fmt is a SimpleDateFormat. Invalid error if not.
36  * @param fmt the UDateFormat, definitely a DateFormat, maybe something else
37  * @param status error code, will be set to failure if there is a familure or the fmt is NULL.
38  */
39 static void verifyIsSimpleDateFormat(const UDateFormat* fmt, UErrorCode *status) {
40    if(U_SUCCESS(*status) &&
41        dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))==NULL) {
42        *status = U_ILLEGAL_ARGUMENT_ERROR;
43    }
44 }
45
46 // This mirrors the correspondence between the
47 // SimpleDateFormat::fgPatternIndexToDateFormatField and
48 // SimpleDateFormat::fgPatternIndexToCalendarField arrays.
49 static UCalendarDateFields gDateFieldMapping[] = {
50     UCAL_ERA,                  // UDAT_ERA_FIELD = 0
51     UCAL_YEAR,                 // UDAT_YEAR_FIELD = 1
52     UCAL_MONTH,                // UDAT_MONTH_FIELD = 2
53     UCAL_DATE,                 // UDAT_DATE_FIELD = 3
54     UCAL_HOUR_OF_DAY,          // UDAT_HOUR_OF_DAY1_FIELD = 4
55     UCAL_HOUR_OF_DAY,          // UDAT_HOUR_OF_DAY0_FIELD = 5
56     UCAL_MINUTE,               // UDAT_MINUTE_FIELD = 6
57     UCAL_SECOND,               // UDAT_SECOND_FIELD = 7
58     UCAL_MILLISECOND,          // UDAT_FRACTIONAL_SECOND_FIELD = 8
59     UCAL_DAY_OF_WEEK,          // UDAT_DAY_OF_WEEK_FIELD = 9
60     UCAL_DAY_OF_YEAR,          // UDAT_DAY_OF_YEAR_FIELD = 10
61     UCAL_DAY_OF_WEEK_IN_MONTH, // UDAT_DAY_OF_WEEK_IN_MONTH_FIELD = 11
62     UCAL_WEEK_OF_YEAR,         // UDAT_WEEK_OF_YEAR_FIELD = 12
63     UCAL_WEEK_OF_MONTH,        // UDAT_WEEK_OF_MONTH_FIELD = 13
64     UCAL_AM_PM,                // UDAT_AM_PM_FIELD = 14
65     UCAL_HOUR,                 // UDAT_HOUR1_FIELD = 15
66     UCAL_HOUR,                 // UDAT_HOUR0_FIELD = 16
67     UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_FIELD = 17
68     UCAL_YEAR_WOY,             // UDAT_YEAR_WOY_FIELD = 18
69     UCAL_DOW_LOCAL,            // UDAT_DOW_LOCAL_FIELD = 19
70     UCAL_EXTENDED_YEAR,        // UDAT_EXTENDED_YEAR_FIELD = 20
71     UCAL_JULIAN_DAY,           // UDAT_JULIAN_DAY_FIELD = 21
72     UCAL_MILLISECONDS_IN_DAY,  // UDAT_MILLISECONDS_IN_DAY_FIELD = 22
73     UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_RFC_FIELD = 23 (also UCAL_DST_OFFSET)
74     UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_GENERIC_FIELD = 24 (also UCAL_DST_OFFSET)
75     UCAL_DOW_LOCAL,            // UDAT_STANDALONE_DAY_FIELD = 25
76     UCAL_MONTH,                // UDAT_STANDALONE_MONTH_FIELD = 26
77     UCAL_MONTH,                // UDAT_QUARTER_FIELD = 27
78     UCAL_MONTH,                // UDAT_STANDALONE_QUARTER_FIELD = 28
79     UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_SPECIAL_FIELD = 29 (also UCAL_DST_OFFSET)
80     UCAL_YEAR,                 // UDAT_YEAR_NAME_FIELD = 30
81     UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD = 31 (also UCAL_DST_OFFSET)
82     UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_ISO_FIELD = 32 (also UCAL_DST_OFFSET)
83     UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_ISO_LOCAL_FIELD = 33 (also UCAL_DST_OFFSET)
84     UCAL_EXTENDED_YEAR,        // UDAT_RELATED_YEAR_FIELD = 34 (not an exact match)
85     UCAL_FIELD_COUNT,          // UDAT_FIELD_COUNT = 35
86     // UCAL_IS_LEAP_MONTH is not the target of a mapping
87 };
88
89 U_CAPI UCalendarDateFields U_EXPORT2
90 udat_toCalendarDateField(UDateFormatField field) {
91   return gDateFieldMapping[field];
92 }
93
94 /* For now- one opener. */
95 static UDateFormatOpener gOpener = NULL;
96
97 U_INTERNAL void U_EXPORT2
98 udat_registerOpener(UDateFormatOpener opener, UErrorCode *status)
99 {
100   if(U_FAILURE(*status)) return;
101   umtx_lock(NULL);
102   if(gOpener==NULL) {
103     gOpener = opener;
104   } else {
105     *status = U_ILLEGAL_ARGUMENT_ERROR;
106   }
107   umtx_unlock(NULL);
108 }
109
110 U_INTERNAL UDateFormatOpener U_EXPORT2
111 udat_unregisterOpener(UDateFormatOpener opener, UErrorCode *status)
112 {
113   if(U_FAILURE(*status)) return NULL;
114   UDateFormatOpener oldOpener = NULL;
115   umtx_lock(NULL);
116   if(gOpener==NULL || gOpener!=opener) {
117     *status = U_ILLEGAL_ARGUMENT_ERROR;
118   } else {
119     oldOpener=gOpener;
120     gOpener=NULL;
121   }
122   umtx_unlock(NULL);
123   return oldOpener;
124 }
125
126
127
128 U_CAPI UDateFormat* U_EXPORT2
129 udat_open(UDateFormatStyle  timeStyle,
130           UDateFormatStyle  dateStyle,
131           const char        *locale,
132           const UChar       *tzID,
133           int32_t           tzIDLength,
134           const UChar       *pattern,
135           int32_t           patternLength,
136           UErrorCode        *status)
137 {
138     DateFormat *fmt;
139     if(U_FAILURE(*status)) {
140         return 0;
141     }
142     if(gOpener!=NULL) { // if it's registered
143       fmt = (DateFormat*) (*gOpener)(timeStyle,dateStyle,locale,tzID,tzIDLength,pattern,patternLength,status);
144       if(fmt!=NULL) {
145         return (UDateFormat*)fmt;
146       } // else fall through.
147     }
148     if(timeStyle != UDAT_PATTERN) {
149         if(locale == 0) {
150             fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle,
151                 (DateFormat::EStyle)timeStyle);
152         }
153         else {
154             fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle,
155                 (DateFormat::EStyle)timeStyle,
156                 Locale(locale));
157         }
158     }
159     else {
160         UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength);
161
162         if(locale == 0) {
163             fmt = new SimpleDateFormat(pat, *status);
164         }
165         else {
166             fmt = new SimpleDateFormat(pat, Locale(locale), *status);
167         }
168     }
169
170     if(fmt == 0) {
171         *status = U_MEMORY_ALLOCATION_ERROR;
172         return 0;
173     }
174
175     if(tzID != 0) {
176         TimeZone *zone = TimeZone::createTimeZone(UnicodeString((UBool)(tzIDLength == -1), tzID, tzIDLength));
177         if(zone == 0) {
178             *status = U_MEMORY_ALLOCATION_ERROR;
179             delete fmt;
180             return 0;
181         }
182         fmt->adoptTimeZone(zone);
183     }
184
185     return (UDateFormat*)fmt;
186 }
187
188
189 U_CAPI void U_EXPORT2
190 udat_close(UDateFormat* format)
191 {
192     delete (DateFormat*)format;
193 }
194
195 U_CAPI UDateFormat* U_EXPORT2
196 udat_clone(const UDateFormat *fmt,
197        UErrorCode *status)
198 {
199     if(U_FAILURE(*status)) return 0;
200
201     Format *res = ((DateFormat*)fmt)->clone();
202
203     if(res == 0) {
204         *status = U_MEMORY_ALLOCATION_ERROR;
205         return 0;
206     }
207
208     return (UDateFormat*) res;
209 }
210
211 U_CAPI int32_t U_EXPORT2
212 udat_format(    const    UDateFormat*    format,
213         UDate           dateToFormat,
214         UChar*          result,
215         int32_t         resultLength,
216         UFieldPosition* position,
217         UErrorCode*     status)
218 {
219     if(U_FAILURE(*status)) {
220         return -1;
221     }
222     if (result == NULL ? resultLength != 0 : resultLength < 0) {
223         *status = U_ILLEGAL_ARGUMENT_ERROR;
224         return -1;
225     }
226
227     UnicodeString res;
228     if (result != NULL) {
229         // NULL destination for pure preflighting: empty dummy string
230         // otherwise, alias the destination buffer
231         res.setTo(result, 0, resultLength);
232     }
233
234     FieldPosition fp;
235
236     if(position != 0)
237         fp.setField(position->field);
238
239     ((DateFormat*)format)->format(dateToFormat, res, fp);
240
241     if(position != 0) {
242         position->beginIndex = fp.getBeginIndex();
243         position->endIndex = fp.getEndIndex();
244     }
245
246     return res.extract(result, resultLength, *status);
247 }
248
249 U_CAPI int32_t U_EXPORT2
250 udat_formatCalendar(const UDateFormat*  format,
251         UCalendar*      calendar,
252         UChar*          result,
253         int32_t         resultLength,
254         UFieldPosition* position,
255         UErrorCode*     status)
256 {
257     if(U_FAILURE(*status)) {
258         return -1;
259     }
260     if (result == NULL ? resultLength != 0 : resultLength < 0) {
261         *status = U_ILLEGAL_ARGUMENT_ERROR;
262         return -1;
263     }
264
265     UnicodeString res;
266     if (result != NULL) {
267         // NULL destination for pure preflighting: empty dummy string
268         // otherwise, alias the destination buffer
269         res.setTo(result, 0, resultLength);
270     }
271
272     FieldPosition fp;
273
274     if(position != 0)
275         fp.setField(position->field);
276
277     ((DateFormat*)format)->format(*(Calendar*)calendar, res, fp);
278
279     if(position != 0) {
280         position->beginIndex = fp.getBeginIndex();
281         position->endIndex = fp.getEndIndex();
282     }
283
284     return res.extract(result, resultLength, *status);
285 }
286
287 U_CAPI int32_t U_EXPORT2
288 udat_formatForFields(    const    UDateFormat*    format,
289         UDate           dateToFormat,
290         UChar*          result,
291         int32_t         resultLength,
292         UFieldPositionIterator* fpositer,
293         UErrorCode*     status)
294 {
295     if(U_FAILURE(*status)) {
296         return -1;
297     }
298     if (result == NULL ? resultLength != 0 : resultLength < 0) {
299         *status = U_ILLEGAL_ARGUMENT_ERROR;
300         return -1;
301     }
302
303     UnicodeString res;
304     if (result != NULL) {
305         // NULL destination for pure preflighting: empty dummy string
306         // otherwise, alias the destination buffer
307         res.setTo(result, 0, resultLength);
308     }
309
310     ((DateFormat*)format)->format(dateToFormat, res, (FieldPositionIterator*)fpositer, *status);
311
312     return res.extract(result, resultLength, *status);
313 }
314
315 U_CAPI int32_t U_EXPORT2
316 udat_formatCalendarForFields(const UDateFormat*  format,
317         UCalendar*      calendar,
318         UChar*          result,
319         int32_t         resultLength,
320         UFieldPositionIterator* fpositer,
321         UErrorCode*     status)
322 {
323     if(U_FAILURE(*status)) {
324         return -1;
325     }
326     if (result == NULL ? resultLength != 0 : resultLength < 0) {
327         *status = U_ILLEGAL_ARGUMENT_ERROR;
328         return -1;
329     }
330
331     UnicodeString res;
332     if (result != NULL) {
333         // NULL destination for pure preflighting: empty dummy string
334         // otherwise, alias the destination buffer
335         res.setTo(result, 0, resultLength);
336     }
337
338     ((DateFormat*)format)->format(*(Calendar*)calendar, res, (FieldPositionIterator*)fpositer, *status);
339
340     return res.extract(result, resultLength, *status);
341 }
342
343 U_CAPI UDate U_EXPORT2
344 udat_parse(    const    UDateFormat*        format,
345         const    UChar*          text,
346         int32_t         textLength,
347         int32_t         *parsePos,
348         UErrorCode      *status)
349 {
350     if(U_FAILURE(*status)) return (UDate)0;
351
352     const UnicodeString src((UBool)(textLength == -1), text, textLength);
353     ParsePosition pp;
354     int32_t stackParsePos = 0;
355     UDate res;
356
357     if(parsePos == NULL) {
358         parsePos = &stackParsePos;
359     }
360
361     pp.setIndex(*parsePos);
362
363     res = ((DateFormat*)format)->parse(src, pp);
364
365     if(pp.getErrorIndex() == -1)
366         *parsePos = pp.getIndex();
367     else {
368         *parsePos = pp.getErrorIndex();
369         *status = U_PARSE_ERROR;
370     }
371
372     return res;
373 }
374
375 U_CAPI void U_EXPORT2
376 udat_parseCalendar(const    UDateFormat*    format,
377                             UCalendar*      calendar,
378                    const    UChar*          text,
379                             int32_t         textLength,
380                             int32_t         *parsePos,
381                             UErrorCode      *status)
382 {
383     if(U_FAILURE(*status)) return;
384
385     const UnicodeString src((UBool)(textLength == -1), text, textLength);
386     ParsePosition pp;
387     int32_t stackParsePos = 0;
388
389     if(parsePos == NULL) {
390         parsePos = &stackParsePos;
391     }
392
393     pp.setIndex(*parsePos);
394
395     ((DateFormat*)format)->parse(src, *(Calendar*)calendar, pp);
396
397     if(pp.getErrorIndex() == -1)
398         *parsePos = pp.getIndex();
399     else {
400         *parsePos = pp.getErrorIndex();
401         *status = U_PARSE_ERROR;
402     }
403 }
404
405 U_CAPI UBool U_EXPORT2
406 udat_isLenient(const UDateFormat* fmt)
407 {
408     return ((DateFormat*)fmt)->isLenient();
409 }
410
411 U_CAPI void U_EXPORT2
412 udat_setLenient(    UDateFormat*    fmt,
413             UBool          isLenient)
414 {
415     ((DateFormat*)fmt)->setLenient(isLenient);
416 }
417
418 U_DRAFT UBool U_EXPORT2
419 udat_getBooleanAttribute(const UDateFormat* fmt, 
420                          UDateFormatBooleanAttribute attr, 
421                          UErrorCode* status)
422 {
423     if(U_FAILURE(*status)) return FALSE;
424     return ((DateFormat*)fmt)->getBooleanAttribute(attr, *status);
425     //return FALSE;
426 }
427
428 U_DRAFT void U_EXPORT2
429 udat_setBooleanAttribute(UDateFormat *fmt, 
430                          UDateFormatBooleanAttribute attr, 
431                          UBool newValue, 
432                          UErrorCode* status)
433 {
434     if(U_FAILURE(*status)) return;
435     ((DateFormat*)fmt)->setBooleanAttribute(attr, newValue, *status);
436 }
437
438 U_CAPI const UCalendar* U_EXPORT2
439 udat_getCalendar(const UDateFormat* fmt)
440 {
441     return (const UCalendar*) ((DateFormat*)fmt)->getCalendar();
442 }
443
444 U_CAPI void U_EXPORT2
445 udat_setCalendar(UDateFormat*    fmt,
446                  const   UCalendar*      calendarToSet)
447 {
448     ((DateFormat*)fmt)->setCalendar(*((Calendar*)calendarToSet));
449 }
450
451 U_DRAFT const UNumberFormat* U_EXPORT2 
452 udat_getNumberFormatForField(const UDateFormat* fmt, UChar field)
453 {
454     UErrorCode status = U_ZERO_ERROR;
455     verifyIsSimpleDateFormat(fmt, &status);
456     if (U_FAILURE(status)) return (const UNumberFormat*) ((DateFormat*)fmt)->getNumberFormat();
457     return (const UNumberFormat*) ((SimpleDateFormat*)fmt)->getNumberFormatForField(field);
458 }
459
460 U_CAPI const UNumberFormat* U_EXPORT2
461 udat_getNumberFormat(const UDateFormat* fmt)
462 {
463     return (const UNumberFormat*) ((DateFormat*)fmt)->getNumberFormat();
464 }
465
466 U_DRAFT void U_EXPORT2 
467 udat_adoptNumberFormatForFields(           UDateFormat*    fmt,
468                                     const  UChar*          fields,
469                                            UNumberFormat*  numberFormatToSet,
470                                            UErrorCode*     status)
471 {
472     verifyIsSimpleDateFormat(fmt, status);
473     if (U_FAILURE(*status)) return;
474     
475     if (fields!=NULL) {
476         UnicodeString overrideFields(fields);
477         ((SimpleDateFormat*)fmt)->adoptNumberFormat(overrideFields, (NumberFormat*)numberFormatToSet, *status);
478     }
479 }
480
481 U_CAPI void U_EXPORT2
482 udat_setNumberFormat(UDateFormat*    fmt,
483                      const   UNumberFormat*  numberFormatToSet)
484 {
485     ((DateFormat*)fmt)->setNumberFormat(*((NumberFormat*)numberFormatToSet));
486 }
487
488 U_DRAFT void U_EXPORT2
489 udat_adoptNumberFormat(      UDateFormat*    fmt,
490                              UNumberFormat*  numberFormatToAdopt)
491 {
492     ((DateFormat*)fmt)->adoptNumberFormat((NumberFormat*)numberFormatToAdopt);
493 }
494
495 U_CAPI const char* U_EXPORT2
496 udat_getAvailable(int32_t index)
497 {
498     return uloc_getAvailable(index);
499 }
500
501 U_CAPI int32_t U_EXPORT2
502 udat_countAvailable()
503 {
504     return uloc_countAvailable();
505 }
506
507 U_CAPI UDate U_EXPORT2
508 udat_get2DigitYearStart(    const   UDateFormat     *fmt,
509                         UErrorCode      *status)
510 {
511     verifyIsSimpleDateFormat(fmt, status);
512     if(U_FAILURE(*status)) return (UDate)0;
513     return ((SimpleDateFormat*)fmt)->get2DigitYearStart(*status);
514 }
515
516 U_CAPI void U_EXPORT2
517 udat_set2DigitYearStart(    UDateFormat     *fmt,
518                         UDate           d,
519                         UErrorCode      *status)
520 {
521     verifyIsSimpleDateFormat(fmt, status);
522     if(U_FAILURE(*status)) return;
523     ((SimpleDateFormat*)fmt)->set2DigitYearStart(d, *status);
524 }
525
526 U_CAPI int32_t U_EXPORT2
527 udat_toPattern(    const   UDateFormat     *fmt,
528         UBool          localized,
529         UChar           *result,
530         int32_t         resultLength,
531         UErrorCode      *status)
532 {
533     if(U_FAILURE(*status)) {
534         return -1;
535     }
536     if (result == NULL ? resultLength != 0 : resultLength < 0) {
537         *status = U_ILLEGAL_ARGUMENT_ERROR;
538         return -1;
539     }
540
541     UnicodeString res;
542     if (result != NULL) {
543         // NULL destination for pure preflighting: empty dummy string
544         // otherwise, alias the destination buffer
545         res.setTo(result, 0, resultLength);
546     }
547
548     const DateFormat *df=reinterpret_cast<const DateFormat *>(fmt);
549     const SimpleDateFormat *sdtfmt=dynamic_cast<const SimpleDateFormat *>(df);
550     const RelativeDateFormat *reldtfmt;
551     if (sdtfmt!=NULL) {
552         if(localized)
553             sdtfmt->toLocalizedPattern(res, *status);
554         else
555             sdtfmt->toPattern(res);
556     } else if (!localized && (reldtfmt=dynamic_cast<const RelativeDateFormat *>(df))!=NULL) {
557         reldtfmt->toPattern(res, *status);
558     } else {
559         *status = U_ILLEGAL_ARGUMENT_ERROR;
560         return -1;
561     }
562
563     return res.extract(result, resultLength, *status);
564 }
565
566 // TODO: should this take an UErrorCode?
567 // A: Yes. Of course.
568 U_CAPI void U_EXPORT2
569 udat_applyPattern(  UDateFormat     *format,
570                     UBool          localized,
571                     const   UChar           *pattern,
572                     int32_t         patternLength)
573 {
574     const UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength);
575     UErrorCode status = U_ZERO_ERROR;
576
577     verifyIsSimpleDateFormat(format, &status);
578     if(U_FAILURE(status)) {
579         return;
580     }
581     
582     if(localized)
583         ((SimpleDateFormat*)format)->applyLocalizedPattern(pat, status);
584     else
585         ((SimpleDateFormat*)format)->applyPattern(pat);
586 }
587
588 U_CAPI int32_t U_EXPORT2
589 udat_getSymbols(const   UDateFormat     *fmt,
590                 UDateFormatSymbolType   type,
591                 int32_t                 index,
592                 UChar                   *result,
593                 int32_t                 resultLength,
594                 UErrorCode              *status)
595 {
596     const DateFormatSymbols *syms;
597     const SimpleDateFormat* sdtfmt;
598     const RelativeDateFormat* rdtfmt;
599     if ((sdtfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
600         syms = sdtfmt->getDateFormatSymbols();
601     } else if ((rdtfmt = dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
602         syms = rdtfmt->getDateFormatSymbols();
603     } else {
604         return -1;
605     }
606     int32_t count;
607     const UnicodeString *res = NULL;
608
609     switch(type) {
610     case UDAT_ERAS:
611         res = syms->getEras(count);
612         break;
613
614     case UDAT_ERA_NAMES:
615         res = syms->getEraNames(count);
616         break;
617
618     case UDAT_MONTHS:
619         res = syms->getMonths(count);
620         break;
621
622     case UDAT_SHORT_MONTHS:
623         res = syms->getShortMonths(count);
624         break;
625
626     case UDAT_WEEKDAYS:
627         res = syms->getWeekdays(count);
628         break;
629
630     case UDAT_SHORT_WEEKDAYS:
631         res = syms->getShortWeekdays(count);
632         break;
633
634     case UDAT_AM_PMS:
635         res = syms->getAmPmStrings(count);
636         break;
637
638     case UDAT_LOCALIZED_CHARS:
639         {
640             UnicodeString res1;
641             if(!(result==NULL && resultLength==0)) {
642                 // NULL destination for pure preflighting: empty dummy string
643                 // otherwise, alias the destination buffer
644                 res1.setTo(result, 0, resultLength);
645             }
646             syms->getLocalPatternChars(res1);
647             return res1.extract(result, resultLength, *status);
648         }
649
650     case UDAT_NARROW_MONTHS:
651         res = syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
652         break;
653
654     case UDAT_SHORTER_WEEKDAYS:
655         res = syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::SHORT);
656         break;
657
658     case UDAT_NARROW_WEEKDAYS:
659         res = syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
660         break;
661
662     case UDAT_STANDALONE_MONTHS:
663         res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
664         break;
665
666     case UDAT_STANDALONE_SHORT_MONTHS:
667         res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
668         break;
669
670     case UDAT_STANDALONE_NARROW_MONTHS:
671         res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
672         break;
673
674     case UDAT_STANDALONE_WEEKDAYS:
675         res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
676         break;
677
678     case UDAT_STANDALONE_SHORT_WEEKDAYS:
679         res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
680         break;
681
682     case UDAT_STANDALONE_SHORTER_WEEKDAYS:
683         res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::SHORT);
684         break;
685
686     case UDAT_STANDALONE_NARROW_WEEKDAYS:
687         res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
688         break;
689
690     case UDAT_QUARTERS:
691         res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
692         break;
693
694     case UDAT_SHORT_QUARTERS:
695         res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
696         break;
697
698     case UDAT_STANDALONE_QUARTERS:
699         res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
700         break;
701
702     case UDAT_STANDALONE_SHORT_QUARTERS:
703         res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
704         break;
705
706     case UDAT_CYCLIC_YEARS_WIDE:
707         res = syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
708         break;
709
710     case UDAT_CYCLIC_YEARS_ABBREVIATED:
711         res = syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
712         break;
713
714     case UDAT_CYCLIC_YEARS_NARROW:
715         res = syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
716         break;
717
718     case UDAT_ZODIAC_NAMES_WIDE:
719         res = syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
720         break;
721
722     case UDAT_ZODIAC_NAMES_ABBREVIATED:
723         res = syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
724         break;
725
726     case UDAT_ZODIAC_NAMES_NARROW:
727         res = syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
728         break;
729
730     }
731
732     if(index < count) {
733         return res[index].extract(result, resultLength, *status);
734     }
735     return 0;
736 }
737
738 // TODO: also needs an errorCode.
739 U_CAPI int32_t U_EXPORT2
740 udat_countSymbols(    const    UDateFormat                *fmt,
741             UDateFormatSymbolType    type)
742 {
743     const DateFormatSymbols *syms;
744     const SimpleDateFormat* sdtfmt;
745     const RelativeDateFormat* rdtfmt;
746     if ((sdtfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
747         syms = sdtfmt->getDateFormatSymbols();
748     } else if ((rdtfmt = dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
749         syms = rdtfmt->getDateFormatSymbols();
750     } else {
751         return 0;
752     }
753     int32_t count = 0;
754
755     switch(type) {
756     case UDAT_ERAS:
757         syms->getEras(count);
758         break;
759
760     case UDAT_MONTHS:
761         syms->getMonths(count);
762         break;
763
764     case UDAT_SHORT_MONTHS:
765         syms->getShortMonths(count);
766         break;
767
768     case UDAT_WEEKDAYS:
769         syms->getWeekdays(count);
770         break;
771
772     case UDAT_SHORT_WEEKDAYS:
773         syms->getShortWeekdays(count);
774         break;
775
776     case UDAT_AM_PMS:
777         syms->getAmPmStrings(count);
778         break;
779
780     case UDAT_LOCALIZED_CHARS:
781         count = 1;
782         break;
783
784     case UDAT_ERA_NAMES:
785         syms->getEraNames(count);
786         break;
787
788     case UDAT_NARROW_MONTHS:
789         syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
790         break;
791
792     case UDAT_SHORTER_WEEKDAYS:
793         syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::SHORT);
794         break;
795
796     case UDAT_NARROW_WEEKDAYS:
797         syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
798         break;
799
800     case UDAT_STANDALONE_MONTHS:
801         syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
802         break;
803
804     case UDAT_STANDALONE_SHORT_MONTHS:
805         syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
806         break;
807
808     case UDAT_STANDALONE_NARROW_MONTHS:
809         syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
810         break;
811
812     case UDAT_STANDALONE_WEEKDAYS:
813         syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
814         break;
815
816     case UDAT_STANDALONE_SHORT_WEEKDAYS:
817         syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
818         break;
819
820     case UDAT_STANDALONE_SHORTER_WEEKDAYS:
821         syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::SHORT);
822         break;
823
824     case UDAT_STANDALONE_NARROW_WEEKDAYS:
825         syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
826         break;
827
828     case UDAT_QUARTERS:
829         syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
830         break;
831
832     case UDAT_SHORT_QUARTERS:
833         syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
834         break;
835
836     case UDAT_STANDALONE_QUARTERS:
837         syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
838         break;
839
840     case UDAT_STANDALONE_SHORT_QUARTERS:
841         syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
842         break;
843
844     case UDAT_CYCLIC_YEARS_WIDE:
845         syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
846         break;
847
848     case UDAT_CYCLIC_YEARS_ABBREVIATED:
849         syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
850         break;
851
852     case UDAT_CYCLIC_YEARS_NARROW:
853         syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
854         break;
855
856     case UDAT_ZODIAC_NAMES_WIDE:
857         syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
858         break;
859
860     case UDAT_ZODIAC_NAMES_ABBREVIATED:
861         syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
862         break;
863
864     case UDAT_ZODIAC_NAMES_NARROW:
865         syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
866         break;
867
868     }
869
870     return count;
871 }
872
873 U_NAMESPACE_BEGIN
874
875 /*
876  * This DateFormatSymbolsSingleSetter class is a friend of DateFormatSymbols
877  * solely for the purpose of avoiding to clone the array of strings
878  * just to modify one of them and then setting all of them back.
879  * For example, the old code looked like this:
880  *  case UDAT_MONTHS:
881  *    res = syms->getMonths(count);
882  *    array = new UnicodeString[count];
883  *    if(array == 0) {
884  *      *status = U_MEMORY_ALLOCATION_ERROR;
885  *      return;
886  *    }
887  *    uprv_arrayCopy(res, array, count);
888  *    if(index < count)
889  *      array[index] = val;
890  *    syms->setMonths(array, count);
891  *    break;
892  *
893  * Even worse, the old code actually cloned the entire DateFormatSymbols object,
894  * cloned one value array, changed one value, and then made the SimpleDateFormat
895  * replace its DateFormatSymbols object with the new one.
896  *
897  * markus 2002-oct-14
898  */
899 class DateFormatSymbolsSingleSetter /* not : public UObject because all methods are static */ {
900 public:
901     static void
902         setSymbol(UnicodeString *array, int32_t count, int32_t index,
903         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
904     {
905         if(array!=NULL) {
906             if(index>=count) {
907                 errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
908             } else if(value==NULL) {
909                 errorCode=U_ILLEGAL_ARGUMENT_ERROR;
910             } else {
911                 array[index].setTo(value, valueLength);
912             }
913         }
914     }
915
916     static void
917         setEra(DateFormatSymbols *syms, int32_t index,
918         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
919     {
920         setSymbol(syms->fEras, syms->fErasCount, index, value, valueLength, errorCode);
921     }
922
923     static void
924         setEraName(DateFormatSymbols *syms, int32_t index,
925         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
926     {
927         setSymbol(syms->fEraNames, syms->fEraNamesCount, index, value, valueLength, errorCode);
928     }
929
930     static void
931         setMonth(DateFormatSymbols *syms, int32_t index,
932         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
933     {
934         setSymbol(syms->fMonths, syms->fMonthsCount, index, value, valueLength, errorCode);
935     }
936
937     static void
938         setShortMonth(DateFormatSymbols *syms, int32_t index,
939         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
940     {
941         setSymbol(syms->fShortMonths, syms->fShortMonthsCount, index, value, valueLength, errorCode);
942     }
943
944     static void
945         setNarrowMonth(DateFormatSymbols *syms, int32_t index,
946         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
947     {
948         setSymbol(syms->fNarrowMonths, syms->fNarrowMonthsCount, index, value, valueLength, errorCode);
949     }
950
951     static void
952         setStandaloneMonth(DateFormatSymbols *syms, int32_t index,
953         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
954     {
955         setSymbol(syms->fStandaloneMonths, syms->fStandaloneMonthsCount, index, value, valueLength, errorCode);
956     }
957
958     static void
959         setStandaloneShortMonth(DateFormatSymbols *syms, int32_t index,
960         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
961     {
962         setSymbol(syms->fStandaloneShortMonths, syms->fStandaloneShortMonthsCount, index, value, valueLength, errorCode);
963     }
964
965     static void
966         setStandaloneNarrowMonth(DateFormatSymbols *syms, int32_t index,
967         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
968     {
969         setSymbol(syms->fStandaloneNarrowMonths, syms->fStandaloneNarrowMonthsCount, index, value, valueLength, errorCode);
970     }
971
972     static void
973         setWeekday(DateFormatSymbols *syms, int32_t index,
974         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
975     {
976         setSymbol(syms->fWeekdays, syms->fWeekdaysCount, index, value, valueLength, errorCode);
977     }
978
979     static void
980         setShortWeekday(DateFormatSymbols *syms, int32_t index,
981         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
982     {
983         setSymbol(syms->fShortWeekdays, syms->fShortWeekdaysCount, index, value, valueLength, errorCode);
984     }
985
986     static void
987         setShorterWeekday(DateFormatSymbols *syms, int32_t index,
988         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
989     {
990         setSymbol(syms->fShorterWeekdays, syms->fShorterWeekdaysCount, index, value, valueLength, errorCode);
991     }
992
993     static void
994         setNarrowWeekday(DateFormatSymbols *syms, int32_t index,
995         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
996     {
997         setSymbol(syms->fNarrowWeekdays, syms->fNarrowWeekdaysCount, index, value, valueLength, errorCode);
998     }
999
1000     static void
1001         setStandaloneWeekday(DateFormatSymbols *syms, int32_t index,
1002         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
1003     {
1004         setSymbol(syms->fStandaloneWeekdays, syms->fStandaloneWeekdaysCount, index, value, valueLength, errorCode);
1005     }
1006
1007     static void
1008         setStandaloneShortWeekday(DateFormatSymbols *syms, int32_t index,
1009         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
1010     {
1011         setSymbol(syms->fStandaloneShortWeekdays, syms->fStandaloneShortWeekdaysCount, index, value, valueLength, errorCode);
1012     }
1013
1014     static void
1015         setStandaloneShorterWeekday(DateFormatSymbols *syms, int32_t index,
1016         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
1017     {
1018         setSymbol(syms->fStandaloneShorterWeekdays, syms->fStandaloneShorterWeekdaysCount, index, value, valueLength, errorCode);
1019     }
1020
1021     static void
1022         setStandaloneNarrowWeekday(DateFormatSymbols *syms, int32_t index,
1023         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
1024     {
1025         setSymbol(syms->fStandaloneNarrowWeekdays, syms->fStandaloneNarrowWeekdaysCount, index, value, valueLength, errorCode);
1026     }
1027
1028     static void
1029         setQuarter(DateFormatSymbols *syms, int32_t index,
1030         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
1031     {
1032         setSymbol(syms->fQuarters, syms->fQuartersCount, index, value, valueLength, errorCode);
1033     }
1034
1035     static void
1036         setShortQuarter(DateFormatSymbols *syms, int32_t index,
1037         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
1038     {
1039         setSymbol(syms->fShortQuarters, syms->fShortQuartersCount, index, value, valueLength, errorCode);
1040     }
1041
1042     static void
1043         setStandaloneQuarter(DateFormatSymbols *syms, int32_t index,
1044         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
1045     {
1046         setSymbol(syms->fStandaloneQuarters, syms->fStandaloneQuartersCount, index, value, valueLength, errorCode);
1047     }
1048
1049     static void
1050         setStandaloneShortQuarter(DateFormatSymbols *syms, int32_t index,
1051         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
1052     {
1053         setSymbol(syms->fStandaloneShortQuarters, syms->fStandaloneShortQuartersCount, index, value, valueLength, errorCode);
1054     }
1055
1056     static void
1057         setShortYearNames(DateFormatSymbols *syms, int32_t index,
1058         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
1059     {
1060         setSymbol(syms->fShortYearNames, syms->fShortYearNamesCount, index, value, valueLength, errorCode);
1061     }
1062
1063     static void
1064         setShortZodiacNames(DateFormatSymbols *syms, int32_t index,
1065         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
1066     {
1067         setSymbol(syms->fShortZodiacNames, syms->fShortZodiacNamesCount, index, value, valueLength, errorCode);
1068     }
1069
1070     static void
1071         setAmPm(DateFormatSymbols *syms, int32_t index,
1072         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
1073     {
1074         setSymbol(syms->fAmPms, syms->fAmPmsCount, index, value, valueLength, errorCode);
1075     }
1076
1077     static void
1078         setLocalPatternChars(DateFormatSymbols *syms,
1079         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
1080     {
1081         setSymbol(&syms->fLocalPatternChars, 1, 0, value, valueLength, errorCode);
1082     }
1083 };
1084
1085 U_NAMESPACE_END
1086
1087 U_CAPI void U_EXPORT2
1088 udat_setSymbols(    UDateFormat             *format,
1089             UDateFormatSymbolType   type,
1090             int32_t                 index,
1091             UChar                   *value,
1092             int32_t                 valueLength,
1093             UErrorCode              *status)
1094 {
1095     verifyIsSimpleDateFormat(format, status);
1096     if(U_FAILURE(*status)) return;
1097
1098     DateFormatSymbols *syms = (DateFormatSymbols *)((SimpleDateFormat *)format)->getDateFormatSymbols();
1099
1100     switch(type) {
1101     case UDAT_ERAS:
1102         DateFormatSymbolsSingleSetter::setEra(syms, index, value, valueLength, *status);
1103         break;
1104
1105     case UDAT_ERA_NAMES:
1106         DateFormatSymbolsSingleSetter::setEraName(syms, index, value, valueLength, *status);
1107         break;
1108
1109     case UDAT_MONTHS:
1110         DateFormatSymbolsSingleSetter::setMonth(syms, index, value, valueLength, *status);
1111         break;
1112
1113     case UDAT_SHORT_MONTHS:
1114         DateFormatSymbolsSingleSetter::setShortMonth(syms, index, value, valueLength, *status);
1115         break;
1116
1117     case UDAT_NARROW_MONTHS:
1118         DateFormatSymbolsSingleSetter::setNarrowMonth(syms, index, value, valueLength, *status);
1119         break;
1120
1121     case UDAT_STANDALONE_MONTHS:
1122         DateFormatSymbolsSingleSetter::setStandaloneMonth(syms, index, value, valueLength, *status);
1123         break;
1124
1125     case UDAT_STANDALONE_SHORT_MONTHS:
1126         DateFormatSymbolsSingleSetter::setStandaloneShortMonth(syms, index, value, valueLength, *status);
1127         break;
1128
1129     case UDAT_STANDALONE_NARROW_MONTHS:
1130         DateFormatSymbolsSingleSetter::setStandaloneNarrowMonth(syms, index, value, valueLength, *status);
1131         break;
1132
1133     case UDAT_WEEKDAYS:
1134         DateFormatSymbolsSingleSetter::setWeekday(syms, index, value, valueLength, *status);
1135         break;
1136
1137     case UDAT_SHORT_WEEKDAYS:
1138         DateFormatSymbolsSingleSetter::setShortWeekday(syms, index, value, valueLength, *status);
1139         break;
1140
1141     case UDAT_SHORTER_WEEKDAYS:
1142         DateFormatSymbolsSingleSetter::setShorterWeekday(syms, index, value, valueLength, *status);
1143         break;
1144
1145     case UDAT_NARROW_WEEKDAYS:
1146         DateFormatSymbolsSingleSetter::setNarrowWeekday(syms, index, value, valueLength, *status);
1147         break;
1148
1149     case UDAT_STANDALONE_WEEKDAYS:
1150         DateFormatSymbolsSingleSetter::setStandaloneWeekday(syms, index, value, valueLength, *status);
1151         break;
1152
1153     case UDAT_STANDALONE_SHORT_WEEKDAYS:
1154         DateFormatSymbolsSingleSetter::setStandaloneShortWeekday(syms, index, value, valueLength, *status);
1155         break;
1156
1157     case UDAT_STANDALONE_SHORTER_WEEKDAYS:
1158         DateFormatSymbolsSingleSetter::setStandaloneShorterWeekday(syms, index, value, valueLength, *status);
1159         break;
1160
1161     case UDAT_STANDALONE_NARROW_WEEKDAYS:
1162         DateFormatSymbolsSingleSetter::setStandaloneNarrowWeekday(syms, index, value, valueLength, *status);
1163         break;
1164
1165     case UDAT_QUARTERS:
1166         DateFormatSymbolsSingleSetter::setQuarter(syms, index, value, valueLength, *status);
1167         break;
1168
1169     case UDAT_SHORT_QUARTERS:
1170         DateFormatSymbolsSingleSetter::setShortQuarter(syms, index, value, valueLength, *status);
1171         break;
1172
1173     case UDAT_STANDALONE_QUARTERS:
1174         DateFormatSymbolsSingleSetter::setStandaloneQuarter(syms, index, value, valueLength, *status);
1175         break;
1176
1177     case UDAT_STANDALONE_SHORT_QUARTERS:
1178         DateFormatSymbolsSingleSetter::setStandaloneShortQuarter(syms, index, value, valueLength, *status);
1179         break;
1180
1181     case UDAT_CYCLIC_YEARS_ABBREVIATED:
1182         DateFormatSymbolsSingleSetter::setShortYearNames(syms, index, value, valueLength, *status);
1183         break;
1184
1185     case UDAT_ZODIAC_NAMES_ABBREVIATED:
1186         DateFormatSymbolsSingleSetter::setShortZodiacNames(syms, index, value, valueLength, *status);
1187         break;
1188
1189     case UDAT_AM_PMS:
1190         DateFormatSymbolsSingleSetter::setAmPm(syms, index, value, valueLength, *status);
1191         break;
1192
1193     case UDAT_LOCALIZED_CHARS:
1194         DateFormatSymbolsSingleSetter::setLocalPatternChars(syms, value, valueLength, *status);
1195         break;
1196
1197     default:
1198         *status = U_UNSUPPORTED_ERROR;
1199         break;
1200         
1201     }
1202 }
1203
1204 U_CAPI const char* U_EXPORT2
1205 udat_getLocaleByType(const UDateFormat *fmt,
1206                      ULocDataLocaleType type,
1207                      UErrorCode* status)
1208 {
1209     if (fmt == NULL) {
1210         if (U_SUCCESS(*status)) {
1211             *status = U_ILLEGAL_ARGUMENT_ERROR;
1212         }
1213         return NULL;
1214     }
1215     return ((Format*)fmt)->getLocaleID(type, *status);
1216 }
1217
1218 U_CAPI void U_EXPORT2
1219 udat_setContext(UDateFormat* fmt, UDisplayContext value, UErrorCode* status)
1220 {
1221     if (U_FAILURE(*status)) {
1222         return;
1223     }
1224     ((DateFormat*)fmt)->setContext(value, *status);
1225     return;
1226 }
1227
1228 U_CAPI UDisplayContext U_EXPORT2
1229 udat_getContext(const UDateFormat* fmt, UDisplayContextType type, UErrorCode* status)
1230 {
1231     if (U_FAILURE(*status)) {
1232         return (UDisplayContext)0;
1233     }
1234     return ((const DateFormat*)fmt)->getContext(type, *status);
1235 }
1236
1237
1238 /**
1239  * Verify that fmt is a RelativeDateFormat. Invalid error if not.
1240  * @param fmt the UDateFormat, definitely a DateFormat, maybe something else
1241  * @param status error code, will be set to failure if there is a familure or the fmt is NULL.
1242  */
1243 static void verifyIsRelativeDateFormat(const UDateFormat* fmt, UErrorCode *status) {
1244    if(U_SUCCESS(*status) &&
1245        dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))==NULL) {
1246        *status = U_ILLEGAL_ARGUMENT_ERROR;
1247    }
1248 }
1249
1250
1251 U_CAPI int32_t U_EXPORT2 
1252 udat_toPatternRelativeDate(const UDateFormat *fmt,
1253                            UChar             *result,
1254                            int32_t           resultLength,
1255                            UErrorCode        *status)
1256 {
1257     verifyIsRelativeDateFormat(fmt, status);
1258     if(U_FAILURE(*status)) {
1259         return -1;
1260     }
1261     if (result == NULL ? resultLength != 0 : resultLength < 0) {
1262         *status = U_ILLEGAL_ARGUMENT_ERROR;
1263         return -1;
1264     }
1265
1266     UnicodeString datePattern;
1267     if (result != NULL) {
1268         // NULL destination for pure preflighting: empty dummy string
1269         // otherwise, alias the destination buffer
1270         datePattern.setTo(result, 0, resultLength);
1271     }
1272     ((RelativeDateFormat*)fmt)->toPatternDate(datePattern, *status);
1273     return datePattern.extract(result, resultLength, *status);
1274 }
1275
1276 U_CAPI int32_t U_EXPORT2 
1277 udat_toPatternRelativeTime(const UDateFormat *fmt,
1278                            UChar             *result,
1279                            int32_t           resultLength,
1280                            UErrorCode        *status)
1281 {
1282     verifyIsRelativeDateFormat(fmt, status);
1283     if(U_FAILURE(*status)) {
1284         return -1;
1285     }
1286     if (result == NULL ? resultLength != 0 : resultLength < 0) {
1287         *status = U_ILLEGAL_ARGUMENT_ERROR;
1288         return -1;
1289     }
1290
1291     UnicodeString timePattern;
1292     if (result != NULL) {
1293         // NULL destination for pure preflighting: empty dummy string
1294         // otherwise, alias the destination buffer
1295         timePattern.setTo(result, 0, resultLength);
1296     }
1297     ((RelativeDateFormat*)fmt)->toPatternTime(timePattern, *status);
1298     return timePattern.extract(result, resultLength, *status);
1299 }
1300
1301 U_CAPI void U_EXPORT2 
1302 udat_applyPatternRelative(UDateFormat *format,
1303                           const UChar *datePattern,
1304                           int32_t     datePatternLength,
1305                           const UChar *timePattern,
1306                           int32_t     timePatternLength,
1307                           UErrorCode  *status)
1308 {
1309     verifyIsRelativeDateFormat(format, status);
1310     if(U_FAILURE(*status)) return;
1311     const UnicodeString datePat((UBool)(datePatternLength == -1), datePattern, datePatternLength);
1312     const UnicodeString timePat((UBool)(timePatternLength == -1), timePattern, timePatternLength);
1313     ((RelativeDateFormat*)format)->applyPatterns(datePat, timePat, *status);
1314 }
1315
1316 #endif /* #if !UCONFIG_NO_FORMATTING */