The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

DateTime::Calendar::Chinese - Traditional Chinese Calendar Implementation

SYNOPSIS

  use DateTime::Calendar::Chinese;

  my $dt = DateTime::Calendar::Chinese->now();
  my $dt = DateTime::Calendar::Chinese->new(
    cycle      => $cycle,
    cycle_year => $cycle_year,
    month      => $month,
    leap_month => $leap_month,
    day        => $day,
  );

  $dt->cycle;
  $dt->cycle_year; # 1 - 60
  $dt->month;      # 1-12
  $dt->leap_month; # true/false
  $dt->day;        # 1-30 
  $dt->elapsed_years; # years since "Chinese Epoch"

  my ($rd_days, $rd_secs, $rd_nanosecs) = $dt->utc_rd_values();

DESCRIPTION

This is an implementation of the Chinese calendar as described in "Calendrical Calculations" [1]. Please note that the following description is the description from [1], and the author has not made attempts to verify the correctness of statements with other sources.

The Chinese calendar described in [1] is expressed in terms of "cycle", "cycle_year", "month", "a boolean leap_month", and "day".

Traditional Chinese years have been counted using the "Sexagecimal Cycle of Names", which is a cycle of 60 names for each year. The names are the combination of a "celestial stem" (tian gan), with a "terrestial branch" (di zhi):

    Celestial Stems         Terrestial Branches
  -------------------     -----------------------
  | Jia             |     | Zi (Rat)            |
  -------------------     -----------------------
  | Yi              |     | Chou (Ox)           |
  -------------------     -----------------------
  | Bing            |     | Yin (Tiger)         |
  -------------------     -----------------------
  | Ding            |     | Mao (Hare)          |
  -------------------     -----------------------
  | Wu              |     | Chen (Dragon)       |
  -------------------     -----------------------
  | Ji              |     | Si (Snake)          |
  -------------------     -----------------------
  | Geng            |     | Wu (Horse)          |
  -------------------     -----------------------
  | Xin             |     | Wei (Sheep)         |
  -------------------     -----------------------
  | Ren             |     | Shen (Monkey)       |
  -------------------     -----------------------
  | Gui             |     | You (Fowl)          |
  -------------------     -----------------------
                          | Xu (Dog)            |
                          -----------------------
                          | Hai (Pig)           |
                          -----------------------

Names are assigned by running each list sequentially, so the first year woud be jiazi, then yuchou, bingyin, and so on.

Chinese months are true lunar months, which starts on a new moon and runs until the day before the next new moon. Therefore each month consists of exactly 29 or 30 days. The month numbers are calculated based on a logic that combines lunar months and solar terms (which is too hard to explain here -- read "Calendrical Calculation" if you must know), and may include leap months.

Leap months can be inserted anywhere in the year, so months are numbered from 1 to 12, with the boolean flag "leap_month" that indicates if the month is a leap month or not.

METHODS

new

This class method accepts parameters for each date and time component: "cycle", "cycle_year", "month", "leap_month", "day", "hour", "minute", "second", "nanosecond". It also accepts "locale" and "time_zone" parameters.

Note that in order to avoid confusion between the official Chinese Calendar which is based on Chinese time zone, the default value for time_zone is *not* "floating", but is instead "Asia/Shanghai". See CAVEATS.

  XXX The time zone settings may change in a few ture version such
  XXX that the calculation is done in Asia/Shanghai, but the
  XXX resulting object is set to "floating" time zone.

Note that currently there's no way to verify if a given date is "correct" -- i.e. if you give a date as a leap_month when it in fact isn't a leap month, all sorts of wacky things will happen. Perhaps there's a simple way to do this. If there is, please let me know

now

This class method is equivalent to calling from_epoch() with the value returned from Perl's time() function.

from_object(object => ...)

This class method can be used to construct a new DateTime::Calendar::Chinese object from any object that implements the utc_rd_values() method.

from_epoch(epoch => ...)

This class method can be used to construct a new DateTime::Calendar::Chinese object from an epoch time instead of components.

set(...)

This method is identical to that of DateTime, except the date components that can be set are restricted to the Chinese ones ("cycle", "cycle_year", "month", "leap_month", "day"). The time components are the same as that of DateTime (See CAVEATS).

utc_rd_values()

Returns the current UTC Rata Die days, seconds, and nanoseconds as a three element list. This method is identical to that of DateTime.

cycle

Returns the current cycle of the sexagecimal names since the Chinese epoch (defined to be 25 Feb, -2636 gregorian).

cycle_year

Returns the current year in the current cycle.

month

Returns the current month.

leap_month

Returns true if the current month is a leap month.

day

Returns the current day.

elapsed_year

This returns the number of years elapsed since the Chinese Epoch as defined by [1] (Which is 15 Feb. -2646 gregorian). Some documents use different epoch dates, and hence this may not match with whatever source you have.

CAVEATS

TIMEZONES

Be careful with time zones! The "official" Chinese Calendar is based on date/time in China, not your local time zone nor "floating" time zone. This is because the Chinese Calendar is based on astronomical events, but dates such as Chinese New Year are calculated in Chinese time and then transferred over to wherever you're at.

For example, the Chinese New Year in 2004 is Jan 22, but that is Jan 22 in China time. The same time is Jan 21 UTC, and now you'd be off by one day.

So when you're calculating Chinese Calendars, always set the time zone to something like 'Asia/Hong_Kong', 'Asia/Shanghai', 'Asia/Taipei'

TIME

Because "Calendrical Calculations" did not go much in detail about the Chinese time system, this module simply uses the time components from the underlying DateTime module (XXX - Note: we may implement this later, so be careful not to use the time components too much for now)

PERFORMANCE

Yes, this module is slow, because the underlying calculations are slow. If you can contribute to the speed, please let me know. So far I've concentrated on porting the algorithms from [1] straight over, and not on performance. I'm sure there's a lot that could be done.

AUTHOR

Daisuke Maki <daisuke@cpan.org>

REFERENCES

  [1] Edward M. Reingold, Nachum Dershowitz
      "Calendrical Calculations (Millenium Edition)", 2nd ed.
       Cambridge University Press, Cambridge, UK 2002

SEE ALSO

DateTime DateTime::Event::Chinese