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