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