Home | History | Annotate | Download | only in i18n
      1 /*
      2 *******************************************************************************
      3 * Copyright (C) 2003 - 2009, 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 const UDate     EthiopicCalendar::fgSystemDefaultCentury        = DBL_MIN;
    138 const int32_t   EthiopicCalendar::fgSystemDefaultCenturyYear    = -1;
    139 
    140 UDate           EthiopicCalendar::fgSystemDefaultCenturyStart       = DBL_MIN;
    141 int32_t         EthiopicCalendar::fgSystemDefaultCenturyStartYear   = -1;
    142 
    143 UDate
    144 EthiopicCalendar::defaultCenturyStart() const
    145 {
    146     initializeSystemDefaultCentury();
    147     return fgSystemDefaultCenturyStart;
    148 }
    149 
    150 int32_t
    151 EthiopicCalendar::defaultCenturyStartYear() const
    152 {
    153     initializeSystemDefaultCentury();
    154     if (isAmeteAlemEra()) {
    155         return fgSystemDefaultCenturyStartYear + AMETE_MIHRET_DELTA;
    156     }
    157     return fgSystemDefaultCenturyStartYear;
    158 }
    159 
    160 void
    161 EthiopicCalendar::initializeSystemDefaultCentury()
    162 {
    163     // lazy-evaluate systemDefaultCenturyStart
    164     UBool needsUpdate;
    165     UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
    166 
    167     if (!needsUpdate) {
    168         return;
    169     }
    170 
    171     UErrorCode status = U_ZERO_ERROR;
    172 
    173     EthiopicCalendar calendar(Locale("@calendar=ethiopic"), status);
    174     if (U_SUCCESS(status)) {
    175         calendar.setTime(Calendar::getNow(), status);
    176         calendar.add(UCAL_YEAR, -80, status);
    177         UDate    newStart = calendar.getTime(status);
    178         int32_t  newYear  = calendar.get(UCAL_YEAR, status);
    179         {
    180             umtx_lock(NULL);
    181             fgSystemDefaultCenturyStartYear = newYear;
    182             fgSystemDefaultCenturyStart = newStart;
    183             umtx_unlock(NULL);
    184         }
    185     }
    186     // We have no recourse upon failure unless we want to propagate the failure
    187     // out.
    188 }
    189 
    190 int32_t
    191 EthiopicCalendar::getJDEpochOffset() const
    192 {
    193     return JD_EPOCH_OFFSET_AMETE_MIHRET;
    194 }
    195 
    196 
    197 #if 0
    198 // We do not want to introduce this API in ICU4C.
    199 // It was accidentally introduced in ICU4J as a public API.
    200 
    201 //-------------------------------------------------------------------------
    202 // Calendar system Conversion methods...
    203 //-------------------------------------------------------------------------
    204 
    205 int32_t
    206 EthiopicCalendar::ethiopicToJD(int32_t year, int32_t month, int32_t date)
    207 {
    208     return ceToJD(year, month, date, JD_EPOCH_OFFSET_AMETE_MIHRET);
    209 }
    210 #endif
    211 
    212 U_NAMESPACE_END
    213 
    214 #endif
    215