Class ChineseCalendar

All Implemented Interfaces:
Serializable, Comparable<ChineseCalendar>, CalendarDate, ChronoDisplay, Temporal<CalendarDate>, LocalizedPatternSupport

@CalendarType("chinese") public final class ChineseCalendar extends EastAsianCalendar<ChineseCalendar.Unit,​ChineseCalendar> implements LocalizedPatternSupport

Represents the Chinese calendar supported in the gregorian range 1645-01-28/3000-01-27.

Introduction

It is a lunisolar calendar which defines years consisting of 12 or 13 months. Modern China now uses the gregorian calendar and uses this calendar mainly for determining the dates some festivals and the actual cyclic year and zodiac. See also Wikipedia.

Following elements which are declared as constants are registered by this class

Furthermore, all elements defined in EpochDays and CommonElements are supported.

Accuracy note

The calculations are based on the algorithms of Dershowitz/Reingold in their book "Calendrical calculations" and astronomical calculations in nowadays precision. Old scholar Chinese astronomers had applied less precise calculations in historic times so tiny deviations for the period 1645-1906 are possible in some rare cases. That means, this class rather models a theoretical ideal than the historic reality.

The future data from 1907 onwards had been compared to the published data of Hongkong observatory. Only the dates 2057-09-29 and 2097-08-08 deviate by one day (so all following days of same month). However, the observatory has explicitly declared these dates to be uncertain because their calculations of New Moon are not accurate enough to decide which month start exactly is right (the results are very close to local midnight).

Examples of usage

How to determine the festivals of New Year and Qing-Ming as gregorian dates:

     ChineseCalendar newyear = ChineseCalendar.ofNewYear(2020);
     ChineseCalendar qingming = newyear.with(ChineseCalendar.SOLAR_TERM, SolarTerm.MINOR_03_QINGMING_015);
     System.out.println(newyear.transform(PlainDate.axis())); // 2020-01-25
     System.out.println(qingming.transform(PlainDate.axis())); // 2020-04-04
 

Formatting with cyclic years and solar terms:

     ChronoFormatter<ChineseCalendar> formatter =
       ChronoFormatter.setUp(ChineseCalendar.axis(), Locale.ENGLISH)
         .addPattern("EEE, d. MMMM r(U) ", PatternType.CLDR_DATE)
         .addText(ChineseCalendar.SOLAR_TERM)
         .build();
     PlainDate winter =
       AstronomicalSeason.WINTER_SOLSTICE
         .inYear(2018)
         .toZonalTimestamp(ZonalOffset.ofHours(OffsetSign.AHEAD_OF_UTC, 8))
         .getCalendarDate();
     ChineseCalendar chineseDate = winter.transform(ChineseCalendar.class);
     assertThat(
       formatter.with(Locale.CHINESE).parse("周六, 16. 十一月 2018(戊戌) 冬至"),
       is(chineseDate));
     assertThat(
       formatter.format(chineseDate),
       is("Sat, 16. Eleventh Month 2018(wù-xū) dōngzhì"));
 

Printing gregorian dates together with Chinese cyclic year and zodiac:

  ChronoPrinter<PlainDate> yearPrinter = // for display of cyclic year
      (PlainDate gregorianDate, StringBuilder buffer, AttributeQuery attributes) -> {
          buffer.append(
              gregorianDate.transform(ChineseCalendar.axis()).getYear().getDisplayName(Locale.TRADITIONAL_CHINESE));
          return Collections.emptySet();
      };

  ChronoPrinter<PlainDate> zodiacPrinter = 
      (PlainDate gregorianDate, StringBuilder buffer, AttributeQuery attributes) -> {
          buffer.append(gregorianDate.transform(ChineseCalendar.axis()).getYear().getZodiac(Locale.TRADITIONAL_CHINESE));
          return Collections.emptySet();
      };

  ChronoFormatter<PlainDate> gf = ChronoFormatter.setUp(PlainDate.axis(), Locale.TRADITIONAL_CHINESE)
      .addPattern("y(", PatternType.CLDR)
      .addCustomized(PlainDate.COMPONENT, yearPrinter, ChronoParser.unsupported())
      //.startSection(Attributes.NUMBER_SYSTEM, NumberSystem.CHINESE_MANDARIN) // month and day in Chinese?
      .addPattern(")年M月d日(", PatternType.CLDR)
      //.endSection()
      .addCustomized(PlainDate.COMPONENT, zodiacPrinter, ChronoParser.unsupported())
      .addLiteral(')')
      .build();

  String s = gf.print(PlainDate.of(2023, 11, 5));
  System.out.println(s); // 2023(癸卯)年11月5日(兔)
 

