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