tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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