Leap months can be formatted in various ways. Following example shows how to customize numerical printing when a non-Chinese language is used:

     ChronoFormatter<ChineseCalendar> f =
       ChronoFormatter.ofPattern("M/d, U(r)", PatternType.CLDR, Locale.ENGLISH, ChineseCalendar.axis())
         .with(EastAsianMonth.LEAP_MONTH_IS_TRAILING, true)
         .with(EastAsianMonth.LEAP_MONTH_INDICATOR, 'b');
     ChineseCalendar cc =
       ChineseCalendar.of(EastAsianYear.forGregorian(2020), EastAsianMonth.valueOf(4).withLeap(), 5);
     assertThat(
       f.format(cc),
       is("4b/5, " + cc.getYear().getDisplayName(Locale.ENGLISH) + "(2020)"));
 

Support for unicode ca-extensions

      Locale locale = Locale.forLanguageTag("en-u-ca-chinese");
      ChronoFormatter<CalendarDate> f = ChronoFormatter.ofGenericCalendarStyle(DisplayMode.FULL, locale);
      assertThat(
          f.format(PlainDate.of(2020, 5, 24)),
          is("Sunday, (leap) Fourth Month 2, 2020(gēng-zǐ)"));
 
Since:
3.40/4.35
Author:
Meno Hochschild
See Also:
Serialized Form
  • Field Details

  • Method Details

    • ofNewYear

      public static ChineseCalendar ofNewYear(int gregorianYear)

      Creates a new instance of a Chinese calendar date on traditional New Year.

      Parameters:
      gregorianYear - gregorian calendar year
      Returns:
      new instance of ChineseCalendar
      Throws:
      IllegalArgumentException - in case of any inconsistencies
    • ofQingMing

      public static ChineseCalendar ofQingMing(int gregorianYear)

      Creates a new instance of a Chinese calendar date on first day of QingMing-festival.

      Parameters:
      gregorianYear - gregorian calendar year
      Returns:
      new instance of ChineseCalendar
      Throws:
      IllegalArgumentException - in case of any inconsistencies
      Since:
      5.2
    • of

      public static ChineseCalendar of(EastAsianYear year, EastAsianMonth month, int dayOfMonth)

      Creates a new instance of a Chinese calendar date.

      Example for determining the date of Dragon Boat festival in gregorian year 2019:

           ChineseCalendar dragonBoatFestival =
                ChineseCalendar.of(
                    EastAsianYear.forGregorian(2019),
                    EastAsianMonth.valueOf(5),
                    5);
           System.out.println(dragonBoatFestival.transform(PlainDate.class));
           // Output: 2019-06-07
       

      Some other festival dates can be calculated in a similar way, see also www.officeholidays.com.

      Parameters:
      year - references the year using different systems like eras or sexagesimal cycles
      month - the month which might be a leap month
      dayOfMonth - the day of month to be checked
      Returns:
      new instance of ChineseCalendar
      Throws:
      IllegalArgumentException - in case of any inconsistencies
    • nowInSystemTime

      public static ChineseCalendar nowInSystemTime()

      Obtains the current calendar date in system time.

      Convenient short-cut for: SystemClock.inLocalView().now(ChineseCalendar.axis()).

      Returns:
      current calendar date in system time zone using the system clock
      See Also:
      SystemClock.inLocalView(), ZonalClock.now(Chronology)
    • isValid

      public static boolean isValid(EastAsianYear year, EastAsianMonth month, int dayOfMonth)

      Queries if given parameter values form a well defined calendar date.

      Parameters:
      year - the year to be checked
      month - the month to be checked
      dayOfMonth - the day of month to be checked
      Returns:
      true if valid else false
    • getDefaultWeekmodel

      public static Weekmodel getDefaultWeekmodel()

      Obtains the standard week model of this calendar.

      The Chinese calendar usually starts on Sunday.

      Returns:
      Weekmodel
    • axis

      public static TimeAxis<ChineseCalendar.Unit,​ChineseCalendar> axis()

      Returns the associated time axis.

      Returns:
      chronology