12e5b6d6dSopenharmony_ci// © 2016 and later: Unicode, Inc. and others.
22e5b6d6dSopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html
32e5b6d6dSopenharmony_ci/*
42e5b6d6dSopenharmony_ci*******************************************************************************
52e5b6d6dSopenharmony_ci* Copyright (C) 2003-2009,2012,2016 International Business Machines Corporation and
62e5b6d6dSopenharmony_ci* others. All Rights Reserved.
72e5b6d6dSopenharmony_ci*******************************************************************************
82e5b6d6dSopenharmony_ci*
92e5b6d6dSopenharmony_ci* File JAPANCAL.CPP
102e5b6d6dSopenharmony_ci*
112e5b6d6dSopenharmony_ci* Modification History:
122e5b6d6dSopenharmony_ci*  05/16/2003    srl     copied from buddhcal.cpp
132e5b6d6dSopenharmony_ci*
142e5b6d6dSopenharmony_ci*/
152e5b6d6dSopenharmony_ci
162e5b6d6dSopenharmony_ci#include "unicode/utypes.h"
172e5b6d6dSopenharmony_ci
182e5b6d6dSopenharmony_ci#if !UCONFIG_NO_FORMATTING
192e5b6d6dSopenharmony_ci#if U_PLATFORM_HAS_WINUWP_API == 0
202e5b6d6dSopenharmony_ci#include <stdlib.h> // getenv() is not available in UWP env
212e5b6d6dSopenharmony_ci#else
222e5b6d6dSopenharmony_ci#ifndef WIN32_LEAN_AND_MEAN
232e5b6d6dSopenharmony_ci#   define WIN32_LEAN_AND_MEAN
242e5b6d6dSopenharmony_ci#endif
252e5b6d6dSopenharmony_ci#   define VC_EXTRALEAN
262e5b6d6dSopenharmony_ci#   define NOUSER
272e5b6d6dSopenharmony_ci#   define NOSERVICE
282e5b6d6dSopenharmony_ci#   define NOIME
292e5b6d6dSopenharmony_ci#   define NOMCX
302e5b6d6dSopenharmony_ci#include <windows.h>
312e5b6d6dSopenharmony_ci#endif
322e5b6d6dSopenharmony_ci#include "cmemory.h"
332e5b6d6dSopenharmony_ci#include "erarules.h"
342e5b6d6dSopenharmony_ci#include "japancal.h"
352e5b6d6dSopenharmony_ci#include "unicode/gregocal.h"
362e5b6d6dSopenharmony_ci#include "umutex.h"
372e5b6d6dSopenharmony_ci#include "uassert.h"
382e5b6d6dSopenharmony_ci#include "ucln_in.h"
392e5b6d6dSopenharmony_ci#include "cstring.h"
402e5b6d6dSopenharmony_ci
412e5b6d6dSopenharmony_cistatic icu::EraRules * gJapaneseEraRules = nullptr;
422e5b6d6dSopenharmony_cistatic icu::UInitOnce gJapaneseEraRulesInitOnce {};
432e5b6d6dSopenharmony_cistatic int32_t gCurrentEra = 0;
442e5b6d6dSopenharmony_ci
452e5b6d6dSopenharmony_ciU_CDECL_BEGIN
462e5b6d6dSopenharmony_cistatic UBool japanese_calendar_cleanup(void) {
472e5b6d6dSopenharmony_ci    if (gJapaneseEraRules) {
482e5b6d6dSopenharmony_ci        delete gJapaneseEraRules;
492e5b6d6dSopenharmony_ci        gJapaneseEraRules = nullptr;
502e5b6d6dSopenharmony_ci    }
512e5b6d6dSopenharmony_ci    gCurrentEra = 0;
522e5b6d6dSopenharmony_ci    gJapaneseEraRulesInitOnce.reset();
532e5b6d6dSopenharmony_ci    return true;
542e5b6d6dSopenharmony_ci}
552e5b6d6dSopenharmony_ciU_CDECL_END
562e5b6d6dSopenharmony_ci
572e5b6d6dSopenharmony_ciU_NAMESPACE_BEGIN
582e5b6d6dSopenharmony_ci
592e5b6d6dSopenharmony_ciUOBJECT_DEFINE_RTTI_IMPLEMENTATION(JapaneseCalendar)
602e5b6d6dSopenharmony_ci
612e5b6d6dSopenharmony_cistatic const int32_t kGregorianEpoch = 1970;    // used as the default value of EXTENDED_YEAR
622e5b6d6dSopenharmony_cistatic const char* TENTATIVE_ERA_VAR_NAME = "ICU_ENABLE_TENTATIVE_ERA";
632e5b6d6dSopenharmony_ci
642e5b6d6dSopenharmony_ci
652e5b6d6dSopenharmony_ci// Export the following for use by test code.
662e5b6d6dSopenharmony_ciUBool JapaneseCalendar::enableTentativeEra() {
672e5b6d6dSopenharmony_ci    // Although start date of next Japanese era is planned ahead, a name of
682e5b6d6dSopenharmony_ci    // new era might not be available. This implementation allows tester to
692e5b6d6dSopenharmony_ci    // check a new era without era names by settings below (in priority order).
702e5b6d6dSopenharmony_ci    // By default, such tentative era is disabled.
712e5b6d6dSopenharmony_ci
722e5b6d6dSopenharmony_ci    // 1. Environment variable ICU_ENABLE_TENTATIVE_ERA=true or false
732e5b6d6dSopenharmony_ci
742e5b6d6dSopenharmony_ci    UBool includeTentativeEra = false;
752e5b6d6dSopenharmony_ci
762e5b6d6dSopenharmony_ci#if U_PLATFORM_HAS_WINUWP_API == 1
772e5b6d6dSopenharmony_ci    // UWP doesn't allow access to getenv(), but we can call GetEnvironmentVariableW to do the same thing.
782e5b6d6dSopenharmony_ci    UChar varName[26] = {};
792e5b6d6dSopenharmony_ci    u_charsToUChars(TENTATIVE_ERA_VAR_NAME, varName, static_cast<int32_t>(uprv_strlen(TENTATIVE_ERA_VAR_NAME)));
802e5b6d6dSopenharmony_ci    WCHAR varValue[5] = {};
812e5b6d6dSopenharmony_ci    DWORD ret = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(varName), varValue, UPRV_LENGTHOF(varValue));
822e5b6d6dSopenharmony_ci    if ((ret == 4) && (_wcsicmp(varValue, L"true") == 0)) {
832e5b6d6dSopenharmony_ci        includeTentativeEra = true;
842e5b6d6dSopenharmony_ci    }
852e5b6d6dSopenharmony_ci#else
862e5b6d6dSopenharmony_ci    char *envVarVal = getenv(TENTATIVE_ERA_VAR_NAME);
872e5b6d6dSopenharmony_ci    if (envVarVal != NULL && uprv_stricmp(envVarVal, "true") == 0) {
882e5b6d6dSopenharmony_ci        includeTentativeEra = true;
892e5b6d6dSopenharmony_ci    }
902e5b6d6dSopenharmony_ci#endif
912e5b6d6dSopenharmony_ci    return includeTentativeEra;
922e5b6d6dSopenharmony_ci}
932e5b6d6dSopenharmony_ci
942e5b6d6dSopenharmony_ci
952e5b6d6dSopenharmony_ci// Initialize global Japanese era data
962e5b6d6dSopenharmony_cistatic void U_CALLCONV initializeEras(UErrorCode &status) {
972e5b6d6dSopenharmony_ci    gJapaneseEraRules = EraRules::createInstance("japanese", JapaneseCalendar::enableTentativeEra(), status);
982e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
992e5b6d6dSopenharmony_ci        return;
1002e5b6d6dSopenharmony_ci    }
1012e5b6d6dSopenharmony_ci    gCurrentEra = gJapaneseEraRules->getCurrentEraIndex();
1022e5b6d6dSopenharmony_ci}
1032e5b6d6dSopenharmony_ci
1042e5b6d6dSopenharmony_cistatic void init(UErrorCode &status) {
1052e5b6d6dSopenharmony_ci    umtx_initOnce(gJapaneseEraRulesInitOnce, &initializeEras, status);
1062e5b6d6dSopenharmony_ci    ucln_i18n_registerCleanup(UCLN_I18N_JAPANESE_CALENDAR, japanese_calendar_cleanup);
1072e5b6d6dSopenharmony_ci}
1082e5b6d6dSopenharmony_ci
1092e5b6d6dSopenharmony_ci/* Some platforms don't like to export constants, like old Palm OS and some z/OS configurations. */
1102e5b6d6dSopenharmony_ciuint32_t JapaneseCalendar::getCurrentEra() {
1112e5b6d6dSopenharmony_ci    return gCurrentEra;
1122e5b6d6dSopenharmony_ci}
1132e5b6d6dSopenharmony_ci
1142e5b6d6dSopenharmony_ciJapaneseCalendar::JapaneseCalendar(const Locale& aLocale, UErrorCode& success)
1152e5b6d6dSopenharmony_ci:   GregorianCalendar(aLocale, success)
1162e5b6d6dSopenharmony_ci{
1172e5b6d6dSopenharmony_ci    init(success);
1182e5b6d6dSopenharmony_ci    setTimeInMillis(getNow(), success); // Call this again now that the vtable is set up properly.
1192e5b6d6dSopenharmony_ci}
1202e5b6d6dSopenharmony_ci
1212e5b6d6dSopenharmony_ciJapaneseCalendar::~JapaneseCalendar()
1222e5b6d6dSopenharmony_ci{
1232e5b6d6dSopenharmony_ci}
1242e5b6d6dSopenharmony_ci
1252e5b6d6dSopenharmony_ciJapaneseCalendar::JapaneseCalendar(const JapaneseCalendar& source)
1262e5b6d6dSopenharmony_ci: GregorianCalendar(source)
1272e5b6d6dSopenharmony_ci{
1282e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
1292e5b6d6dSopenharmony_ci    init(status);
1302e5b6d6dSopenharmony_ci    U_ASSERT(U_SUCCESS(status));
1312e5b6d6dSopenharmony_ci}
1322e5b6d6dSopenharmony_ci
1332e5b6d6dSopenharmony_ciJapaneseCalendar& JapaneseCalendar::operator= ( const JapaneseCalendar& right)
1342e5b6d6dSopenharmony_ci{
1352e5b6d6dSopenharmony_ci    GregorianCalendar::operator=(right);
1362e5b6d6dSopenharmony_ci    return *this;
1372e5b6d6dSopenharmony_ci}
1382e5b6d6dSopenharmony_ci
1392e5b6d6dSopenharmony_ciJapaneseCalendar* JapaneseCalendar::clone() const
1402e5b6d6dSopenharmony_ci{
1412e5b6d6dSopenharmony_ci    return new JapaneseCalendar(*this);
1422e5b6d6dSopenharmony_ci}
1432e5b6d6dSopenharmony_ci
1442e5b6d6dSopenharmony_ciconst char *JapaneseCalendar::getType() const
1452e5b6d6dSopenharmony_ci{
1462e5b6d6dSopenharmony_ci    return "japanese";
1472e5b6d6dSopenharmony_ci}
1482e5b6d6dSopenharmony_ci
1492e5b6d6dSopenharmony_ciint32_t JapaneseCalendar::getDefaultMonthInYear(int32_t eyear)
1502e5b6d6dSopenharmony_ci{
1512e5b6d6dSopenharmony_ci    int32_t era = internalGetEra();
1522e5b6d6dSopenharmony_ci    // TODO do we assume we can trust 'era'?  What if it is denormalized?
1532e5b6d6dSopenharmony_ci
1542e5b6d6dSopenharmony_ci    int32_t month = 0;
1552e5b6d6dSopenharmony_ci
1562e5b6d6dSopenharmony_ci    // Find out if we are at the edge of an era
1572e5b6d6dSopenharmony_ci    int32_t eraStart[3] = { 0,0,0 };
1582e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
1592e5b6d6dSopenharmony_ci    gJapaneseEraRules->getStartDate(era, eraStart, status);
1602e5b6d6dSopenharmony_ci    U_ASSERT(U_SUCCESS(status));
1612e5b6d6dSopenharmony_ci    if(eyear == eraStart[0]) {
1622e5b6d6dSopenharmony_ci        // Yes, we're in the first year of this era.
1632e5b6d6dSopenharmony_ci        return eraStart[1]  // month
1642e5b6d6dSopenharmony_ci                -1;         // return 0-based month
1652e5b6d6dSopenharmony_ci    }
1662e5b6d6dSopenharmony_ci
1672e5b6d6dSopenharmony_ci    return month;
1682e5b6d6dSopenharmony_ci}
1692e5b6d6dSopenharmony_ci
1702e5b6d6dSopenharmony_ciint32_t JapaneseCalendar::getDefaultDayInMonth(int32_t eyear, int32_t month)
1712e5b6d6dSopenharmony_ci{
1722e5b6d6dSopenharmony_ci    int32_t era = internalGetEra();
1732e5b6d6dSopenharmony_ci    int32_t day = 1;
1742e5b6d6dSopenharmony_ci
1752e5b6d6dSopenharmony_ci    int32_t eraStart[3] = { 0,0,0 };
1762e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
1772e5b6d6dSopenharmony_ci    gJapaneseEraRules->getStartDate(era, eraStart, status);
1782e5b6d6dSopenharmony_ci    U_ASSERT(U_SUCCESS(status));
1792e5b6d6dSopenharmony_ci    if(eyear == eraStart[0]) {
1802e5b6d6dSopenharmony_ci        if(month == eraStart[1] - 1) {
1812e5b6d6dSopenharmony_ci            return eraStart[2];
1822e5b6d6dSopenharmony_ci        }
1832e5b6d6dSopenharmony_ci    }
1842e5b6d6dSopenharmony_ci
1852e5b6d6dSopenharmony_ci    return day;
1862e5b6d6dSopenharmony_ci}
1872e5b6d6dSopenharmony_ci
1882e5b6d6dSopenharmony_ci
1892e5b6d6dSopenharmony_ciint32_t JapaneseCalendar::internalGetEra() const
1902e5b6d6dSopenharmony_ci{
1912e5b6d6dSopenharmony_ci    return internalGet(UCAL_ERA, gCurrentEra);
1922e5b6d6dSopenharmony_ci}
1932e5b6d6dSopenharmony_ci
1942e5b6d6dSopenharmony_ciint32_t JapaneseCalendar::handleGetExtendedYear()
1952e5b6d6dSopenharmony_ci{
1962e5b6d6dSopenharmony_ci    // EXTENDED_YEAR in JapaneseCalendar is a Gregorian year
1972e5b6d6dSopenharmony_ci    // The default value of EXTENDED_YEAR is 1970 (Showa 45)
1982e5b6d6dSopenharmony_ci    int32_t year;
1992e5b6d6dSopenharmony_ci
2002e5b6d6dSopenharmony_ci    if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR &&
2012e5b6d6dSopenharmony_ci        newerField(UCAL_EXTENDED_YEAR, UCAL_ERA) == UCAL_EXTENDED_YEAR) {
2022e5b6d6dSopenharmony_ci        year = internalGet(UCAL_EXTENDED_YEAR, kGregorianEpoch);
2032e5b6d6dSopenharmony_ci    } else {
2042e5b6d6dSopenharmony_ci        UErrorCode status = U_ZERO_ERROR;
2052e5b6d6dSopenharmony_ci        int32_t eraStartYear = gJapaneseEraRules->getStartYear(internalGet(UCAL_ERA, gCurrentEra), status);
2062e5b6d6dSopenharmony_ci        U_ASSERT(U_SUCCESS(status));
2072e5b6d6dSopenharmony_ci
2082e5b6d6dSopenharmony_ci        // extended year is a gregorian year, where 1 = 1AD,  0 = 1BC, -1 = 2BC, etc
2092e5b6d6dSopenharmony_ci        year = internalGet(UCAL_YEAR, 1)    // pin to minimum of year 1 (first year)
2102e5b6d6dSopenharmony_ci            + eraStartYear                  // add gregorian starting year
2112e5b6d6dSopenharmony_ci            - 1;                            // Subtract one because year starts at 1
2122e5b6d6dSopenharmony_ci    }
2132e5b6d6dSopenharmony_ci    return year;
2142e5b6d6dSopenharmony_ci}
2152e5b6d6dSopenharmony_ci
2162e5b6d6dSopenharmony_ci
2172e5b6d6dSopenharmony_civoid JapaneseCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status)
2182e5b6d6dSopenharmony_ci{
2192e5b6d6dSopenharmony_ci    //Calendar::timeToFields(theTime, quick, status);
2202e5b6d6dSopenharmony_ci    GregorianCalendar::handleComputeFields(julianDay, status);
2212e5b6d6dSopenharmony_ci    int32_t year = internalGet(UCAL_EXTENDED_YEAR); // Gregorian year
2222e5b6d6dSopenharmony_ci    int32_t eraIdx = gJapaneseEraRules->getEraIndex(year, internalGet(UCAL_MONTH) + 1, internalGet(UCAL_DAY_OF_MONTH), status);
2232e5b6d6dSopenharmony_ci
2242e5b6d6dSopenharmony_ci    internalSet(UCAL_ERA, eraIdx);
2252e5b6d6dSopenharmony_ci    internalSet(UCAL_YEAR, year - gJapaneseEraRules->getStartYear(eraIdx, status) + 1);
2262e5b6d6dSopenharmony_ci}
2272e5b6d6dSopenharmony_ci
2282e5b6d6dSopenharmony_ci/*
2292e5b6d6dSopenharmony_ciDisable pivoting
2302e5b6d6dSopenharmony_ci*/
2312e5b6d6dSopenharmony_ciUBool JapaneseCalendar::haveDefaultCentury() const
2322e5b6d6dSopenharmony_ci{
2332e5b6d6dSopenharmony_ci    return false;
2342e5b6d6dSopenharmony_ci}
2352e5b6d6dSopenharmony_ci
2362e5b6d6dSopenharmony_ciUDate JapaneseCalendar::defaultCenturyStart() const
2372e5b6d6dSopenharmony_ci{
2382e5b6d6dSopenharmony_ci    return 0;// WRONG
2392e5b6d6dSopenharmony_ci}
2402e5b6d6dSopenharmony_ci
2412e5b6d6dSopenharmony_ciint32_t JapaneseCalendar::defaultCenturyStartYear() const
2422e5b6d6dSopenharmony_ci{
2432e5b6d6dSopenharmony_ci    return 0;
2442e5b6d6dSopenharmony_ci}
2452e5b6d6dSopenharmony_ci
2462e5b6d6dSopenharmony_ciint32_t JapaneseCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const
2472e5b6d6dSopenharmony_ci{
2482e5b6d6dSopenharmony_ci    switch(field) {
2492e5b6d6dSopenharmony_ci    case UCAL_ERA:
2502e5b6d6dSopenharmony_ci        if (limitType == UCAL_LIMIT_MINIMUM || limitType == UCAL_LIMIT_GREATEST_MINIMUM) {
2512e5b6d6dSopenharmony_ci            return 0;
2522e5b6d6dSopenharmony_ci        }
2532e5b6d6dSopenharmony_ci        return gJapaneseEraRules->getNumberOfEras() - 1; // max known era, not gCurrentEra
2542e5b6d6dSopenharmony_ci    case UCAL_YEAR:
2552e5b6d6dSopenharmony_ci        {
2562e5b6d6dSopenharmony_ci            switch (limitType) {
2572e5b6d6dSopenharmony_ci            case UCAL_LIMIT_MINIMUM:
2582e5b6d6dSopenharmony_ci            case UCAL_LIMIT_GREATEST_MINIMUM:
2592e5b6d6dSopenharmony_ci                return 1;
2602e5b6d6dSopenharmony_ci            case UCAL_LIMIT_LEAST_MAXIMUM:
2612e5b6d6dSopenharmony_ci                return 1;
2622e5b6d6dSopenharmony_ci            case  UCAL_LIMIT_COUNT: //added to avoid warning
2632e5b6d6dSopenharmony_ci            case UCAL_LIMIT_MAXIMUM:
2642e5b6d6dSopenharmony_ci            {
2652e5b6d6dSopenharmony_ci                UErrorCode status = U_ZERO_ERROR;
2662e5b6d6dSopenharmony_ci                int32_t eraStartYear = gJapaneseEraRules->getStartYear(gCurrentEra, status);
2672e5b6d6dSopenharmony_ci                U_ASSERT(U_SUCCESS(status));
2682e5b6d6dSopenharmony_ci                return GregorianCalendar::handleGetLimit(UCAL_YEAR, UCAL_LIMIT_MAXIMUM) - eraStartYear;
2692e5b6d6dSopenharmony_ci            }
2702e5b6d6dSopenharmony_ci            default:
2712e5b6d6dSopenharmony_ci                return 1;    // Error condition, invalid limitType
2722e5b6d6dSopenharmony_ci            }
2732e5b6d6dSopenharmony_ci        }
2742e5b6d6dSopenharmony_ci    default:
2752e5b6d6dSopenharmony_ci        return GregorianCalendar::handleGetLimit(field,limitType);
2762e5b6d6dSopenharmony_ci    }
2772e5b6d6dSopenharmony_ci}
2782e5b6d6dSopenharmony_ci
2792e5b6d6dSopenharmony_ciint32_t JapaneseCalendar::getActualMaximum(UCalendarDateFields field, UErrorCode& status) const {
2802e5b6d6dSopenharmony_ci    if (field == UCAL_YEAR) {
2812e5b6d6dSopenharmony_ci        int32_t era = get(UCAL_ERA, status);
2822e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
2832e5b6d6dSopenharmony_ci            return 0; // error case... any value
2842e5b6d6dSopenharmony_ci        }
2852e5b6d6dSopenharmony_ci        if (era == gJapaneseEraRules->getNumberOfEras() - 1) { // max known era, not gCurrentEra
2862e5b6d6dSopenharmony_ci            // TODO: Investigate what value should be used here - revisit after 4.0.
2872e5b6d6dSopenharmony_ci            return handleGetLimit(UCAL_YEAR, UCAL_LIMIT_MAXIMUM);
2882e5b6d6dSopenharmony_ci        } else {
2892e5b6d6dSopenharmony_ci            int32_t nextEraStart[3] = { 0,0,0 };
2902e5b6d6dSopenharmony_ci            gJapaneseEraRules->getStartDate(era + 1, nextEraStart, status);
2912e5b6d6dSopenharmony_ci            int32_t nextEraYear = nextEraStart[0];
2922e5b6d6dSopenharmony_ci            int32_t nextEraMonth = nextEraStart[1]; // 1-base
2932e5b6d6dSopenharmony_ci            int32_t nextEraDate = nextEraStart[2];
2942e5b6d6dSopenharmony_ci
2952e5b6d6dSopenharmony_ci            int32_t eraStartYear = gJapaneseEraRules->getStartYear(era, status);
2962e5b6d6dSopenharmony_ci            int32_t maxYear = nextEraYear - eraStartYear + 1;   // 1-base
2972e5b6d6dSopenharmony_ci            if (nextEraMonth == 1 && nextEraDate == 1) {
2982e5b6d6dSopenharmony_ci                // Subtract 1, because the next era starts at Jan 1
2992e5b6d6dSopenharmony_ci                maxYear--;
3002e5b6d6dSopenharmony_ci            }
3012e5b6d6dSopenharmony_ci            return maxYear;
3022e5b6d6dSopenharmony_ci        }
3032e5b6d6dSopenharmony_ci    }
3042e5b6d6dSopenharmony_ci    return GregorianCalendar::getActualMaximum(field, status);
3052e5b6d6dSopenharmony_ci}
3062e5b6d6dSopenharmony_ci
3072e5b6d6dSopenharmony_ciU_NAMESPACE_END
3082e5b6d6dSopenharmony_ci
3092e5b6d6dSopenharmony_ci#endif
310