1 /*
2  *******************************************************************************
3  * Copyright (C) 2008-2014, Google, International Business Machines Corporation and
4  * others. All Rights Reserved.
5  *******************************************************************************
6  */
7 
8 #include "unicode/tmunit.h"
9 #include "uassert.h"
10 
11 #if !UCONFIG_NO_FORMATTING
12 
13 U_NAMESPACE_BEGIN
14 
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeUnit)15 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeUnit)
16 
17 
18 /*
19  * There are only 7 time units.
20  * So, TimeUnit could be made as singleton
21  * (similar to uniset_props.cpp, or unorm.cpp,
22  * in which a static TimeUnit* array is created, and
23  * the creatInstance() returns a const TimeUnit*).
24  * But the constraint is TimeUnit is a data member of Measure.
25  * But Measure (which is an existing API) does not expect it's "unit" member
26  * as singleton. Meaure takes ownership of the "unit" member.
27  * In its constructor, it does not take a const "unit" pointer.
28  * Also, Measure can clone and destruct the "unit" pointer.
29  * In order to preserve the old behavior and let Measure handle singleton "unit",
30  * 1. a flag need to be added in Measure;
31  * 2. a new constructor which takes const "unit" as parameter need to be added,
32  *    and this new constructor will set the flag on.
33  * 3. clone and destructor need to check upon this flag to distinguish on how
34  *    to handle the "unit".
35  *
36  * Since TimeUnit is such a light weight object, comparing with the heavy weight
37  * format operation, we decided to avoid the above complication.
38  *
39  * So, both TimeUnit and CurrencyUnit (the 2 subclasses of MeasureUnit) are
40  * immutable and non-singleton.
41  *
42  * Currently, TimeUnitAmount and CurrencyAmount are immutable.
43  * If an application needs to create a long list of TimeUnitAmount on the same
44  * time unit but different number, for example,
45  * 1 hour, 2 hour, 3 hour, ................. 10,000 hour,
46  * there might be performance hit because 10,000 TimeUnit object,
47  * although all are the same time unit, will be created in heap and deleted.
48  *
49  * To address this performance issue, if there is any in the future,
50  * we should and need to change TimeUnitAmount and CurrencyAmount to be
51  * immutable by allowing a setter on the number.
52  * Or we need to add 2 parallel mutable classes in order to
53  * preserve the existing API.
54  * Or we can use freezable.
55  */
56 TimeUnit* U_EXPORT2
57 TimeUnit::createInstance(TimeUnit::UTimeUnitFields timeUnitField,
58                          UErrorCode& status) {
59     if (U_FAILURE(status)) {
60         return NULL;
61     }
62     if (timeUnitField < 0 || timeUnitField >= UTIMEUNIT_FIELD_COUNT) {
63         status = U_ILLEGAL_ARGUMENT_ERROR;
64         return NULL;
65     }
66     return new TimeUnit(timeUnitField);
67 }
68 
69 
TimeUnit(TimeUnit::UTimeUnitFields timeUnitField)70 TimeUnit::TimeUnit(TimeUnit::UTimeUnitFields timeUnitField) {
71     fTimeUnitField = timeUnitField;
72     switch (fTimeUnitField) {
73     case UTIMEUNIT_YEAR:
74         initTime("year");
75         break;
76     case UTIMEUNIT_MONTH:
77         initTime("month");
78         break;
79     case UTIMEUNIT_DAY:
80         initTime("day");
81         break;
82     case UTIMEUNIT_WEEK:
83         initTime("week");
84         break;
85     case UTIMEUNIT_HOUR:
86         initTime("hour");
87         break;
88     case UTIMEUNIT_MINUTE:
89         initTime("minute");
90         break;
91     case UTIMEUNIT_SECOND:
92         initTime("second");
93         break;
94     default:
95         U_ASSERT(false);
96         break;
97     }
98 }
99 
TimeUnit(const TimeUnit & other)100 TimeUnit::TimeUnit(const TimeUnit& other)
101 :   MeasureUnit(other), fTimeUnitField(other.fTimeUnitField) {
102 }
103 
104 UObject*
clone() const105 TimeUnit::clone() const {
106     return new TimeUnit(*this);
107 }
108 
109 TimeUnit&
operator =(const TimeUnit & other)110 TimeUnit::operator=(const TimeUnit& other) {
111     if (this == &other) {
112         return *this;
113     }
114     MeasureUnit::operator=(other);
115     fTimeUnitField = other.fTimeUnitField;
116     return *this;
117 }
118 
119 TimeUnit::UTimeUnitFields
getTimeUnitField() const120 TimeUnit::getTimeUnitField() const {
121     return fTimeUnitField;
122 }
123 
~TimeUnit()124 TimeUnit::~TimeUnit() {
125 }
126 
127 
128 U_NAMESPACE_END
129 
130 #endif
131