Coverage Report

Created: 2026-02-05 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/icu/icu4c/source/i18n/datefmt.cpp
Line
Count
Source
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
11.5k
            : fPattern(pattern) { }
57
    ~DateFmtBestPattern();
58
};
59
60
10.2k
DateFmtBestPattern::~DateFmtBestPattern() {
61
10.2k
}
62
63
template<> 
64
const DateFmtBestPattern *LocaleCacheKey<DateFmtBestPattern>::createObject(
65
0
        const void * /*creationContext*/, UErrorCode &status) const {
66
0
    status = U_UNSUPPORTED_ERROR;
67
0
    return nullptr;
68
0
}
69
70
class DateFmtBestPatternKey : public LocaleCacheKey<DateFmtBestPattern> { 
71
private:
72
    UnicodeString fSkeleton;
73
protected:
74
43.7k
    virtual bool equals(const CacheKeyBase &other) const override {
75
43.7k
       if (!LocaleCacheKey<DateFmtBestPattern>::equals(other)) {
76
0
           return false;
77
0
       }
78
       // We know that this and other are of same class if we get this far.
79
43.7k
       return operator==(static_cast<const DateFmtBestPatternKey &>(other));
80
43.7k
    }
81
public:
82
    DateFmtBestPatternKey(
83
        const Locale &loc,
84
        const UnicodeString &skeleton,
85
        UErrorCode &status)
86
43.0k
            : LocaleCacheKey<DateFmtBestPattern>(loc),
87
43.0k
              fSkeleton(DateTimePatternGenerator::staticGetSkeleton(skeleton, status)) { }
88
    DateFmtBestPatternKey(const DateFmtBestPatternKey &other) :
89
11.5k
            LocaleCacheKey<DateFmtBestPattern>(other),
90
11.5k
            fSkeleton(other.fSkeleton) { }
91
    virtual ~DateFmtBestPatternKey();
92
66.1k
    virtual int32_t hashCode() const override {
93
66.1k
        return static_cast<int32_t>(37u * static_cast<uint32_t>(LocaleCacheKey<DateFmtBestPattern>::hashCode()) + static_cast<uint32_t>(fSkeleton.hashCode()));
94
66.1k
    }
95
43.7k
    inline bool operator==(const DateFmtBestPatternKey &other) const {
96
43.7k
        return fSkeleton == other.fSkeleton;
97
43.7k
    }
98
11.5k
    virtual CacheKeyBase *clone() const override {
99
11.5k
        return new DateFmtBestPatternKey(*this);
100
11.5k
    }
101
    virtual const DateFmtBestPattern *createObject(
102
11.5k
            const void * /*unused*/, UErrorCode &status) const override {
103
11.5k
        LocalPointer<DateTimePatternGenerator> dtpg(
104
11.5k
                    DateTimePatternGenerator::createInstance(fLoc, status));
105
11.5k
        if (U_FAILURE(status)) {
106
0
            return nullptr;
107
0
        }
108
  
109
11.5k
        LocalPointer<DateFmtBestPattern> pattern(
110
11.5k
                new DateFmtBestPattern(
111
11.5k
                        dtpg->getBestPattern(fSkeleton, status)),
112
11.5k
                status);
113
11.5k
        if (U_FAILURE(status)) {
114
0
            return nullptr;
115
0
        }
116
11.5k
        DateFmtBestPattern *result = pattern.orphan();
117
11.5k
        result->addRef();
118
11.5k
        return result;
119
11.5k
    }
120
};
121
122
53.3k
DateFmtBestPatternKey::~DateFmtBestPatternKey() { }
123
124
125
DateFormat::DateFormat()
126
140k
:   fCalendar(nullptr),
127
140k
    fNumberFormat(nullptr),
128
140k
    fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
129
140k
{
130
140k
}
131
132
//----------------------------------------------------------------------
133
134
DateFormat::DateFormat(const DateFormat& other)
135
0
:   Format(other),
136
0
    fCalendar(nullptr),
137
0
    fNumberFormat(nullptr),
138
0
    fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
