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 nullptr;
63 }
64 if (timeUnitField < 0 || timeUnitField >= UTIMEUNIT_FIELD_COUNT) {
65 status = U_ILLEGAL_ARGUMENT_ERROR;
66 return nullptr;
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_EXIT;
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