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 */ 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 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 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 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 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 187 udat_close(UDateFormat* format) 188 { 189 delete (DateFormat*)format; 190 } 191 192 U_CAPI UDateFormat* U_EXPORT2 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 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 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 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 301 udat_isLenient(const UDateFormat* fmt) 302 { 303 return ((DateFormat*)fmt)->isLenient(); 304 } 305 306 U_CAPI void U_EXPORT2 307 udat_setLenient( UDateFormat* fmt, 308 UBool isLenient) 309 { 310 ((DateFormat*)fmt)->setLenient(isLenient); 311 } 312 313 U_CAPI const UCalendar* U_EXPORT2 314 udat_getCalendar(const UDateFormat* fmt) 315 { 316 return (const UCalendar*) ((DateFormat*)fmt)->getCalendar(); 317 } 318 319 U_CAPI void U_EXPORT2 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 327 udat_getNumberFormat(const UDateFormat* fmt) 328 { 329 return (const UNumberFormat*) ((DateFormat*)fmt)->getNumberFormat(); 330 } 331 332 U_CAPI void U_EXPORT2 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 340 udat_getAvailable(int32_t index) 341 { 342 return uloc_getAvailable(index); 343 } 344 345 U_CAPI int32_t U_EXPORT2 346 udat_countAvailable() 347 { 348 return uloc_countAvailable(); 349 } 350 351 U_CAPI UDate U_EXPORT2 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 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 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 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