139
0
{
140
0
    *this = other;
141
0
}
142
143
//----------------------------------------------------------------------
144
145
DateFormat& DateFormat::operator=(const DateFormat& other)
146
0
{
147
0
    if (this != &other)
148
0
    {
149
0
        delete fCalendar;
150
0
        delete fNumberFormat;
151
0
        if(other.fCalendar) {
152
0
          fCalendar = other.fCalendar->clone();
153
0
        } else {
154
0
          fCalendar = nullptr;
155
0
        }
156
0
        if(other.fNumberFormat) {
157
0
          fNumberFormat = other.fNumberFormat->clone();
158
0
        } else {
159
0
          fNumberFormat = nullptr;
160
0
        }
161
0
        fBoolFlags = other.fBoolFlags;
162
0
        fCapitalizationContext = other.fCapitalizationContext;
163
0
    }
164
0
    return *this;
165
0
}
166
167
//----------------------------------------------------------------------
168
169
DateFormat::~DateFormat()
170
140k
{
171
140k
    delete fCalendar;
172
140k
    delete fNumberFormat;
173
140k
}
174
175
//----------------------------------------------------------------------
176
177
bool
178
DateFormat::operator==(const Format& other) const
179
0
{
180
0
    if (this == &other) {
181
0
        return true;
182
0
    }
183
0
    if (!(Format::operator==(other))) {
184
0
        return false;
185
0
    }
186
    // Format::operator== guarantees that this cast is safe
187
0
    DateFormat* fmt = (DateFormat*)&other;
188
0
    return fCalendar&&(fCalendar->isEquivalentTo(*fmt->fCalendar)) &&
189
0
         (fNumberFormat && *fNumberFormat == *fmt->fNumberFormat) &&
190
0
         (fCapitalizationContext == fmt->fCapitalizationContext);
191
0
}
192
193
//----------------------------------------------------------------------
194
195
UnicodeString&
196
DateFormat::format(const Formattable& obj,
197
                   UnicodeString& appendTo,
198
                   FieldPosition& fieldPosition,
199
                   UErrorCode& status) const
200
0
{
201
0
    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
0
    UDate date = 0;
205
0
    switch (obj.getType())
206
0
    {
207
0
    case Formattable::kDate:
208
0
        date = obj.getDate();
209
0
        break;
210
0
    case Formattable::kDouble:
211
0
        date = static_cast<UDate>(obj.getDouble());
212
0
        break;
213
0
    case Formattable::kLong:
214
0
        date = static_cast<UDate>(obj.getLong());
215
0
        break;
216
0
    default:
217
0
        status = U_ILLEGAL_ARGUMENT_ERROR;
218
0
        return appendTo;
219
0
    }
220
221
    // Is this right?
222
    //if (fieldPosition.getBeginIndex() == fieldPosition.getEndIndex())
223
    //  status = U_ILLEGAL_ARGUMENT_ERROR;
224
225
0
    return format(date, appendTo, fieldPosition);
226
0
}
227
228
//----------------------------------------------------------------------
229
230
UnicodeString&
231
DateFormat::format(const Formattable& obj,
232
                   UnicodeString& appendTo,
233
                   FieldPositionIterator* posIter,
234
                   UErrorCode& status) const
