tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

japancal.cpp (9704B)


      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-2009,2012,2016 International Business Machines Corporation and
      6 * others. All Rights Reserved.
      7 *******************************************************************************
      8 *
      9 * File JAPANCAL.CPP
     10 *
     11 * Modification History:
     12 *  05/16/2003    srl     copied from buddhcal.cpp
     13 *
     14 */
     15 
     16 #include "unicode/utypes.h"
     17 
     18 #if !UCONFIG_NO_FORMATTING
     19 #if U_PLATFORM_HAS_WINUWP_API == 0
     20 #include <stdlib.h> // getenv() is not available in UWP env
     21 #else
     22 #ifndef WIN32_LEAN_AND_MEAN
     23 #   define WIN32_LEAN_AND_MEAN
     24 #endif
     25 #   define VC_EXTRALEAN
     26 #   define NOUSER
     27 #   define NOSERVICE
     28 #   define NOIME
     29 #   define NOMCX
     30 #include <windows.h>
     31 #endif
     32 #include "cmemory.h"
     33 #include "erarules.h"
     34 #include "japancal.h"
     35 #include "unicode/gregocal.h"
     36 #include "umutex.h"
     37 #include "uassert.h"
     38 #include "ucln_in.h"
     39 #include "cstring.h"
     40 
     41 static icu::EraRules * gJapaneseEraRules = nullptr;
     42 static icu::UInitOnce gJapaneseEraRulesInitOnce {};
     43 static int32_t gCurrentEra = 0;
     44 
     45 U_CDECL_BEGIN
     46 static UBool japanese_calendar_cleanup() {
     47    if (gJapaneseEraRules) {
     48        delete gJapaneseEraRules;
     49        gJapaneseEraRules = nullptr;
     50    }
     51    gCurrentEra = 0;
     52    gJapaneseEraRulesInitOnce.reset();
     53    return true;
     54 }
     55 U_CDECL_END
     56 
     57 U_NAMESPACE_BEGIN
     58 
     59 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(JapaneseCalendar)
     60 
     61 static const int32_t kGregorianEpoch = 1970;    // used as the default value of EXTENDED_YEAR
     62 static const char* TENTATIVE_ERA_VAR_NAME = "ICU_ENABLE_TENTATIVE_ERA";
     63 
     64 
     65 // Export the following for use by test code.
     66 UBool JapaneseCalendar::enableTentativeEra() {
     67    // Although start date of next Japanese era is planned ahead, a name of
     68    // new era might not be available. This implementation allows tester to
     69    // check a new era without era names by settings below (in priority order).
     70    // By default, such tentative era is disabled.
     71 
     72    // 1. Environment variable ICU_ENABLE_TENTATIVE_ERA=true or false
     73 
     74    UBool includeTentativeEra = false;
     75 
     76 #if U_PLATFORM_HAS_WINUWP_API == 1
     77    // UWP doesn't allow access to getenv(), but we can call GetEnvironmentVariableW to do the same thing.
     78    char16_t varName[26] = {};
     79    u_charsToUChars(TENTATIVE_ERA_VAR_NAME, varName, static_cast<int32_t>(uprv_strlen(TENTATIVE_ERA_VAR_NAME)));
     80    WCHAR varValue[5] = {};
     81    DWORD ret = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(varName), varValue, UPRV_LENGTHOF(varValue));
     82    if ((ret == 4) && (_wcsicmp(varValue, L"true") == 0)) {
     83        includeTentativeEra = true;
     84    }
     85 #else
     86    char *envVarVal = getenv(TENTATIVE_ERA_VAR_NAME);
     87    if (envVarVal != nullptr && uprv_stricmp(envVarVal, "true") == 0) {
     88        includeTentativeEra = true;
     89    }
     90 #endif
     91    return includeTentativeEra;
     92 }
     93 
     94 
     95 // Initialize global Japanese era data
     96 static void U_CALLCONV initializeEras(UErrorCode &status) {
     97    gJapaneseEraRules = EraRules::createInstance("japanese", JapaneseCalendar::enableTentativeEra(), status);
     98    if (U_FAILURE(status)) {
     99        return;
    100    }
    101    gCurrentEra = gJapaneseEraRules->getCurrentEraCode();
    102 }
    103 
    104 static void init(UErrorCode &status) {
    105    umtx_initOnce(gJapaneseEraRulesInitOnce, &initializeEras, status);
    106    ucln_i18n_registerCleanup(UCLN_I18N_JAPANESE_CALENDAR, japanese_calendar_cleanup);
    107 }
    108 
    109 /* Some platforms don't like to export constants, like old Palm OS and some z/OS configurations. */
    110 uint32_t JapaneseCalendar::getCurrentEra() {
    111    return gCurrentEra;
    112 }
    113 
    114 JapaneseCalendar::JapaneseCalendar(const Locale& aLocale, UErrorCode& success)
    115 :   GregorianCalendar(aLocale, success)
    116 {
    117    init(success);
    118 }
    119 
    120 JapaneseCalendar::~JapaneseCalendar()
    121 {
    122 }
    123 
    124 JapaneseCalendar::JapaneseCalendar(const JapaneseCalendar& source)
    125 : GregorianCalendar(source)
    126 {
    127    UErrorCode status = U_ZERO_ERROR;
    128    init(status);
    129    U_ASSERT(U_SUCCESS(status));
    130 }
    131 
    132 JapaneseCalendar* JapaneseCalendar::clone() const
    133 {
    134    return new JapaneseCalendar(*this);
    135 }
    136 
    137 const char *JapaneseCalendar::getType() const
    138 {
    139    return "japanese";
    140 }
    141 
    142 int32_t JapaneseCalendar::getDefaultMonthInYear(int32_t eyear, UErrorCode& status) 
    143 {
    144    if (U_FAILURE(status)) {
    145      return 0;
    146    }
    147    int32_t era = internalGetEra();
    148    // TODO do we assume we can trust 'era'?  What if it is denormalized?
    149 
    150    int32_t month = 0;
    151 
    152    // Find out if we are at the edge of an era
    153    int32_t eraStart[3] = { 0,0,0 };
    154    gJapaneseEraRules->getStartDate(era, eraStart, status);
    155    if (U_FAILURE(status)) {
    156        return 0;
    157    }
    158    if(eyear == eraStart[0]) {
    159        // Yes, we're in the first year of this era.
    160        return eraStart[1]  // month
    161                -1;         // return 0-based month
    162    }
    163 
    164    return month;
    165 }
    166 
    167 int32_t JapaneseCalendar::getDefaultDayInMonth(int32_t eyear, int32_t month, UErrorCode& status) 
    168 {
    169    if (U_FAILURE(status)) {
    170        return 0;
    171    }
    172    int32_t era = internalGetEra();
    173    int32_t day = 1;
    174 
    175    int32_t eraStart[3] = { 0,0,0 };
    176    gJapaneseEraRules->getStartDate(era, eraStart, status);
    177    if (U_FAILURE(status)) {
    178        return 0;
    179    }
    180    if (eyear == eraStart[0] && (month == eraStart[1] - 1)) {
    181        return eraStart[2];
    182    }
    183    return day;
    184 }
    185 
    186 
    187 int32_t JapaneseCalendar::internalGetEra() const
    188 {
    189    return internalGet(UCAL_ERA, gCurrentEra);
    190 }
    191 
    192 int32_t JapaneseCalendar::handleGetExtendedYear(UErrorCode& status)
    193 {
    194    if (U_FAILURE(status)) {
    195        return 0;
    196    }
    197    // EXTENDED_YEAR in JapaneseCalendar is a Gregorian year
    198    // The default value of EXTENDED_YEAR is 1970 (Showa 45)
    199 
    200    if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR &&
    201        newerField(UCAL_EXTENDED_YEAR, UCAL_ERA) == UCAL_EXTENDED_YEAR) {
    202        return internalGet(UCAL_EXTENDED_YEAR, kGregorianEpoch);
    203    }
    204    int32_t eraStartYear = gJapaneseEraRules->getStartYear(internalGet(UCAL_ERA, gCurrentEra), status);
    205    if (U_FAILURE(status)) {
    206        return 0;
    207    }
    208 
    209    // extended year is a gregorian year, where 1 = 1AD,  0 = 1BC, -1 = 2BC, etc
    210    int32_t year = internalGet(UCAL_YEAR, 1);   // pin to minimum of year 1 (first year)
    211    // add gregorian starting year, subtract one because year starts at 1
    212    if (uprv_add32_overflow(year, eraStartYear - 1,  &year)) {
    213        status = U_ILLEGAL_ARGUMENT_ERROR;
    214        return 0;
    215    }
    216    return year;
    217 }
    218 
    219 
    220 void JapaneseCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status)
    221 {
    222    //Calendar::timeToFields(theTime, quick, status);
    223    GregorianCalendar::handleComputeFields(julianDay, status);
    224    int32_t year = internalGet(UCAL_EXTENDED_YEAR); // Gregorian year
    225    int32_t eraCode = gJapaneseEraRules->getEraCode(year, internalGetMonth(status) + 1, internalGet(UCAL_DAY_OF_MONTH), status);
    226 
    227    int32_t startYear = gJapaneseEraRules->getStartYear(eraCode, status) - 1;
    228    if (U_FAILURE(status)) {
    229        return;
    230    }
    231    if (uprv_add32_overflow(year, -startYear,  &year)) {
    232        status = U_ILLEGAL_ARGUMENT_ERROR;
    233        return;
    234    }
    235    internalSet(UCAL_ERA, eraCode);
    236    internalSet(UCAL_YEAR, year);
    237 }
    238 
    239 /*
    240 Disable pivoting 
    241 */
    242 UBool JapaneseCalendar::haveDefaultCentury() const
    243 {
    244    return false;
    245 }
    246 
    247 UDate JapaneseCalendar::defaultCenturyStart() const
    248 {
    249    return 0;// WRONG
    250 }
    251 
    252 int32_t JapaneseCalendar::defaultCenturyStartYear() const
    253 {
    254    return 0;
    255 }
    256 
    257 int32_t JapaneseCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const
    258 {
    259    switch(field) {
    260    case UCAL_ERA:
    261        if (limitType == UCAL_LIMIT_MINIMUM || limitType == UCAL_LIMIT_GREATEST_MINIMUM) {
    262            return 0;
    263        }
    264        return gJapaneseEraRules->getMaxEraCode(); // max known era, not gCurrentEra
    265    case UCAL_YEAR:
    266        {
    267            switch (limitType) {
    268            case UCAL_LIMIT_MINIMUM:
    269            case UCAL_LIMIT_GREATEST_MINIMUM:
    270                return 1;
    271            case UCAL_LIMIT_LEAST_MAXIMUM:
    272                return 1;
    273            case  UCAL_LIMIT_COUNT: //added to avoid warning
    274            case UCAL_LIMIT_MAXIMUM:
    275            {
    276                UErrorCode status = U_ZERO_ERROR;
    277                int32_t eraStartYear = gJapaneseEraRules->getStartYear(gCurrentEra, status);
    278                U_ASSERT(U_SUCCESS(status));
    279                return GregorianCalendar::handleGetLimit(UCAL_YEAR, UCAL_LIMIT_MAXIMUM) - eraStartYear;
    280            }
    281            default:
    282                return 1;    // Error condition, invalid limitType
    283            }
    284        }
    285    default:
    286        return GregorianCalendar::handleGetLimit(field,limitType);
    287    }
    288 }
    289 
    290 int32_t JapaneseCalendar::getActualMaximum(UCalendarDateFields field, UErrorCode& status) const {
    291    if (field != UCAL_YEAR) {
    292        return GregorianCalendar::getActualMaximum(field, status);
    293    }
    294    int32_t era = get(UCAL_ERA, status);
    295    if (U_FAILURE(status)) {
    296        return 0; // error case... any value
    297    }
    298    if (era == gJapaneseEraRules->getMaxEraCode()) { // max known era, not gCurrentEra
    299        // TODO: Investigate what value should be used here - revisit after 4.0.
    300        return handleGetLimit(UCAL_YEAR, UCAL_LIMIT_MAXIMUM);
    301    }
    302    int32_t nextEraStart[3] = { 0,0,0 };
    303    gJapaneseEraRules->getStartDate(era + 1, nextEraStart, status);
    304    int32_t nextEraYear = nextEraStart[0];
    305    int32_t nextEraMonth = nextEraStart[1]; // 1-base
    306    int32_t nextEraDate = nextEraStart[2];
    307 
    308    int32_t eraStartYear = gJapaneseEraRules->getStartYear(era, status);
    309    int32_t maxYear = nextEraYear - eraStartYear + 1;   // 1-base
    310    if (nextEraMonth == 1 && nextEraDate == 1) {
    311        // Subtract 1, because the next era starts at Jan 1
    312        maxYear--;
    313    }
    314    return maxYear;
    315 }
    316 
    317 U_NAMESPACE_END
    318 
    319 #endif