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