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