datefmt.cpp (22918B)
1 // © 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ******************************************************************************* 5 * Copyright (C) 1997-2015, International Business Machines Corporation and * 6 * others. All Rights Reserved. * 7 ******************************************************************************* 8 * 9 * File DATEFMT.CPP 10 * 11 * Modification History: 12 * 13 * Date Name Description 14 * 02/19/97 aliu Converted from java. 15 * 03/31/97 aliu Modified extensively to work with 50 locales. 16 * 04/01/97 aliu Added support for centuries. 17 * 08/12/97 aliu Fixed operator== to use Calendar::equivalentTo. 18 * 07/20/98 stephen Changed ParsePosition initialization 19 ******************************************************************************** 20 */ 21 22 #include "unicode/utypes.h" 23 24 #if !UCONFIG_NO_FORMATTING 25 26 #include "unicode/ures.h" 27 #include "unicode/datefmt.h" 28 #include "unicode/smpdtfmt.h" 29 #include "unicode/dtptngen.h" 30 #include "unicode/udisplaycontext.h" 31 #include "unicode/gregocal.h" 32 #include "reldtfmt.h" 33 #include "sharedobject.h" 34 #include "unifiedcache.h" 35 #include "uarrsort.h" 36 37 #include "cstring.h" 38 #include "windtfmt.h" 39 40 #if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL) 41 #include <stdio.h> 42 #endif 43 #include <typeinfo> 44 45 // ***************************************************************************** 46 // class DateFormat 47 // ***************************************************************************** 48 49 U_NAMESPACE_BEGIN 50 51 class DateFmtBestPattern : public SharedObject { 52 public: 53 UnicodeString fPattern; 54 55 DateFmtBestPattern(const UnicodeString &pattern) 56 : fPattern(pattern) { } 57 ~DateFmtBestPattern(); 58 }; 59 60 DateFmtBestPattern::~DateFmtBestPattern() { 61 } 62 63 template<> 64 const DateFmtBestPattern *LocaleCacheKey<DateFmtBestPattern>::createObject( 65 const void * /*creationContext*/, UErrorCode &status) const { 66 status = U_UNSUPPORTED_ERROR; 67 return nullptr; 68 } 69 70 class DateFmtBestPatternKey : public LocaleCacheKey<DateFmtBestPattern> { 71 private: 72 UnicodeString fSkeleton; 73 protected: 74 virtual bool equals(const CacheKeyBase &other) const override { 75 if (!LocaleCacheKey<DateFmtBestPattern>::equals(other)) { 76 return false; 77 } 78 // We know that this and other are of same class if we get this far. 79 return operator==(static_cast<const DateFmtBestPatternKey &>(other)); 80 } 81 public: 82 DateFmtBestPatternKey( 83 const Locale &loc, 84 const UnicodeString &skeleton, 85 UErrorCode &status) 86 : LocaleCacheKey<DateFmtBestPattern>(loc), 87 fSkeleton(DateTimePatternGenerator::staticGetSkeleton(skeleton, status)) { } 88 DateFmtBestPatternKey(const DateFmtBestPatternKey &other) : 89 LocaleCacheKey<DateFmtBestPattern>(other), 90 fSkeleton(other.fSkeleton) { } 91 virtual ~DateFmtBestPatternKey(); 92 virtual int32_t hashCode() const override { 93 return static_cast<int32_t>(37u * static_cast<uint32_t>(LocaleCacheKey<DateFmtBestPattern>::hashCode()) + static_cast<uint32_t>(fSkeleton.hashCode())); 94 } 95 inline bool operator==(const DateFmtBestPatternKey &other) const { 96 return fSkeleton == other.fSkeleton; 97 } 98 virtual CacheKeyBase *clone() const override { 99 return new DateFmtBestPatternKey(*this); 100 } 101 virtual const DateFmtBestPattern *createObject( 102 const void * /*unused*/, UErrorCode &status) const override { 103 LocalPointer<DateTimePatternGenerator> dtpg( 104 DateTimePatternGenerator::createInstance(fLoc, status)); 105 if (U_FAILURE(status)) { 106 return nullptr; 107 } 108 109 LocalPointer<DateFmtBestPattern> pattern( 110 new DateFmtBestPattern( 111 dtpg->getBestPattern(fSkeleton, status)), 112 status); 113 if (U_FAILURE(status)) { 114 return nullptr; 115 } 116 DateFmtBestPattern *result = pattern.orphan(); 117 result->addRef(); 118 return result; 119 } 120 }; 121 122 DateFmtBestPatternKey::~DateFmtBestPatternKey() { } 123 124 125 DateFormat::DateFormat() 126 : fCalendar(nullptr), 127 fNumberFormat(nullptr), 128 fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE) 129 { 130 } 131 132 //---------------------------------------------------------------------- 133 134 DateFormat::DateFormat(const DateFormat& other) 135 : Format(other), 136 fCalendar(nullptr), 137 fNumberFormat(nullptr), 138 fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE) 139 { 140 *this = other; 141 } 142 143 //---------------------------------------------------------------------- 144 145 DateFormat& DateFormat::operator=(const DateFormat& other) 146 { 147 if (this != &other) 148 { 149 delete fCalendar; 150 delete fNumberFormat; 151 if(other.fCalendar) { 152 fCalendar = other.fCalendar->clone(); 153 } else { 154 fCalendar = nullptr; 155 } 156 if(other.fNumberFormat) { 157 fNumberFormat = other.fNumberFormat->clone(); 158 } else { 159 fNumberFormat = nullptr; 160 } 161 fBoolFlags = other.fBoolFlags; 162 fCapitalizationContext = other.fCapitalizationContext; 163 } 164 return *this; 165 } 166 167 //---------------------------------------------------------------------- 168 169 DateFormat::~DateFormat() 170 { 171 delete fCalendar; 172 delete fNumberFormat; 173 } 174 175 //---------------------------------------------------------------------- 176 177 bool 178 DateFormat::operator==(const Format& other) const 179 { 180 if (this == &other) { 181 return true; 182 } 183 if (!(Format::operator==(other))) { 184 return false; 185 } 186 // Format::operator== guarantees that this cast is safe 187 DateFormat* fmt = (DateFormat*)&other; 188 return fCalendar&&(fCalendar->isEquivalentTo(*fmt->fCalendar)) && 189 (fNumberFormat && *fNumberFormat == *fmt->fNumberFormat) && 190 (fCapitalizationContext == fmt->fCapitalizationContext); 191 } 192 193 //---------------------------------------------------------------------- 194 195 UnicodeString& 196 DateFormat::format(const Formattable& obj, 197 UnicodeString& appendTo, 198 FieldPosition& fieldPosition, 199 UErrorCode& status) const 200 { 201 if (U_FAILURE(status)) return appendTo; 202 203 // if the type of the Formattable is double or long, treat it as if it were a Date 204 UDate date = 0; 205 switch (obj.getType()) 206 { 207 case Formattable::kDate: 208 date = obj.getDate(); 209 break; 210 case Formattable::kDouble: 211 date = static_cast<UDate>(obj.getDouble()); 212 break; 213 case Formattable::kLong: 214 date = static_cast<UDate>(obj.getLong()); 215 break; 216 default: 217 status = U_ILLEGAL_ARGUMENT_ERROR; 218 return appendTo; 219 } 220 221 // Is this right? 222 //if (fieldPosition.getBeginIndex() == fieldPosition.getEndIndex()) 223 // status = U_ILLEGAL_ARGUMENT_ERROR; 224 225 return format(date, appendTo, fieldPosition); 226 } 227 228 //---------------------------------------------------------------------- 229 230 UnicodeString& 231 DateFormat::format(const Formattable& obj, 232 UnicodeString& appendTo, 233 FieldPositionIterator* posIter, 234 UErrorCode& status) const 235 { 236 if (U_FAILURE(status)) return appendTo; 237 238 // if the type of the Formattable is double or long, treat it as if it were a Date 239 UDate date = 0; 240 switch (obj.getType()) 241 { 242 case Formattable::kDate: 243 date = obj.getDate(); 244 break; 245 case Formattable::kDouble: 246 date = static_cast<UDate>(obj.getDouble()); 247 break; 248 case Formattable::kLong: 249 date = static_cast<UDate>(obj.getLong()); 250 break; 251 default: 252 status = U_ILLEGAL_ARGUMENT_ERROR; 253 return appendTo; 254 } 255 256 // Is this right? 257 //if (fieldPosition.getBeginIndex() == fieldPosition.getEndIndex()) 258 // status = U_ILLEGAL_ARGUMENT_ERROR; 259 260 return format(date, appendTo, posIter, status); 261 } 262 263 //---------------------------------------------------------------------- 264 265 // Default implementation for backwards compatibility, subclasses should implement. 266 UnicodeString& 267 DateFormat::format(Calendar& /* unused cal */, 268 UnicodeString& appendTo, 269 FieldPositionIterator* /* unused posIter */, 270 UErrorCode& status) const { 271 if (U_SUCCESS(status)) { 272 status = U_UNSUPPORTED_ERROR; 273 } 274 return appendTo; 275 } 276 277 //---------------------------------------------------------------------- 278 279 UnicodeString& 280 DateFormat::format(UDate date, UnicodeString& appendTo, FieldPosition& fieldPosition) const { 281 if (fCalendar != nullptr) { 282 UErrorCode ec = U_ZERO_ERROR; 283 // Avoid a heap allocation and corresponding free for the common case 284 if (typeid(*fCalendar) == typeid(GregorianCalendar)) { 285 GregorianCalendar cal(*static_cast<GregorianCalendar*>(fCalendar)); 286 cal.setTime(date, ec); 287 if (U_SUCCESS(ec)) { 288 format(cal, appendTo, fieldPosition); 289 } 290 } else { 291 // Use a clone of our calendar instance 292 Calendar *calClone = fCalendar->clone(); 293 if (calClone != nullptr) { 294 calClone->setTime(date, ec); 295 if (U_SUCCESS(ec)) { 296 format(*calClone, appendTo, fieldPosition); 297 } 298 delete calClone; 299 } 300 } 301 } 302 return appendTo; 303 } 304 305 //---------------------------------------------------------------------- 306 307 UnicodeString& 308 DateFormat::format(UDate date, UnicodeString& appendTo, FieldPositionIterator* posIter, 309 UErrorCode& status) const { 310 if (fCalendar != nullptr) { 311 UErrorCode ec = U_ZERO_ERROR; 312 // Avoid a heap allocation and corresponding free for the common case 313 if (typeid(*fCalendar) == typeid(GregorianCalendar)) { 314 GregorianCalendar cal(*static_cast<GregorianCalendar*>(fCalendar)); 315 cal.setTime(date, ec); 316 if (U_SUCCESS(ec)) { 317 format(cal, appendTo, posIter, status); 318 } 319 } else { 320 Calendar* calClone = fCalendar->clone(); 321 if (calClone != nullptr) { 322 calClone->setTime(date, status); 323 if (U_SUCCESS(status)) { 324 format(*calClone, appendTo, posIter, status); 325 } 326 delete calClone; 327 } 328 } 329 } 330 return appendTo; 331 } 332 333 //---------------------------------------------------------------------- 334 335 UnicodeString& 336 DateFormat::format(UDate date, UnicodeString& appendTo) const 337 { 338 // Note that any error information is just lost. That's okay 339 // for this convenience method. 340 FieldPosition fpos(FieldPosition::DONT_CARE); 341 return format(date, appendTo, fpos); 342 } 343 344 //---------------------------------------------------------------------- 345 346 UDate 347 DateFormat::parse(const UnicodeString& text, 348 ParsePosition& pos) const 349 { 350 UDate d = 0; // Error return UDate is 0 (the epoch) 351 if (fCalendar != nullptr) { 352 Calendar* calClone = fCalendar->clone(); 353 if (calClone != nullptr) { 354 int32_t start = pos.getIndex(); 355 calClone->clear(); 356 parse(text, *calClone, pos); 357 if (pos.getIndex() != start) { 358 UErrorCode ec = U_ZERO_ERROR; 359 d = calClone->getTime(ec); 360 if (U_FAILURE(ec)) { 361 // We arrive here if fCalendar => calClone is non-lenient and 362 // there is an out-of-range field. We don't know which field 363 // was illegal so we set the error index to the start. 364 pos.setIndex(start); 365 pos.setErrorIndex(start); 366 d = 0; 367 } 368 } 369 delete calClone; 370 } 371 } 372 return d; 373 } 374 375 //---------------------------------------------------------------------- 376 377 UDate 378 DateFormat::parse(const UnicodeString& text, 379 UErrorCode& status) const 380 { 381 if (U_FAILURE(status)) return 0; 382 383 ParsePosition pos(0); 384 UDate result = parse(text, pos); 385 if (pos.getIndex() == 0) { 386 #if defined (U_DEBUG_CAL) 387 fprintf(stderr, "%s:%d - - failed to parse - err index %d\n" 388 , __FILE__, __LINE__, pos.getErrorIndex() ); 389 #endif 390 status = U_ILLEGAL_ARGUMENT_ERROR; 391 } 392 return result; 393 } 394 395 //---------------------------------------------------------------------- 396 397 void 398 DateFormat::parseObject(const UnicodeString& source, 399 Formattable& result, 400 ParsePosition& pos) const 401 { 402 result.setDate(parse(source, pos)); 403 } 404 405 //---------------------------------------------------------------------- 406 407 DateFormat* U_EXPORT2 408 DateFormat::createTimeInstance(DateFormat::EStyle style, 409 const Locale& aLocale) 410 { 411 return createDateTimeInstance(kNone, style, aLocale); 412 } 413 414 //---------------------------------------------------------------------- 415 416 DateFormat* U_EXPORT2 417 DateFormat::createDateInstance(DateFormat::EStyle style, 418 const Locale& aLocale) 419 { 420 return createDateTimeInstance(style, kNone, aLocale); 421 } 422 423 //---------------------------------------------------------------------- 424 425 DateFormat* U_EXPORT2 426 DateFormat::createDateTimeInstance(EStyle dateStyle, 427 EStyle timeStyle, 428 const Locale& aLocale) 429 { 430 if(dateStyle != kNone) 431 { 432 dateStyle = static_cast<EStyle>(dateStyle + kDateOffset); 433 } 434 return create(timeStyle, dateStyle, aLocale); 435 } 436 437 //---------------------------------------------------------------------- 438 439 DateFormat* U_EXPORT2 440 DateFormat::createInstance() 441 { 442 return createDateTimeInstance(kShort, kShort, Locale::getDefault()); 443 } 444 445 //---------------------------------------------------------------------- 446 447 UnicodeString U_EXPORT2 448 DateFormat::getBestPattern( 449 const Locale &locale, 450 const UnicodeString &skeleton, 451 UErrorCode &status) { 452 UnifiedCache *cache = UnifiedCache::getInstance(status); 453 if (U_FAILURE(status)) { 454 return {}; 455 } 456 DateFmtBestPatternKey key(locale, skeleton, status); 457 const DateFmtBestPattern *patternPtr = nullptr; 458 cache->get(key, patternPtr, status); 459 if (U_FAILURE(status)) { 460 return {}; 461 } 462 UnicodeString result(patternPtr->fPattern); 463 patternPtr->removeRef(); 464 return result; 465 } 466 467 DateFormat* U_EXPORT2 468 DateFormat::createInstanceForSkeleton( 469 Calendar *calendarToAdopt, 470 const UnicodeString& skeleton, 471 const Locale &locale, 472 UErrorCode &status) { 473 LocalPointer<Calendar> calendar(calendarToAdopt); 474 if (U_FAILURE(status)) { 475 return nullptr; 476 } 477 if (calendar.isNull()) { 478 status = U_ILLEGAL_ARGUMENT_ERROR; 479 return nullptr; 480 } 481 Locale localeWithCalendar = locale; 482 localeWithCalendar.setKeywordValue("calendar", calendar->getType(), status); 483 if (U_FAILURE(status)) { 484 return nullptr; 485 } 486 DateFormat *result = createInstanceForSkeleton(skeleton, localeWithCalendar, status); 487 if (U_FAILURE(status)) { 488 return nullptr; 489 } 490 result->adoptCalendar(calendar.orphan()); 491 return result; 492 } 493 494 DateFormat* U_EXPORT2 495 DateFormat::createInstanceForSkeleton( 496 const UnicodeString& skeleton, 497 const Locale &locale, 498 UErrorCode &status) { 499 if (U_FAILURE(status)) { 500 return nullptr; 501 } 502 LocalPointer<DateFormat> df( 503 new SimpleDateFormat( 504 getBestPattern(locale, skeleton, status), 505 locale, status), 506 status); 507 return U_SUCCESS(status) ? df.orphan() : nullptr; 508 } 509 510 DateFormat* U_EXPORT2 511 DateFormat::createInstanceForSkeleton( 512 const UnicodeString& skeleton, 513 UErrorCode &status) { 514 return createInstanceForSkeleton( 515 skeleton, Locale::getDefault(), status); 516 } 517 518 //---------------------------------------------------------------------- 519 520 DateFormat* U_EXPORT2 521 DateFormat::create(EStyle timeStyle, EStyle dateStyle, const Locale& locale) 522 { 523 UErrorCode status = U_ZERO_ERROR; 524 #if U_PLATFORM_USES_ONLY_WIN32_API 525 char buffer[8]; 526 int32_t count = locale.getKeywordValue("compat", buffer, sizeof(buffer), status); 527 528 // if the locale has "@compat=host", create a host-specific DateFormat... 529 if (count > 0 && uprv_strcmp(buffer, "host") == 0) { 530 Win32DateFormat *f = new Win32DateFormat(timeStyle, dateStyle, locale, status); 531 532 if (U_SUCCESS(status)) { 533 return f; 534 } 535 536 delete f; 537 } 538 #endif 539 540 // is it relative? 541 if(/*((timeStyle!=UDAT_NONE)&&(timeStyle & UDAT_RELATIVE)) || */((dateStyle!=kNone)&&((dateStyle-kDateOffset) & UDAT_RELATIVE))) { 542 RelativeDateFormat* r = new RelativeDateFormat(static_cast<UDateFormatStyle>(timeStyle), static_cast<UDateFormatStyle>(dateStyle - kDateOffset), locale, status); 543 if(U_SUCCESS(status)) return r; 544 delete r; 545 status = U_ZERO_ERROR; 546 } 547 548 // Try to create a SimpleDateFormat of the desired style. 549 SimpleDateFormat *f = new SimpleDateFormat(timeStyle, dateStyle, locale, status); 550 if (U_SUCCESS(status)) return f; 551 delete f; 552 553 // If that fails, try to create a format using the default pattern and 554 // the DateFormatSymbols for this locale. 555 status = U_ZERO_ERROR; 556 f = new SimpleDateFormat(locale, status); 557 if (U_SUCCESS(status)) return f; 558 delete f; 559 560 // This should never really happen, because the preceding constructor 561 // should always succeed. If the resource data is unavailable, a last 562 // resort object should be returned. 563 return nullptr; 564 } 565 566 //---------------------------------------------------------------------- 567 568 const Locale* U_EXPORT2 569 DateFormat::getAvailableLocales(int32_t& count) 570 { 571 // Get the list of installed locales. 572 // Even if root has the correct date format for this locale, 573 // it's still a valid locale (we don't worry about data fallbacks). 574 return Locale::getAvailableLocales(count); 575 } 576 577 //---------------------------------------------------------------------- 578 579 void 580 DateFormat::adoptCalendar(Calendar* newCalendar) 581 { 582 delete fCalendar; 583 fCalendar = newCalendar; 584 } 585 586 //---------------------------------------------------------------------- 587 void 588 DateFormat::setCalendar(const Calendar& newCalendar) 589 { 590 Calendar* newCalClone = newCalendar.clone(); 591 if (newCalClone != nullptr) { 592 adoptCalendar(newCalClone); 593 } 594 } 595 596 //---------------------------------------------------------------------- 597 598 const Calendar* 599 DateFormat::getCalendar() const 600 { 601 return fCalendar; 602 } 603 604 //---------------------------------------------------------------------- 605 606 void 607 DateFormat::adoptNumberFormat(NumberFormat* newNumberFormat) 608 { 609 delete fNumberFormat; 610 fNumberFormat = newNumberFormat; 611 newNumberFormat->setParseIntegerOnly(true); 612 newNumberFormat->setGroupingUsed(false); 613 } 614 //---------------------------------------------------------------------- 615 616 void 617 DateFormat::setNumberFormat(const NumberFormat& newNumberFormat) 618 { 619 NumberFormat* newNumFmtClone = newNumberFormat.clone(); 620 if (newNumFmtClone != nullptr) { 621 adoptNumberFormat(newNumFmtClone); 622 } 623 } 624 625 //---------------------------------------------------------------------- 626 627 const NumberFormat* 628 DateFormat::getNumberFormat() const 629 { 630 return fNumberFormat; 631 } 632 633 //---------------------------------------------------------------------- 634 635 void 636 DateFormat::adoptTimeZone(TimeZone* zone) 637 { 638 if (fCalendar != nullptr) { 639 fCalendar->adoptTimeZone(zone); 640 } 641 } 642 //---------------------------------------------------------------------- 643 644 void 645 DateFormat::setTimeZone(const TimeZone& zone) 646 { 647 if (fCalendar != nullptr) { 648 fCalendar->setTimeZone(zone); 649 } 650 } 651 652 //---------------------------------------------------------------------- 653 654 const TimeZone& 655 DateFormat::getTimeZone() const 656 { 657 if (fCalendar != nullptr) { 658 return fCalendar->getTimeZone(); 659 } 660 // If calendar doesn't exists, create default timezone. 661 // fCalendar is rarely null 662 return *(TimeZone::createDefault()); 663 } 664 665 //---------------------------------------------------------------------- 666 667 void 668 DateFormat::setLenient(UBool lenient) 669 { 670 if (fCalendar != nullptr) { 671 fCalendar->setLenient(lenient); 672 } 673 UErrorCode status = U_ZERO_ERROR; 674 setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, lenient, status); 675 setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, lenient, status); 676 } 677 678 //---------------------------------------------------------------------- 679 680 UBool 681 DateFormat::isLenient() const 682 { 683 UBool lenient = true; 684 if (fCalendar != nullptr) { 685 lenient = fCalendar->isLenient(); 686 } 687 UErrorCode status = U_ZERO_ERROR; 688 return lenient 689 && getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status) 690 && getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status); 691 } 692 693 void 694 DateFormat::setCalendarLenient(UBool lenient) 695 { 696 if (fCalendar != nullptr) { 697 fCalendar->setLenient(lenient); 698 } 699 } 700 701 //---------------------------------------------------------------------- 702 703 UBool 704 DateFormat::isCalendarLenient() const 705 { 706 if (fCalendar != nullptr) { 707 return fCalendar->isLenient(); 708 } 709 // fCalendar is rarely null 710 return false; 711 } 712 713 714 //---------------------------------------------------------------------- 715 716 717 void DateFormat::setContext(UDisplayContext value, UErrorCode& status) 718 { 719 if (U_FAILURE(status)) 720 return; 721 if (static_cast<UDisplayContextType>(static_cast<uint32_t>(value) >> 8) == UDISPCTX_TYPE_CAPITALIZATION) { 722 fCapitalizationContext = value; 723 } else { 724 status = U_ILLEGAL_ARGUMENT_ERROR; 725 } 726 } 727 728 729 //---------------------------------------------------------------------- 730 731 732 UDisplayContext DateFormat::getContext(UDisplayContextType type, UErrorCode& status) const 733 { 734 if (U_FAILURE(status)) 735 return static_cast<UDisplayContext>(0); 736 if (type != UDISPCTX_TYPE_CAPITALIZATION) { 737 status = U_ILLEGAL_ARGUMENT_ERROR; 738 return static_cast<UDisplayContext>(0); 739 } 740 return fCapitalizationContext; 741 } 742 743 744 //---------------------------------------------------------------------- 745 746 747 DateFormat& 748 DateFormat::setBooleanAttribute(UDateFormatBooleanAttribute attr, 749 UBool newValue, 750 UErrorCode &status) { 751 if(!fBoolFlags.isValidValue(newValue)) { 752 status = U_ILLEGAL_ARGUMENT_ERROR; 753 } else { 754 fBoolFlags.set(attr, newValue); 755 } 756 757 return *this; 758 } 759 760 //---------------------------------------------------------------------- 761 762 UBool 763 DateFormat::getBooleanAttribute(UDateFormatBooleanAttribute attr, UErrorCode &/*status*/) const { 764 765 return fBoolFlags.get(attr); 766 } 767 768 U_NAMESPACE_END 769 770 #endif /* #if !UCONFIG_NO_FORMATTING */ 771 772 //eof