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