Home | History | Annotate | Download | only in i18n
      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