1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 ******************************************************************************
5 * Copyright (C) 2013, International Business Machines Corporation
6 * and others. All Rights Reserved.
7 ******************************************************************************
10 *****************************************************************************
16 #if !UCONFIG_NO_FORMATTING
18 #include "gregoimp.h" // Math
22 #include "unicode/rbtz.h"
23 #include "unicode/tzrule.h"
26 static icu::TimeZone
*gDangiCalendarZoneAstroCalc
= NULL
;
27 static icu::UInitOnce gDangiCalendarInitOnce
= U_INITONCE_INITIALIZER
;
30 * The start year of the Korean traditional calendar (Dan-gi) is the inaugural
31 * year of Dan-gun (BC 2333).
33 static const int32_t DANGI_EPOCH_YEAR
= -2332; // Gregorian year
36 static UBool
calendar_dangi_cleanup(void) {
37 if (gDangiCalendarZoneAstroCalc
) {
38 delete gDangiCalendarZoneAstroCalc
;
39 gDangiCalendarZoneAstroCalc
= NULL
;
41 gDangiCalendarInitOnce
.reset();
48 // Implementation of the DangiCalendar class
50 //-------------------------------------------------------------------------
52 //-------------------------------------------------------------------------
54 DangiCalendar::DangiCalendar(const Locale
& aLocale
, UErrorCode
& success
)
55 : ChineseCalendar(aLocale
, DANGI_EPOCH_YEAR
, getDangiCalZoneAstroCalc(), success
)
59 DangiCalendar::DangiCalendar (const DangiCalendar
& other
)
60 : ChineseCalendar(other
)
64 DangiCalendar::~DangiCalendar()
69 DangiCalendar::clone() const
71 return new DangiCalendar(*this);
74 const char *DangiCalendar::getType() const {
79 * The time zone used for performing astronomical computations for
80 * Dangi calendar. In Korea various timezones have been used historically
81 * (cf. http://www.math.snu.ac.kr/~kye/others/lunar.html):
84 * 1908/04/01 - 1911/12/31: GMT+8.5
85 * 1912/01/01 - 1954/03/20: GMT+9
86 * 1954/03/21 - 1961/08/09: GMT+8.5
87 * 1961/08/10 - : GMT+9
89 * Note that, in 1908-1911, the government did not apply the timezone change
90 * but used GMT+8. In addition, 1954-1961's timezone change does not affect
91 * the lunar date calculation. Therefore, the following simpler rule works:
96 * Unfortunately, our astronomer's approximation doesn't agree with the
97 * references (http://www.math.snu.ac.kr/~kye/others/lunar.html and
98 * http://astro.kasi.re.kr/Life/ConvertSolarLunarForm.aspx?MenuID=115)
99 * in 1897/7/30. So the following ad hoc fix is used here:
106 static void U_CALLCONV
initDangiCalZoneAstroCalc(void) {
107 U_ASSERT(gDangiCalendarZoneAstroCalc
== NULL
);
108 const UDate millis1897
[] = { (UDate
)((1897 - 1970) * 365 * kOneDay
) }; // some days of error is not a problem here
109 const UDate millis1898
[] = { (UDate
)((1898 - 1970) * 365 * kOneDay
) }; // some days of error is not a problem here
110 const UDate millis1912
[] = { (UDate
)((1912 - 1970) * 365 * kOneDay
) }; // this doesn't create an issue for 1911/12/20
111 InitialTimeZoneRule
* initialTimeZone
= new InitialTimeZoneRule(UNICODE_STRING_SIMPLE("GMT+8"), 8*kOneHour
, 0);
112 TimeZoneRule
* rule1897
= new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1897"), 7*kOneHour
, 0, millis1897
, 1, DateTimeRule::STANDARD_TIME
);
113 TimeZoneRule
* rule1898to1911
= new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1898-1911"), 8*kOneHour
, 0, millis1898
, 1, DateTimeRule::STANDARD_TIME
);
114 TimeZoneRule
* ruleFrom1912
= new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1912-"), 9*kOneHour
, 0, millis1912
, 1, DateTimeRule::STANDARD_TIME
);
115 UErrorCode status
= U_ZERO_ERROR
;
116 RuleBasedTimeZone
* dangiCalZoneAstroCalc
= new RuleBasedTimeZone(UNICODE_STRING_SIMPLE("KOREA_ZONE"), initialTimeZone
); // adopts initialTimeZone
117 dangiCalZoneAstroCalc
->addTransitionRule(rule1897
, status
); // adopts rule1897
118 dangiCalZoneAstroCalc
->addTransitionRule(rule1898to1911
, status
);
119 dangiCalZoneAstroCalc
->addTransitionRule(ruleFrom1912
, status
);
120 dangiCalZoneAstroCalc
->complete(status
);
121 if (U_SUCCESS(status
)) {
122 gDangiCalendarZoneAstroCalc
= dangiCalZoneAstroCalc
;
124 delete dangiCalZoneAstroCalc
;
125 gDangiCalendarZoneAstroCalc
= NULL
;
127 ucln_i18n_registerCleanup(UCLN_I18N_DANGI_CALENDAR
, calendar_dangi_cleanup
);
130 const TimeZone
* DangiCalendar::getDangiCalZoneAstroCalc(void) const {
131 umtx_initOnce(gDangiCalendarInitOnce
, &initDangiCalZoneAstroCalc
);
132 return gDangiCalendarZoneAstroCalc
;
136 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DangiCalendar
)