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