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) 2003 - 2013, International Business Machines Corporation and
      6 * others. All Rights Reserved.
      7 *******************************************************************************
      8 */
      9 
     10 #include "unicode/utypes.h"
     11 
     12 #if !UCONFIG_NO_FORMATTING
     13 
     14 #include "umutex.h"
     15 #include "ethpccal.h"
     16 #include "cecal.h"
     17 #include <float.h>
     18 
     19 U_NAMESPACE_BEGIN
     20 
     21 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(EthiopicCalendar)
     22 
     23 //static const int32_t JD_EPOCH_OFFSET_AMETE_ALEM = -285019;
     24 static const int32_t JD_EPOCH_OFFSET_AMETE_MIHRET = 1723856;
     25 static const int32_t AMETE_MIHRET_DELTA = 5500; // 5501 - 1 (Amete Alem 5501 = Amete Mihret 1)
     26 
     27 //-------------------------------------------------------------------------
     28 // Constructors...
     29 //-------------------------------------------------------------------------
     30 
     31 EthiopicCalendar::EthiopicCalendar(const Locale& aLocale,
     32                                    UErrorCode& success,
     33                                    EEraType type /*= AMETE_MIHRET_ERA*/)
     34 :   CECalendar(aLocale, success),
     35     eraType(type)
     36 {
     37 }
     38 
     39 EthiopicCalendar::EthiopicCalendar(const EthiopicCalendar& other)
     40 :   CECalendar(other),
     41     eraType(other.eraType)
     42 {
     43 }
     44 
     45 EthiopicCalendar::~EthiopicCalendar()
     46 {
     47 }
     48 
     49 Calendar*
     50 EthiopicCalendar::clone() const
     51 {
     52     return new EthiopicCalendar(*this);
     53 }
     54 
     55 const char *
     56 EthiopicCalendar::getType() const
     57 {
     58     if (isAmeteAlemEra()) {
     59         return "ethiopic-amete-alem";
     60     }
     61     return "ethiopic";
     62 }
     63 
     64 void
     65 EthiopicCalendar::setAmeteAlemEra(UBool onOff)
     66 {
     67     eraType = onOff ? AMETE_ALEM_ERA : AMETE_MIHRET_ERA;
     68 }
     69 
     70 UBool
     71 EthiopicCalendar::isAmeteAlemEra() const
     72 {
     73     return (eraType == AMETE_ALEM_ERA);
     74 }
     75 
     76 //-------------------------------------------------------------------------
     77 // Calendar framework
     78 //-------------------------------------------------------------------------
     79 
     80 int32_t
     81 EthiopicCalendar::handleGetExtendedYear()
     82 {
     83     // Ethiopic calendar uses EXTENDED_YEAR aligned to
     84     // Amelete Hihret year always.
     85     int32_t eyear;
     86     if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) {
     87         eyear = internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1
     88     } else if (isAmeteAlemEra()) {
     89         eyear = internalGet(UCAL_YEAR, 1 + AMETE_MIHRET_DELTA)
     90             - AMETE_MIHRET_DELTA; // Default to year 1 of Amelete Mihret
     91     } else {
     92         // The year defaults to the epoch start, the era to AMETE_MIHRET
     93         int32_t era = internalGet(UCAL_ERA, AMETE_MIHRET);
     94         if (era == AMETE_MIHRET) {
     95             eyear = internalGet(UCAL_YEAR, 1); // Default to year 1
     96         } else {
     97             eyear = internalGet(UCAL_YEAR, 1) - AMETE_MIHRET_DELTA;
     98         }
     99     }
    100     return eyear;
    101 }
    102 
    103 void
    104 EthiopicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &/*status*/)
    105 {
    106     int32_t eyear, month, day, era, year;
    107     jdToCE(julianDay, getJDEpochOffset(), eyear, month, day);
    108 
    109     if (isAmeteAlemEra()) {
    110         era = AMETE_ALEM;
    111         year = eyear + AMETE_MIHRET_DELTA;
    112     } else {
    113         if (eyear > 0) {
    114             era = AMETE_MIHRET;
    115             year = eyear;
    116         } else {
    117             era = AMETE_ALEM;
    118             year = eyear + AMETE_MIHRET_DELTA;
    119         }
    120     }
    121 
    122     internalSet(UCAL_EXTENDED_YEAR, eyear);
    123     internalSet(UCAL_ERA, era);
    124     internalSet(UCAL_YEAR, year);
    125     internalSet(UCAL_MONTH, month);
    126     internalSet(UCAL_DATE, day);
    127     internalSet(UCAL_DAY_OF_YEAR, (30 * month) + day);
    128 }
    129 
    130 int32_t
    131 EthiopicCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const
    132 {
    133     if (isAmeteAlemEra() && field == UCAL_ERA) {
    134         return 0; // Only one era in this mode, era is always 0
    135     }
    136     return CECalendar::handleGetLimit(field, limitType);
    137 }
    138 
    139 /**
    140  * The system maintains a static default century start date and Year.  They are
    141  * initialized the first time they are used.  Once the system default century date
    142  * and year are set, they do not change.
    143  */
    144 static UDate           gSystemDefaultCenturyStart       = DBL_MIN;
    145 static int32_t         gSystemDefaultCenturyStartYear   = -1;
    146 static icu::UInitOnce  gSystemDefaultCenturyInit        = U_INITONCE_INITIALIZER;
    147 
    148 static void U_CALLCONV initializeSystemDefaultCentury()
    149 {
    150     UErrorCode status = U_ZERO_ERROR;
    151     EthiopicCalendar calendar(Locale("@calendar=ethiopic"), status);
    152     if (U_SUCCESS(status)) {
    153         calendar.setTime(Calendar::getNow(), status);
    154         calendar.add(UCAL_YEAR, -80, status);
    155 
    156         gSystemDefaultCenturyStart = calendar.getTime(status);
    157         gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
    158     }
    159     // We have no recourse upon failure unless we want to propagate the failure
    160     // out.
    161 }
    162 
    163 UDate
    164 EthiopicCalendar::defaultCenturyStart() const
    165 {
    166     // lazy-evaluate systemDefaultCenturyStart
    167     umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
    168     return gSystemDefaultCenturyStart;
    169 }
    170 
    171 int32_t
    172 EthiopicCalendar::defaultCenturyStartYear() const
    173 {
    174     // lazy-evaluate systemDefaultCenturyStartYear
    175     umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
    176     if (isAmeteAlemEra()) {
    177         return gSystemDefaultCenturyStartYear + AMETE_MIHRET_DELTA;
    178     }
    179     return gSystemDefaultCenturyStartYear;
    180 }
    181 
    182 
    183 int32_t
    184 EthiopicCalendar::getJDEpochOffset() const
    185 {
    186     return JD_EPOCH_OFFSET_AMETE_MIHRET;
    187 }
    188 
    189 
    190 #if 0
    191 // We do not want to introduce this API in ICU4C.
    192 // It was accidentally introduced in ICU4J as a public API.
    193 
    194 //-------------------------------------------------------------------------
    195 // Calendar system Conversion methods...
    196 //-------------------------------------------------------------------------
    197 
    198 int32_t
    199 EthiopicCalendar::ethiopicToJD(int32_t year, int32_t month, int32_t date)
    200 {
    201     return ceToJD(year, month, date, JD_EPOCH_OFFSET_AMETE_MIHRET);
    202 }
    203 #endif
    204 
    205 U_NAMESPACE_END
    206 
    207 #endif
    208