1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/i18n/dangical.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,139 @@ 1.4 +/* 1.5 + ****************************************************************************** 1.6 + * Copyright (C) 2013, International Business Machines Corporation 1.7 + * and others. All Rights Reserved. 1.8 + ****************************************************************************** 1.9 + * 1.10 + * File DANGICAL.CPP 1.11 + ***************************************************************************** 1.12 + */ 1.13 + 1.14 +#include "chnsecal.h" 1.15 +#include "dangical.h" 1.16 + 1.17 +#if !UCONFIG_NO_FORMATTING 1.18 + 1.19 +#include "gregoimp.h" // Math 1.20 +#include "uassert.h" 1.21 +#include "ucln_in.h" 1.22 +#include "umutex.h" 1.23 +#include "unicode/rbtz.h" 1.24 +#include "unicode/tzrule.h" 1.25 + 1.26 +// --- The cache -- 1.27 +static icu::TimeZone *gDangiCalendarZoneAstroCalc = NULL; 1.28 +static icu::UInitOnce gDangiCalendarInitOnce = U_INITONCE_INITIALIZER; 1.29 + 1.30 +/** 1.31 + * The start year of the Korean traditional calendar (Dan-gi) is the inaugural 1.32 + * year of Dan-gun (BC 2333). 1.33 + */ 1.34 +static const int32_t DANGI_EPOCH_YEAR = -2332; // Gregorian year 1.35 + 1.36 +U_CDECL_BEGIN 1.37 +static UBool calendar_dangi_cleanup(void) { 1.38 + if (gDangiCalendarZoneAstroCalc) { 1.39 + delete gDangiCalendarZoneAstroCalc; 1.40 + gDangiCalendarZoneAstroCalc = NULL; 1.41 + } 1.42 + gDangiCalendarInitOnce.reset(); 1.43 + return TRUE; 1.44 +} 1.45 +U_CDECL_END 1.46 + 1.47 +U_NAMESPACE_BEGIN 1.48 + 1.49 +// Implementation of the DangiCalendar class 1.50 + 1.51 +//------------------------------------------------------------------------- 1.52 +// Constructors... 1.53 +//------------------------------------------------------------------------- 1.54 + 1.55 +DangiCalendar::DangiCalendar(const Locale& aLocale, UErrorCode& success) 1.56 +: ChineseCalendar(aLocale, DANGI_EPOCH_YEAR, getDangiCalZoneAstroCalc(), success) 1.57 +{ 1.58 +} 1.59 + 1.60 +DangiCalendar::DangiCalendar (const DangiCalendar& other) 1.61 +: ChineseCalendar(other) 1.62 +{ 1.63 +} 1.64 + 1.65 +DangiCalendar::~DangiCalendar() 1.66 +{ 1.67 +} 1.68 + 1.69 +Calendar* 1.70 +DangiCalendar::clone() const 1.71 +{ 1.72 + return new DangiCalendar(*this); 1.73 +} 1.74 + 1.75 +const char *DangiCalendar::getType() const { 1.76 + return "dangi"; 1.77 +} 1.78 + 1.79 +/** 1.80 + * The time zone used for performing astronomical computations for 1.81 + * Dangi calendar. In Korea various timezones have been used historically 1.82 + * (cf. http://www.math.snu.ac.kr/~kye/others/lunar.html): 1.83 + * 1.84 + * - 1908/04/01: GMT+8 1.85 + * 1908/04/01 - 1911/12/31: GMT+8.5 1.86 + * 1912/01/01 - 1954/03/20: GMT+9 1.87 + * 1954/03/21 - 1961/08/09: GMT+8.5 1.88 + * 1961/08/10 - : GMT+9 1.89 + * 1.90 + * Note that, in 1908-1911, the government did not apply the timezone change 1.91 + * but used GMT+8. In addition, 1954-1961's timezone change does not affect 1.92 + * the lunar date calculation. Therefore, the following simpler rule works: 1.93 + * 1.94 + * -1911: GMT+8 1.95 + * 1912-: GMT+9 1.96 + * 1.97 + * Unfortunately, our astronomer's approximation doesn't agree with the 1.98 + * references (http://www.math.snu.ac.kr/~kye/others/lunar.html and 1.99 + * http://astro.kasi.re.kr/Life/ConvertSolarLunarForm.aspx?MenuID=115) 1.100 + * in 1897/7/30. So the following ad hoc fix is used here: 1.101 + * 1.102 + * -1896: GMT+8 1.103 + * 1897: GMT+7 1.104 + * 1898-1911: GMT+8 1.105 + * 1912- : GMT+9 1.106 + */ 1.107 +static void U_CALLCONV initDangiCalZoneAstroCalc(void) { 1.108 + U_ASSERT(gDangiCalendarZoneAstroCalc == NULL); 1.109 + const UDate millis1897[] = { (UDate)((1897 - 1970) * 365 * kOneDay) }; // some days of error is not a problem here 1.110 + const UDate millis1898[] = { (UDate)((1898 - 1970) * 365 * kOneDay) }; // some days of error is not a problem here 1.111 + const UDate millis1912[] = { (UDate)((1912 - 1970) * 365 * kOneDay) }; // this doesn't create an issue for 1911/12/20 1.112 + InitialTimeZoneRule* initialTimeZone = new InitialTimeZoneRule(UNICODE_STRING_SIMPLE("GMT+8"), 8*kOneHour, 0); 1.113 + TimeZoneRule* rule1897 = new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1897"), 7*kOneHour, 0, millis1897, 1, DateTimeRule::STANDARD_TIME); 1.114 + TimeZoneRule* rule1898to1911 = new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1898-1911"), 8*kOneHour, 0, millis1898, 1, DateTimeRule::STANDARD_TIME); 1.115 + TimeZoneRule* ruleFrom1912 = new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1912-"), 9*kOneHour, 0, millis1912, 1, DateTimeRule::STANDARD_TIME); 1.116 + UErrorCode status = U_ZERO_ERROR; 1.117 + RuleBasedTimeZone* dangiCalZoneAstroCalc = new RuleBasedTimeZone(UNICODE_STRING_SIMPLE("KOREA_ZONE"), initialTimeZone); // adopts initialTimeZone 1.118 + dangiCalZoneAstroCalc->addTransitionRule(rule1897, status); // adopts rule1897 1.119 + dangiCalZoneAstroCalc->addTransitionRule(rule1898to1911, status); 1.120 + dangiCalZoneAstroCalc->addTransitionRule(ruleFrom1912, status); 1.121 + dangiCalZoneAstroCalc->complete(status); 1.122 + if (U_SUCCESS(status)) { 1.123 + gDangiCalendarZoneAstroCalc = dangiCalZoneAstroCalc; 1.124 + } else { 1.125 + delete dangiCalZoneAstroCalc; 1.126 + gDangiCalendarZoneAstroCalc = NULL; 1.127 + } 1.128 + ucln_i18n_registerCleanup(UCLN_I18N_DANGI_CALENDAR, calendar_dangi_cleanup); 1.129 +} 1.130 + 1.131 +const TimeZone* DangiCalendar::getDangiCalZoneAstroCalc(void) const { 1.132 + umtx_initOnce(gDangiCalendarInitOnce, &initDangiCalZoneAstroCalc); 1.133 + return gDangiCalendarZoneAstroCalc; 1.134 +} 1.135 + 1.136 + 1.137 +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DangiCalendar) 1.138 + 1.139 +U_NAMESPACE_END 1.140 + 1.141 +#endif 1.142 +