235
0
{
236
0
    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
0
    UDate date = 0;
240
0
    switch (obj.getType())
241
0
    {
242
0
    case Formattable::kDate:
243
0
        date = obj.getDate();
244
0
        break;
245
0
    case Formattable::kDouble:
246
0
        date = static_cast<UDate>(obj.getDouble());
247
0
        break;
248
0
    case Formattable::kLong:
249
0
        date = static_cast<UDate>(obj.getLong());
250
0
        break;
251
0
    default:
252
0
        status = U_ILLEGAL_ARGUMENT_ERROR;
253
0
        return appendTo;
254
0
    }
255
256
    // Is this right?
257
    //if (fieldPosition.getBeginIndex() == fieldPosition.getEndIndex())
258
    //  status = U_ILLEGAL_ARGUMENT_ERROR;
259
260
0
    return format(date, appendTo, posIter, status);
261
0
}
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
0
                   UErrorCode& status) const {
271
0
    if (U_SUCCESS(status)) {
272
0
        status = U_UNSUPPORTED_ERROR;
273
0
    }
274
0
    return appendTo;
275
0
}
276
277
//----------------------------------------------------------------------
278
279
UnicodeString&
280
29.4k
DateFormat::format(UDate date, UnicodeString& appendTo, FieldPosition& fieldPosition) const {
281
29.4k
    if (fCalendar != nullptr) {
282
29.4k
        UErrorCode ec = U_ZERO_ERROR;
283
        // Avoid a heap allocation and corresponding free for the common case
284
29.4k
        if (typeid(*fCalendar) == typeid(GregorianCalendar)) {
285
27.9k
            GregorianCalendar cal(*static_cast<GregorianCalendar*>(fCalendar));
286
27.9k
            cal.setTime(date, ec);
287
27.9k
            if (U_SUCCESS(ec)) {
288
27.5k
                format(cal, appendTo, fieldPosition);
289
27.5k
            }
290
27.9k
        } else {
291
            // Use a clone of our calendar instance
292
1.45k
            Calendar *calClone = fCalendar->clone();
293
1.45k
            if (calClone != nullptr) {
294
1.45k
                calClone->setTime(date, ec);
295
1.45k
                if (U_SUCCESS(ec)) {
296
1.44k
                    format(*calClone, appendTo, fieldPosition);
297
1.44k
                }
298
1.45k
                delete calClone;
299
1.45k
            }
300
1.45k
        }
301
29.4k
    }
302
29.4k
    return appendTo;
303
29.4k
}
304
305
//----------------------------------------------------------------------
306
307
UnicodeString&
308
DateFormat::format(UDate date, UnicodeString& appendTo, FieldPositionIterator* posIter,
309
0
                   UErrorCode& status) const {
310
0
    if (fCalendar != nullptr) {
311
0
        UErrorCode ec = U_ZERO_ERROR;
312
        // Avoid a heap allocation and corresponding free for the common case
313
0
        if (typeid(*fCalendar) == typeid(GregorianCalendar)) {
314
0
            GregorianCalendar cal(*static_cast<GregorianCalendar*>(fCalendar));
315
0
            cal.setTime(date, ec);
316
0
            if (U_SUCCESS(ec)) {
317
0
                format(cal, appendTo, posIter, status);
318
0
            }
319
0
        } else {
320
0
            Calendar* calClone = fCalendar->clone();
321
0
            if (calClone != nullptr) {
322
0
                calClone->setTime(date, status);
323
0
                if (U_SUCCESS(status)) {
324
0
                    format(*calClone, appendTo, posIter, status);
325
0
                }
326
0
                delete calClone;
327
0
            }
328
0
        }
329
0
    }
330
0
    return appendTo;
331
0
}
332
333
//----------------------------------------------------------------------
334
335
UnicodeString&
336
DateFormat::format(UDate date, UnicodeString& appendTo) const
337
29.4k
{
338
    // Note that any error information is just lost.  That's okay
339
    // for this convenience method.
340
29.4k
    FieldPosition fpos(FieldPosition::DONT_CARE);
341
29.4k
    return format(date, appendTo, fpos);
342
29.4k
}
343
344
//----------------------------------------------------------------------
345
346
UDate
347
DateFormat::parse(const UnicodeString& text,
348
                  ParsePosition& pos) const
349
0
{
350
0
    UDate d = 0; // Error return UDate is 0 (the epoch)
351
0
    if (fCalendar != nullptr) {
352
0
        Calendar* calClone = fCalendar->clone();
353
0
        if (calClone != nullptr) {
354
0
            int32_t start = pos.getIndex();
355
0
            calClone->clear();
356
0
            parse(text, *calClone, pos);
357
0
            if (pos.getIndex() != start) {
358
0
                UErrorCode ec = U_ZERO_ERROR;
359
0
                d = calClone->getTime(ec);
360
0
                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
0
                    pos.setIndex(start);
365
0
                    pos.setErrorIndex(start);
366
0
                    d = 0;
367
0
                }
368
0
            }
369
0
            delete calClone;
370
0
        }
371
0
    }
372
0
    return d;
373
0
}
374
375
//----------------------------------------------------------------------
376
377
UDate
378
DateFormat::parse(const UnicodeString& text,
379
                  UErrorCode& status) const
380
0
{
381
0
    if (U_FAILURE(status)) return 0;
382
383
0
    ParsePosition pos(0);
384
0
    UDate result = parse(text, pos);
385
0
    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
0
      status = U_ILLEGAL_ARGUMENT_ERROR;
391
0
    }
392
0
    return result;
