2 ******************************************************************************
3 * Copyright (C) 2013, International Business Machines Corporation
4 * and others. All Rights Reserved.
5 ******************************************************************************
8 *****************************************************************************
14 #if !UCONFIG_NO_FORMATTING
16 #include "gregoimp.h" // Math
20 #include "unicode/rbtz.h"
21 #include "unicode/tzrule.h"
24 static icu::TimeZone
*gDangiCalendarZoneAstroCalc
= NULL
;
25 static icu::UInitOnce gDangiCalendarInitOnce
= U_INITONCE_INITIALIZER
;
28 * The start year of the Korean traditional calendar (Dan-gi) is the inaugural
29 * year of Dan-gun (BC 2333).
31 static const int32_t DANGI_EPOCH_YEAR
= -2332; // Gregorian year
34 static UBool
calendar_dangi_cleanup(void) {
35 if (gDangiCalendarZoneAstroCalc
) {
36 delete gDangiCalendarZoneAstroCalc
;
37 gDangiCalendarZoneAstroCalc
= NULL
;
39 gDangiCalendarInitOnce
.reset();
46 // Implementation of the DangiCalendar class
48 //-------------------------------------------------------------------------
50 //-------------------------------------------------------------------------
52 DangiCalendar::DangiCalendar(const Locale
& aLocale
, UErrorCode
& success
)
53 : ChineseCalendar(aLocale
, DANGI_EPOCH_YEAR
, getDangiCalZoneAstroCalc(), success
)
57 DangiCalendar::DangiCalendar (const DangiCalendar
& other
)
58 : ChineseCalendar(other
)
62 DangiCalendar::~DangiCalendar()
67 DangiCalendar::clone() const
69 return new DangiCalendar(*this);
72 const char *DangiCalendar::getType() const {
77 * The time zone used for performing astronomical computations for
78 * Dangi calendar. In Korea various timezones have been used historically
79 * (cf. http://www.math.snu.ac.kr/~kye/others/lunar.html):
82 * 1908/04/01 - 1911/12/31: GMT+8.5
83 * 1912/01/01 - 1954/03/20: GMT+9
84 * 1954/03/21 - 1961/08/09: GMT+8.5
85 * 1961/08/10 - : GMT+9
87 * Note that, in 1908-1911, the government did not apply the timezone change
88 * but used GMT+8. In addition, 1954-1961's timezone change does not affect
89 * the lunar date calculation. Therefore, the following simpler rule works:
94 * Unfortunately, our astronomer's approximation doesn't agree with the
95 * references (http://www.math.snu.ac.kr/~kye/others/lunar.html and
96 * http://astro.kasi.re.kr/Life/ConvertSolarLunarForm.aspx?MenuID=115)
97 * in 1897/7/30. So the following ad hoc fix is used here:
104 static void U_CALLCONV
initDangiCalZoneAstroCalc(void) {
105 U_ASSERT(gDangiCalendarZoneAstroCalc
== NULL
);
106 const UDate millis1897
[] = { (UDate
)((1897 - 1970) * 365 * kOneDay
) }; // some days of error is not a problem here
107 const UDate millis1898
[] = { (UDate
)((1898 - 1970) * 365 * kOneDay
) }; // some days of error is not a problem here
108 const UDate millis1912
[] = { (UDate
)((1912 - 1970) * 365 * kOneDay
) }; // this doesn't create an issue for 1911/12/20
109 InitialTimeZoneRule
* initialTimeZone
= new InitialTimeZoneRule(UNICODE_STRING_SIMPLE("GMT+8"), 8*kOneHour
, 0);
110 TimeZoneRule
* rule1897
= new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1897"), 7*kOneHour
, 0, millis1897
, 1, DateTimeRule::STANDARD_TIME
);
111 TimeZoneRule
* rule1898to1911
= new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1898-1911"), 8*kOneHour
, 0, millis1898
, 1, DateTimeRule::STANDARD_TIME
);
112 TimeZoneRule
* ruleFrom1912
= new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1912-"), 9*kOneHour
, 0, millis1912
, 1, DateTimeRule::STANDARD_TIME
);
113 UErrorCode status
= U_ZERO_ERROR
;
114 RuleBasedTimeZone
* dangiCalZoneAstroCalc
= new RuleBasedTimeZone(UNICODE_STRING_SIMPLE("KOREA_ZONE"), initialTimeZone
); // adopts initialTimeZone
115 dangiCalZoneAstroCalc
->addTransitionRule(rule1897
, status
); // adopts rule1897
116 dangiCalZoneAstroCalc
->addTransitionRule(rule1898to1911
, status
);
117 dangiCalZoneAstroCalc
->addTransitionRule(ruleFrom1912
, status
);
118 dangiCalZoneAstroCalc
->complete(status
);
119 if (U_SUCCESS(status
)) {
120 gDangiCalendarZoneAstroCalc
= dangiCalZoneAstroCalc
;
122 delete dangiCalZoneAstroCalc
;
123 gDangiCalendarZoneAstroCalc
= NULL
;
125 ucln_i18n_registerCleanup(UCLN_I18N_DANGI_CALENDAR
, calendar_dangi_cleanup
);
128 const TimeZone
* DangiCalendar::getDangiCalZoneAstroCalc(void) const {
129 umtx_initOnce(gDangiCalendarInitOnce
, &initDangiCalZoneAstroCalc
);
130 return gDangiCalendarZoneAstroCalc
;
134 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DangiCalendar
)