summaryrefslogtreecommitdiffstats
path: root/intl/icu/source/i18n/tmunit.cpp
blob: ffa67eddeb3a493a3b07b40f5652aba3afb551fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
 *******************************************************************************
 * Copyright (C) 2008-2014, Google, International Business Machines Corporation and
 * others. All Rights Reserved.
 *******************************************************************************
 */

#include "unicode/tmunit.h"
#include "uassert.h"

#if !UCONFIG_NO_FORMATTING

U_NAMESPACE_BEGIN

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeUnit)


/*
 * There are only 7 time units.
 * So, TimeUnit could be made as singleton 
 * (similar to uniset_props.cpp, or unorm.cpp,
 * in which a static TimeUnit* array is created, and 
 * the creatInstance() returns a const TimeUnit*).
 * But the constraint is TimeUnit is a data member of Measure.
 * But Measure (which is an existing API) does not expect it's "unit" member
 * as singleton. Meaure takes ownership of the "unit" member.
 * In its constructor, it does not take a const "unit" pointer.
 * Also, Measure can clone and destruct the "unit" pointer.
 * In order to preserve the old behavior and let Measure handle singleton "unit",  
 * 1. a flag need to be added in Measure; 
 * 2. a new constructor which takes const "unit" as parameter need to be added,
 *    and this new constructor will set the flag on.
 * 3. clone and destructor need to check upon this flag to distinguish on how
 *    to handle the "unit". 
 * 
 * Since TimeUnit is such a light weight object, comparing with the heavy weight
 * format operation, we decided to avoid the above complication.
 * 
 * So, both TimeUnit and CurrencyUnit (the 2 subclasses of MeasureUnit) are
 * immutable and non-singleton.
 *
 * Currently, TimeUnitAmount and CurrencyAmount are immutable.
 * If an application needs to create a long list of TimeUnitAmount on the same
 * time unit but different number, for example,
 * 1 hour, 2 hour, 3 hour, ................. 10,000 hour,
 * there might be performance hit because 10,000 TimeUnit object, 
 * although all are the same time unit, will be created in heap and deleted.
 *
 * To address this performance issue, if there is any in the future,
 * we should and need to change TimeUnitAmount and CurrencyAmount to be 
 * immutable by allowing a setter on the number.
 * Or we need to add 2 parallel mutable classes in order to 
 * preserve the existing API.
 * Or we can use freezable.
 */
TimeUnit* U_EXPORT2 
TimeUnit::createInstance(TimeUnit::UTimeUnitFields timeUnitField, 
                         UErrorCode& status) {
    if (U_FAILURE(status)) {
        return nullptr;
    }
    if (timeUnitField < 0 || timeUnitField >= UTIMEUNIT_FIELD_COUNT) {
        status = U_ILLEGAL_ARGUMENT_ERROR;
        return nullptr;
    }
    return new TimeUnit(timeUnitField);
}


TimeUnit::TimeUnit(TimeUnit::UTimeUnitFields timeUnitField) {
    fTimeUnitField = timeUnitField;
    switch (fTimeUnitField) {
    case UTIMEUNIT_YEAR:
        initTime("year");
        break;
    case UTIMEUNIT_MONTH:
        initTime("month");
        break;
    case UTIMEUNIT_DAY:
        initTime("day");
        break;
    case UTIMEUNIT_WEEK:
        initTime("week");
        break;
    case UTIMEUNIT_HOUR:
        initTime("hour");
        break;
    case UTIMEUNIT_MINUTE:
        initTime("minute");
        break;
    case UTIMEUNIT_SECOND:
        initTime("second");
        break;
    default:
        UPRV_UNREACHABLE_EXIT;
    }
}

TimeUnit::TimeUnit(const TimeUnit& other) 
:   MeasureUnit(other), fTimeUnitField(other.fTimeUnitField) {
}

TimeUnit* 
TimeUnit::clone() const {
    return new TimeUnit(*this);
}

TimeUnit&
TimeUnit::operator=(const TimeUnit& other) {
    if (this == &other) {
        return *this;
    }
    MeasureUnit::operator=(other);
    fTimeUnitField = other.fTimeUnitField;
    return *this;
}

TimeUnit::UTimeUnitFields
TimeUnit::getTimeUnitField() const {
    return fTimeUnitField;
}

TimeUnit::~TimeUnit() {
}


U_NAMESPACE_END

#endif