393
0
}
394
395
//----------------------------------------------------------------------
396
397
void
398
DateFormat::parseObject(const UnicodeString& source,
399
                        Formattable& result,
400
                        ParsePosition& pos) const
401
0
{
402
0
    result.setDate(parse(source, pos));
403
0
}
404
405
//----------------------------------------------------------------------
406
407
DateFormat* U_EXPORT2
408
DateFormat::createTimeInstance(DateFormat::EStyle style,
409
                               const Locale& aLocale)
410
4.81k
{
411
4.81k
    return createDateTimeInstance(kNone, style, aLocale);
412
4.81k
}
413
414
//----------------------------------------------------------------------
415
416
DateFormat* U_EXPORT2
417
DateFormat::createDateInstance(DateFormat::EStyle style,
418
                               const Locale& aLocale)
419
30.3k
{
420
30.3k
    return createDateTimeInstance(style, kNone, aLocale);
421
30.3k
}
422
423
//----------------------------------------------------------------------
424
425
DateFormat* U_EXPORT2
426
DateFormat::createDateTimeInstance(EStyle dateStyle,
427
                                   EStyle timeStyle,
428
                                   const Locale& aLocale)
429
64.6k
{
430
64.6k
   if(dateStyle != kNone)
431
56.2k
   {
432
56.2k
       dateStyle = static_cast<EStyle>(dateStyle + kDateOffset);
433
56.2k
   }
434
64.6k
   return create(timeStyle, dateStyle, aLocale);
435
64.6k
}
436
437
//----------------------------------------------------------------------
438
439
DateFormat* U_EXPORT2
440
DateFormat::createInstance()
441
0
{
442
0
    return createDateTimeInstance(kShort, kShort, Locale::getDefault());
443
0
}
444
445
//----------------------------------------------------------------------
446
447
UnicodeString U_EXPORT2
448
DateFormat::getBestPattern(
449
        const Locale &locale,
450
        const UnicodeString &skeleton,
451
43.0k
        UErrorCode &status) {
452
43.0k
    UnifiedCache *cache = UnifiedCache::getInstance(status);
453
43.0k
    if (U_FAILURE(status)) {
454
0
        return {};
455
0
    }
456
43.0k
    DateFmtBestPatternKey key(locale, skeleton, status);
457
43.0k
    const DateFmtBestPattern *patternPtr = nullptr;
458
43.0k
    cache->get(key, patternPtr, status);
459
43.0k
    if (U_FAILURE(status)) {
460
0
        return {};
461
0
    }
462
43.0k
    UnicodeString result(patternPtr->fPattern);
463
43.0k
    patternPtr->removeRef();
464
43.0k
    return result;
465
43.0k
}
466
467
DateFormat* U_EXPORT2
468
DateFormat::createInstanceForSkeleton(
469
        Calendar *calendarToAdopt,
470
        const UnicodeString& skeleton,
471
        const Locale &locale,
472
0
        UErrorCode &status) {
473
0
    LocalPointer<Calendar> calendar(calendarToAdopt);
474
0
    if (U_FAILURE(status)) {
475
0
        return nullptr;
476
0
    }
477
0
    if (calendar.isNull()) {
478
0
        status = U_ILLEGAL_ARGUMENT_ERROR;
479
0
        return nullptr;
480
0
    }
481
0
    Locale localeWithCalendar = locale;
482
0
    localeWithCalendar.setKeywordValue("calendar", calendar->getType(), status);
483
0
    if (U_FAILURE(status)) {
484
0
        return nullptr;
485
0
    }
486
0
    DateFormat *result = createInstanceForSkeleton(skeleton, localeWithCalendar, status);
487
0
    if (U_FAILURE(status)) {
488
0
        return nullptr;
489
0
    }
490
0
    result->adoptCalendar(calendar.orphan());
491
0
    return result;
492
0
}
493
494
DateFormat* U_EXPORT2
495
DateFormat::createInstanceForSkeleton(
496
        const UnicodeString& skeleton,
497
        const Locale &locale,
498
43.0k
        UErrorCode &status) {
499
43.0k
    if (U_FAILURE(status)) {
500
0
        return nullptr;
501
0
    }
502
43.0k
    LocalPointer<DateFormat> df(
503
43.0k
        new SimpleDateFormat(
504
43.0k
            getBestPattern(locale, skeleton, status),
505
43.0k
            locale, status),
506
43.0k
        status);
507
43.0k
    return U_SUCCESS(status) ? df.orphan() : nullptr;
508
43.0k
}
509
510
DateFormat* U_EXPORT2
511
DateFormat::createInstanceForSkeleton(
512
        const UnicodeString& skeleton,
513
7.35k
        UErrorCode &status) {
514
7.35k
    return createInstanceForSkeleton(
515
7.35k
            skeleton, Locale::getDefault(), status);
516
7.35k
}
517
518
//----------------------------------------------------------------------
519
520
DateFormat* U_EXPORT2
521
DateFormat::create(EStyle timeStyle, EStyle dateStyle, const Locale& locale)
522
64.6k
{
523
64.6k
    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
64.6k
    if(/*((timeStyle!=UDAT_NONE)&&(timeStyle & UDAT_RELATIVE)) || */((dateStyle!=kNone)&&((dateStyle-kDateOffset) & UDAT_RELATIVE))) {
542
10.5k
        RelativeDateFormat* r = new RelativeDateFormat(static_cast<UDateFormatStyle>(timeStyle), static_cast<UDateFormatStyle>(dateStyle - kDateOffset), locale, status);
543
10.5k
        if(U_SUCCESS(status)) return r;
544
5.83k
        delete r;
545
5.83k
        status = U_ZERO_ERROR;
546
5.83k
    }
547
548
    // Try to create a SimpleDateFormat of the desired style.
549
59.9k
    SimpleDateFormat *f = new SimpleDateFormat(timeStyle, dateStyle, locale, status);
550
59.9k
    if (U_SUCCESS(status)) return f;
551
19.4k
    delete f;
552
553
    // If that fails, try to create a format using the default pattern and
554
    // the DateFormatSymbols for this locale.
555
19.4k
    status = U_ZERO_ERROR;
556
19.4k
    f = new SimpleDateFormat(locale, status);
557
19.4k
    if (U_SUCCESS(status)) return f;
558
693
    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
693
    return nullptr;
564
19.4k
}
565
566
//----------------------------------------------------------------------
567
568
const Locale* U_EXPORT2
569
DateFormat::getAvailableLocales(int32_t& count)
570
0
{
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
0
    return Locale::getAvailableLocales(count);
575
0
}
576
577
//----------------------------------------------------------------------
578
579
void
580
DateFormat::adoptCalendar(Calendar* newCalendar)
581
0
{
582
0
    delete fCalendar;
583
0
    fCalendar = newCalendar;
584
0
}
585
586
//----------------------------------------------------------------------
587
void
588
DateFormat::setCalendar(const Calendar& newCalendar)
589
0
{
590
0
    Calendar* newCalClone = newCalendar.clone();
591
0
    if (newCalClone != nullptr) {
592
0
        adoptCalendar(newCalClone);
593
0
    }
594
0
}
595
596
//----------------------------------------------------------------------
597
598
const Calendar*
599
DateFormat::getCalendar() const
600
0
{
601
0
    return fCalendar;
602
0
}
603
604
//----------------------------------------------------------------------
605
606
void
607
DateFormat::adoptNumberFormat(NumberFormat* newNumberFormat)
608
0
{
609
0
    delete fNumberFormat;
610
0
    fNumberFormat = newNumberFormat;
611
0
    newNumberFormat->setParseIntegerOnly(true);
612
0
    newNumberFormat->setGroupingUsed(false);
613
0
}
614
//----------------------------------------------------------------------
615
616
void
617
DateFormat::setNumberFormat(const NumberFormat& newNumberFormat)
618
0
{
619
0
    NumberFormat* newNumFmtClone = newNumberFormat.clone();
620
0
    if (newNumFmtClone != nullptr) {
621
0
        adoptNumberFormat(newNumFmtClone);
622
0
    }
623
0
}
624
625
//----------------------------------------------------------------------
626
627
const NumberFormat*
628
DateFormat::getNumberFormat() const
629
0
{
630
0
    return fNumberFormat;
631
0
}
632
633
//----------------------------------------------------------------------
634
635
void
636
DateFormat::adoptTimeZone(TimeZone* zone)
637
0
{
638
0
    if (fCalendar != nullptr) {
639
0
        fCalendar->adoptTimeZone(zone);
640
0
    }
641
0
}
642
//----------------------------------------------------------------------
643
644
void
645
DateFormat::setTimeZone(const TimeZone& zone)
646
0
{
647
0
    if (fCalendar != nullptr) {
648
0
        fCalendar->setTimeZone(zone);
649
0
    }
650
0
}
651
652
//----------------------------------------------------------------------
653
654
const TimeZone&
655
DateFormat::getTimeZone() const
656
0
{
657
0
    if (fCalendar != nullptr) {
658
0
        return fCalendar->getTimeZone();
659
0
    }
660
    // If calendar doesn't exists, create default timezone.
661
    // fCalendar is rarely null
662
0
    return *(TimeZone::createDefault());
663
0
}
664
665
//----------------------------------------------------------------------
666
667
void
668
DateFormat::setLenient(UBool lenient)
669
0
{
670
0
    if (fCalendar != nullptr) {
671
0
        fCalendar->setLenient(lenient);
672
0
    }
673
0
    UErrorCode status = U_ZERO_ERROR;
674
0
    setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, lenient, status);
