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