Home | History | Annotate | Download | only in i18n
      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 
     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 
     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         U_ASSERT(false);
     98         break;
     99     }
    100 }
    101 
    102 TimeUnit::TimeUnit(const TimeUnit& other)
    103 :   MeasureUnit(other), fTimeUnitField(other.fTimeUnitField) {
    104 }
    105 
    106 UObject*
    107 TimeUnit::clone() const {
    108     return new TimeUnit(*this);
    109 }
    110 
    111 TimeUnit&
    112 TimeUnit::operator=(const TimeUnit& other) {
    113     if (this == &other) {
    114         return *this;
    115     }
    116     MeasureUnit::operator=(other);
    117     fTimeUnitField = other.fTimeUnitField;
    118     return *this;
    119 }
    120 
    121 TimeUnit::UTimeUnitFields
    122 TimeUnit::getTimeUnitField() const {
    123     return fTimeUnitField;
    124 }
    125 
    126 TimeUnit::~TimeUnit() {
    127 }
    128 
    129 
    130 U_NAMESPACE_END
    131 
    132 #endif
    133