1 // © 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ***************************************************************************** 5 * Copyright (C) 2007-2013, International Business Machines Corporation 6 * and others. All Rights Reserved. 7 ***************************************************************************** 8 * 9 * File CHNSECAL.H 10 * 11 * Modification History: 12 * 13 * Date Name Description 14 * 9/18/2007 ajmacher ported from java ChineseCalendar 15 ***************************************************************************** 16 */ 17 18 #ifndef CHNSECAL_H 19 #define CHNSECAL_H 20 21 #include "unicode/utypes.h" 22 23 #if !UCONFIG_NO_FORMATTING 24 25 #include "unicode/calendar.h" 26 #include "unicode/timezone.h" 27 28 U_NAMESPACE_BEGIN 29 30 /** 31 * <code>ChineseCalendar</code> is a concrete subclass of {@link Calendar} 32 * that implements a traditional Chinese calendar. The traditional Chinese 33 * calendar is a lunisolar calendar: Each month starts on a new moon, and 34 * the months are numbered according to solar events, specifically, to 35 * guarantee that month 11 always contains the winter solstice. In order 36 * to accomplish this, leap months are inserted in certain years. Leap 37 * months are numbered the same as the month they follow. The decision of 38 * which month is a leap month depends on the relative movements of the sun 39 * and moon. 40 * 41 * <p>This class defines one addition field beyond those defined by 42 * <code>Calendar</code>: The <code>IS_LEAP_MONTH</code> field takes the 43 * value of 0 for normal months, or 1 for leap months. 44 * 45 * <p>All astronomical computations are performed with respect to a time 46 * zone of GMT+8:00 and a longitude of 120 degrees east. Although some 47 * calendars implement a historically more accurate convention of using 48 * Beijing's local longitude (116 degrees 25 minutes east) and time zone 49 * (GMT+7:45:40) for dates before 1929, we do not implement this here. 50 * 51 * <p>Years are counted in two different ways in the Chinese calendar. The 52 * first method is by sequential numbering from the 61st year of the reign 53 * of Huang Di, 2637 BCE, which is designated year 1 on the Chinese 54 * calendar. The second method uses 60-year cycles from the same starting 55 * point, which is designated year 1 of cycle 1. In this class, the 56 * <code>EXTENDED_YEAR</code> field contains the sequential year count. 57 * The <code>ERA</code> field contains the cycle number, and the 58 * <code>YEAR</code> field contains the year of the cycle, a value between 59 * 1 and 60. 60 * 61 * <p>There is some variation in what is considered the starting point of 62 * the calendar, with some sources starting in the first year of the reign 63 * of Huang Di, rather than the 61st. This gives continuous year numbers 64 * 60 years greater and cycle numbers one greater than what this class 65 * implements. 66 * 67 * <p>Because <code>ChineseCalendar</code> defines an additional field and 68 * redefines the way the <code>ERA</code> field is used, it requires a new 69 * format class, <code>ChineseDateFormat</code>. As always, use the 70 * methods <code>DateFormat.getXxxInstance(Calendar cal,...)</code> to 71 * obtain a formatter for this calendar. 72 * 73 * <p>References:<ul> 74 * 75 * <li>Dershowitz and Reingold, <i>Calendrical Calculations</i>, 76 * Cambridge University Press, 1997</li> 77 * 78 * <li>Helmer Aslaksen's 79 * <a href="http://www.math.nus.edu.sg/aslaksen/calendar/chinese.shtml"> 80 * Chinese Calendar page</a></li> 81 * 82 * <li>The <a href="http://www.tondering.dk/claus/calendar.html"> 83 * Calendar FAQ</a></li> 84 * 85 * </ul> 86 * 87 * <p> 88 * This class should only be subclassed to implement variants of the Chinese lunar calendar.</p> 89 * <p> 90 * ChineseCalendar usually should be instantiated using 91 * {@link com.ibm.icu.util.Calendar#getInstance(ULocale)} passing in a <code>ULocale</code> 92 * with the tag <code>"@calendar=chinese"</code>.</p> 93 * 94 * @see com.ibm.icu.text.ChineseDateFormat 95 * @see com.ibm.icu.util.Calendar 96 * @author Alan Liu 97 * @internal 98 */ 99 class U_I18N_API ChineseCalendar : public Calendar { 100 public: 101 //------------------------------------------------------------------------- 102 // Constructors... 103 //------------------------------------------------------------------------- 104 105 /** 106 * Constructs a ChineseCalendar based on the current time in the default time zone 107 * with the given locale. 108 * 109 * @param aLocale The given locale. 110 * @param success Indicates the status of ChineseCalendar object construction. 111 * Returns U_ZERO_ERROR if constructed successfully. 112 * @internal 113 */ 114 ChineseCalendar(const Locale& aLocale, UErrorCode &success); 115 116 protected: 117 118 /** 119 * Constructs a ChineseCalendar based on the current time in the default time zone 120 * with the given locale, using the specified epoch year and time zone for 121 * astronomical calculations. 122 * 123 * @param aLocale The given locale. 124 * @param epochYear The epoch year to use for calculation. 125 * @param zoneAstroCalc The TimeZone to use for astronomical calculations. If null, 126 * will be set appropriately for Chinese calendar (UTC + 8:00). 127 * @param success Indicates the status of ChineseCalendar object construction; 128 * if successful, will not be changed to an error value. 129 * @internal 130 */ 131 ChineseCalendar(const Locale& aLocale, int32_t epochYear, const TimeZone* zoneAstroCalc, UErrorCode &success); 132 133 public: 134 /** 135 * Copy Constructor 136 * @internal 137 */ 138 ChineseCalendar(const ChineseCalendar& other); 139 140 /** 141 * Destructor. 142 * @internal 143 */ 144 virtual ~ChineseCalendar(); 145 146 // clone 147 virtual ChineseCalendar* clone() const override; 148 149 private: 150 151 //------------------------------------------------------------------------- 152 // Internal data.... 153 //------------------------------------------------------------------------- 154 155 UBool isLeapYear; 156 int32_t fEpochYear; // Start year of this Chinese calendar instance. 157 const TimeZone* fZoneAstroCalc; // Zone used for the astronomical calculation 158 // of this Chinese calendar instance. 159 160 //---------------------------------------------------------------------- 161 // Calendar framework 162 //---------------------------------------------------------------------- 163 164 protected: 165 virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const override; 166 virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const override; 167 virtual int32_t handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth) const override; 168 virtual int32_t handleGetExtendedYear() override; 169 virtual void handleComputeFields(int32_t julianDay, UErrorCode &status) override; 170 virtual const UFieldResolutionTable* getFieldResolutionTable() const override; 171 172 public: 173 virtual void add(UCalendarDateFields field, int32_t amount, UErrorCode &status) override; 174 virtual void add(EDateFields field, int32_t amount, UErrorCode &status) override; 175 virtual void roll(UCalendarDateFields field, int32_t amount, UErrorCode &status) override; 176 virtual void roll(EDateFields field, int32_t amount, UErrorCode &status) override; 177 178 //---------------------------------------------------------------------- 179 // Internal methods & astronomical calculations 180 //---------------------------------------------------------------------- 181 182 private: 183 184 static const UFieldResolutionTable CHINESE_DATE_PRECEDENCE[]; 185 186 double daysToMillis(double days) const; 187 double millisToDays(double millis) const; 188 virtual int32_t winterSolstice(int32_t gyear) const; 189 virtual int32_t newMoonNear(double days, UBool after) const; 190 virtual int32_t synodicMonthsBetween(int32_t day1, int32_t day2) const; 191 virtual int32_t majorSolarTerm(int32_t days) const; 192 virtual UBool hasNoMajorSolarTerm(int32_t newMoon) const; 193 virtual UBool isLeapMonthBetween(int32_t newMoon1, int32_t newMoon2) const; 194 virtual void computeChineseFields(int32_t days, int32_t gyear, 195 int32_t gmonth, UBool setAllFields); 196 virtual int32_t newYear(int32_t gyear) const; 197 virtual void offsetMonth(int32_t newMoon, int32_t dom, int32_t delta); 198 const TimeZone* getChineseCalZoneAstroCalc(void) const; 199 200 // UObject stuff 201 public: 202 /** 203 * @return The class ID for this object. All objects of a given class have the 204 * same class ID. Objects of other classes have different class IDs. 205 * @internal 206 */ 207 virtual UClassID getDynamicClassID(void) const override; 208 209 /** 210 * Return the class ID for this class. This is useful only for comparing to a return 211 * value from getDynamicClassID(). For example: 212 * 213 * Base* polymorphic_pointer = createPolymorphicObject(); 214 * if (polymorphic_pointer->getDynamicClassID() == 215 * Derived::getStaticClassID()) ... 216 * 217 * @return The class ID for all objects of this class. 218 * @internal 219 */ 220 static UClassID U_EXPORT2 getStaticClassID(void); 221 222 /** 223 * return the calendar type, "chinese". 224 * 225 * @return calendar type 226 * @internal 227 */ 228 virtual const char * getType() const override; 229 230 231 protected: 232 /** 233 * (Overrides Calendar) Return true if the current date for this Calendar is in 234 * Daylight Savings Time. Recognizes DST_OFFSET, if it is set. 235 * 236 * @param status Fill-in parameter which receives the status of this operation. 237 * @return True if the current date for this Calendar is in Daylight Savings Time, 238 * false, otherwise. 239 * @internal 240 */ 241 virtual UBool inDaylightTime(UErrorCode& status) const override; 242 243 244 /** 245 * Returns true because the Islamic Calendar does have a default century 246 * @internal 247 */ 248 virtual UBool haveDefaultCentury() const override; 249 250 /** 251 * Returns the date of the start of the default century 252 * @return start of century - in milliseconds since epoch, 1970 253 * @internal 254 */ 255 virtual UDate defaultCenturyStart() const override; 256 257 /** 258 * Returns the year in which the default century begins 259 * @internal 260 */ 261 virtual int32_t defaultCenturyStartYear() const override; 262 263 private: // default century stuff. 264 265 /** 266 * Returns the beginning date of the 100-year window that dates 267 * with 2-digit years are considered to fall within. 268 */ 269 UDate internalGetDefaultCenturyStart(void) const; 270 271 /** 272 * Returns the first year of the 100-year window that dates with 273 * 2-digit years are considered to fall within. 274 */ 275 int32_t internalGetDefaultCenturyStartYear(void) const; 276 277 ChineseCalendar() = delete; // default constructor not implemented 278 }; 279 280 U_NAMESPACE_END 281 282 #endif 283 #endif 284