675
0
    setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, lenient, status);
676
0
}
677
678
//----------------------------------------------------------------------
679
680
UBool
681
DateFormat::isLenient() const
682
0
{
683
0
    UBool lenient = true;
684
0
    if (fCalendar != nullptr) {
685
0
        lenient = fCalendar->isLenient();
686
0
    }
687
0
    UErrorCode status = U_ZERO_ERROR;
688
0
    return lenient
689
0
        && getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status)
690
0
        && getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status);
691
0
}
692
693
void
694
DateFormat::setCalendarLenient(UBool lenient)
695
0
{
696
0
    if (fCalendar != nullptr) {
697
0
        fCalendar->setLenient(lenient);
698
0
    }
699
0
}
700
701
//----------------------------------------------------------------------
702
703
UBool
704
DateFormat::isCalendarLenient() const
705
0
{
706
0
    if (fCalendar != nullptr) {
707
0
        return fCalendar->isLenient();
708
0
    }
709
    // fCalendar is rarely null
710
0
    return false;
711
0
}
712
713
714
//----------------------------------------------------------------------
715
716
717
void DateFormat::setContext(UDisplayContext value, UErrorCode& status)
718
2.41k
{
719
2.41k
    if (U_FAILURE(status))
720
0
        return;
721
2.41k
    if (static_cast<UDisplayContextType>(static_cast<uint32_t>(value) >> 8) == UDISPCTX_TYPE_CAPITALIZATION) {
722
2.41k
        fCapitalizationContext = value;
723
2.41k
    } else {
724
0
        status = U_ILLEGAL_ARGUMENT_ERROR;
725
0
   }
726
2.41k
}
727
728
729
//----------------------------------------------------------------------
730
731
732
UDisplayContext DateFormat::getContext(UDisplayContextType type, UErrorCode& status) const
733
31.3k
{
734
31.3k
    if (U_FAILURE(status))
735
0
        return static_cast<UDisplayContext>(0);
736
31.3k
    if (type != UDISPCTX_TYPE_CAPITALIZATION) {
737
0
        status = U_ILLEGAL_ARGUMENT_ERROR;
738
0
        return static_cast<UDisplayContext>(0);
739
0
    }
740
31.3k
    return fCapitalizationContext;
741
31.3k
}
742
743
744
//----------------------------------------------------------------------
745
746
747
DateFormat& 
748
DateFormat::setBooleanAttribute(UDateFormatBooleanAttribute attr,
749
                      UBool newValue,
750
519k
                      UErrorCode &status) {
751
519k
    if(!fBoolFlags.isValidValue(newValue)) {
752
0
        status = U_ILLEGAL_ARGUMENT_ERROR;
753
519k
    } else {
754
519k
        fBoolFlags.set(attr, newValue);
755
519k
    }
756
757
519k
    return *this;
758
519k
}
759
760
//----------------------------------------------------------------------
761
762
UBool 
763
0
DateFormat::getBooleanAttribute(UDateFormatBooleanAttribute attr, UErrorCode &/*status*/) const {
764
765
0
    return fBoolFlags.get(attr);
766
0
}
767
768
U_NAMESPACE_END
769
770
#endif /* #if !UCONFIG_NO_FORMATTING */
771
772
//eof