intl/icu/source/i18n/dangical.cpp

changeset 0
6474c204b198
     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 +

mercurial