2 ******************************************************************************
3 * Copyright (C) 2013, International Business Machines Corporation
4 * and others. All Rights Reserved.
5 ******************************************************************************
8 *****************************************************************************
14 #if !UCONFIG_NO_FORMATTING
17 #include "gregoimp.h" // Math
18 #include "unicode/rbtz.h"
19 #include "unicode/tzrule.h"
23 static UMutex dangiLock
= U_MUTEX_INITIALIZER
;
24 static icu::TimeZone
*gDangiCalendarZoneAstroCalc
= NULL
;
25 static UBool gDangiCalendarZoneAstroCalcInitialized
= FALSE
;
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 gDangiCalendarZoneAstroCalcInitialized
= FALSE
;
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 const TimeZone
* DangiCalendar::getDangiCalZoneAstroCalc(void) const {
106 UMTX_CHECK(&dangiLock
, gDangiCalendarZoneAstroCalcInitialized
, initialized
);
108 umtx_lock(&dangiLock
);
110 if (!gDangiCalendarZoneAstroCalcInitialized
) {
111 const UDate millis1897
[] = { (UDate
)((1897 - 1970) * 365 * kOneDay
) }; // some days of error is not a problem here
112 const UDate millis1898
[] = { (UDate
)((1898 - 1970) * 365 * kOneDay
) }; // some days of error is not a problem here
113 const UDate millis1912
[] = { (UDate
)((1912 - 1970) * 365 * kOneDay
) }; // this doesn't create an issue for 1911/12/20
114 InitialTimeZoneRule
* initialTimeZone
= new InitialTimeZoneRule(UNICODE_STRING_SIMPLE("GMT+8"), 8*kOneHour
, 0);
115 TimeZoneRule
* rule1897
= new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1897"), 7*kOneHour
, 0, millis1897
, 1, DateTimeRule::STANDARD_TIME
);
116 TimeZoneRule
* rule1898to1911
= new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1898-1911"), 8*kOneHour
, 0, millis1898
, 1, DateTimeRule::STANDARD_TIME
);
117 TimeZoneRule
* ruleFrom1912
= new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1912-"), 9*kOneHour
, 0, millis1912
, 1, DateTimeRule::STANDARD_TIME
);
118 UErrorCode status
= U_ZERO_ERROR
;
119 RuleBasedTimeZone
* dangiCalZoneAstroCalc
= new RuleBasedTimeZone(UNICODE_STRING_SIMPLE("KOREA_ZONE"), initialTimeZone
); // adopts initialTimeZone
120 dangiCalZoneAstroCalc
->addTransitionRule(rule1897
, status
); // adopts rule1897
121 dangiCalZoneAstroCalc
->addTransitionRule(rule1898to1911
, status
);
122 dangiCalZoneAstroCalc
->addTransitionRule(ruleFrom1912
, status
);
123 dangiCalZoneAstroCalc
->complete(status
);
124 if (U_SUCCESS(status
)) {
125 gDangiCalendarZoneAstroCalc
= dangiCalZoneAstroCalc
;
127 delete dangiCalZoneAstroCalc
;
128 gDangiCalendarZoneAstroCalc
= NULL
;
130 gDangiCalendarZoneAstroCalcInitialized
= TRUE
;
131 ucln_i18n_registerCleanup(UCLN_I18N_DANGI_CALENDAR
, calendar_dangi_cleanup
);
134 umtx_unlock(&dangiLock
);
136 return gDangiCalendarZoneAstroCalc
;
139 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DangiCalendar
)