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