tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

dangical.cpp (5485B)


      1 // © 2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 ******************************************************************************
      5 * Copyright (C) 2013, International Business Machines Corporation
      6 * and others. All Rights Reserved.
      7 ******************************************************************************
      8 *
      9 * File DANGICAL.CPP
     10 *****************************************************************************
     11 */
     12 
     13 #include "chnsecal.h"
     14 #include "dangical.h"
     15 
     16 #if !UCONFIG_NO_FORMATTING
     17 
     18 #include "astro.h" // CalendarCache
     19 #include "gregoimp.h" // Math
     20 #include "uassert.h"
     21 #include "ucln_in.h"
     22 #include "umutex.h"
     23 #include "unicode/rbtz.h"
     24 #include "unicode/tzrule.h"
     25 
     26 // --- The cache --
     27 // Lazy Creation & Access synchronized by class CalendarCache with a mutex.
     28 static icu::CalendarCache *gWinterSolsticeCache = nullptr;
     29 static icu::CalendarCache *gNewYearCache = nullptr;
     30 
     31 // gAstronomerTimeZone
     32 static icu::TimeZone *gAstronomerTimeZone = nullptr;
     33 static icu::UInitOnce gAstronomerTimeZoneInitOnce {};
     34 
     35 U_CDECL_BEGIN
     36 static UBool calendar_dangi_cleanup() {
     37    if (gWinterSolsticeCache) {
     38        delete gWinterSolsticeCache;
     39        gWinterSolsticeCache = nullptr;
     40    }
     41    if (gNewYearCache) {
     42        delete gNewYearCache;
     43        gNewYearCache = nullptr;
     44    }
     45 
     46    if (gAstronomerTimeZone) {
     47        delete gAstronomerTimeZone;
     48        gAstronomerTimeZone = nullptr;
     49    }
     50    gAstronomerTimeZoneInitOnce.reset();
     51    return true;
     52 }
     53 U_CDECL_END
     54 
     55 U_NAMESPACE_BEGIN
     56 
     57 // Implementation of the DangiCalendar class
     58 
     59 //-------------------------------------------------------------------------
     60 // Constructors...
     61 //-------------------------------------------------------------------------
     62 
     63 const TimeZone* getAstronomerTimeZone(UErrorCode &status);
     64 
     65 DangiCalendar::DangiCalendar(const Locale& aLocale, UErrorCode& success)
     66 :   ChineseCalendar(aLocale, success)
     67 {
     68 }
     69 
     70 DangiCalendar::DangiCalendar (const DangiCalendar& other) 
     71 : ChineseCalendar(other)
     72 {
     73 }
     74 
     75 DangiCalendar::~DangiCalendar()
     76 {
     77 }
     78 
     79 DangiCalendar*
     80 DangiCalendar::clone() const
     81 {
     82    return new DangiCalendar(*this);
     83 }
     84 
     85 const char *DangiCalendar::getType() const { 
     86    return "dangi";
     87 }
     88 
     89 /**
     90 * The time zone used for performing astronomical computations for
     91 * Dangi calendar. In Korea various timezones have been used historically 
     92 * (cf. http://www.math.snu.ac.kr/~kye/others/lunar.html): 
     93 *  
     94 *            - 1908/04/01: GMT+8 
     95 * 1908/04/01 - 1911/12/31: GMT+8.5 
     96 * 1912/01/01 - 1954/03/20: GMT+9 
     97 * 1954/03/21 - 1961/08/09: GMT+8.5 
     98 * 1961/08/10 -           : GMT+9 
     99 *  
    100 * Note that, in 1908-1911, the government did not apply the timezone change 
    101 * but used GMT+8. In addition, 1954-1961's timezone change does not affect 
    102 * the lunar date calculation. Therefore, the following simpler rule works: 
    103 *   
    104 * -1911: GMT+8 
    105 * 1912-: GMT+9 
    106 *  
    107 * Unfortunately, our astronomer's approximation doesn't agree with the 
    108 * references (http://www.math.snu.ac.kr/~kye/others/lunar.html and 
    109 * http://astro.kasi.re.kr/Life/ConvertSolarLunarForm.aspx?MenuID=115) 
    110 * in 1897/7/30. So the following ad hoc fix is used here: 
    111 *  
    112 *     -1896: GMT+8 
    113 *      1897: GMT+7 
    114 * 1898-1911: GMT+8 
    115 * 1912-    : GMT+9 
    116 */
    117 static void U_CALLCONV initAstronomerTimeZone(UErrorCode &status) {
    118    U_ASSERT(gAstronomerTimeZone == nullptr);
    119    const UDate millis1897[] = { static_cast<UDate>((1897 - 1970) * 365 * kOneDay) }; // some days of error is not a problem here
    120    const UDate millis1898[] = { static_cast<UDate>((1898 - 1970) * 365 * kOneDay) }; // some days of error is not a problem here
    121    const UDate millis1912[] = { static_cast<UDate>((1912 - 1970) * 365 * kOneDay) }; // this doesn't create an issue for 1911/12/20
    122    LocalPointer<InitialTimeZoneRule> initialTimeZone(new InitialTimeZoneRule(
    123        UnicodeString(u"GMT+8"), 8*kOneHour, 0), status);
    124 
    125    LocalPointer<TimeZoneRule> rule1897(new TimeArrayTimeZoneRule(
    126        UnicodeString(u"Korean 1897"), 7*kOneHour, 0, millis1897, 1, DateTimeRule::STANDARD_TIME), status);
    127 
    128    LocalPointer<TimeZoneRule> rule1898to1911(new TimeArrayTimeZoneRule(
    129        UnicodeString(u"Korean 1898-1911"), 8*kOneHour, 0, millis1898, 1, DateTimeRule::STANDARD_TIME), status);
    130 
    131    LocalPointer<TimeZoneRule> ruleFrom1912(new TimeArrayTimeZoneRule(
    132        UnicodeString(u"Korean 1912-"), 9*kOneHour, 0, millis1912, 1, DateTimeRule::STANDARD_TIME), status);
    133 
    134    LocalPointer<RuleBasedTimeZone> zone(new RuleBasedTimeZone(
    135        UnicodeString(u"KOREA_ZONE"), initialTimeZone.orphan()), status); // adopts initialTimeZone
    136 
    137    if (U_FAILURE(status)) {
    138        return;
    139    }
    140    zone->addTransitionRule(rule1897.orphan(), status); // adopts rule1897
    141    zone->addTransitionRule(rule1898to1911.orphan(), status);
    142    zone->addTransitionRule(ruleFrom1912.orphan(), status);
    143    zone->complete(status);
    144    if (U_SUCCESS(status)) {
    145        gAstronomerTimeZone = zone.orphan();
    146    }
    147    ucln_i18n_registerCleanup(UCLN_I18N_DANGI_CALENDAR, calendar_dangi_cleanup);
    148 }
    149 
    150 const TimeZone* getAstronomerTimeZone(UErrorCode &status) {
    151    umtx_initOnce(gAstronomerTimeZoneInitOnce, &initAstronomerTimeZone, status);
    152    return gAstronomerTimeZone;
    153 }
    154 
    155 ChineseCalendar::Setting DangiCalendar::getSetting(UErrorCode& status) const {
    156  return {
    157    getAstronomerTimeZone(status),
    158    &gWinterSolsticeCache, &gNewYearCache
    159  };
    160 }
    161 
    162 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DangiCalendar)
    163 
    164 U_NAMESPACE_END
    165 
    166 #endif