Class ChineseCalendar
- All Implemented Interfaces:
Serializable
,Comparable<ChineseCalendar>
,CalendarDate
,ChronoDisplay
,Temporal<CalendarDate>
,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
DAY_OF_WEEK
DAY_OF_MONTH
DAY_OF_YEAR
WEEKDAY_IN_MONTH
MONTH_OF_YEAR
MONTH_AS_ORDINAL
SOLAR_TERM
YEAR_OF_CYCLE
YEAR_OF_ERA
CYCLE
ERA
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
-
Nested Class Summary
Modifier and TypeClassDescriptionstatic class
Defines some calendar units for the Chinese calendar. -
Field Summary
Modifier and TypeFieldDescriptionstatic ChronoElement<Integer>
Represents the cycle number related to the introduction of sexagesimal cycles by the legendary yellow emperor Huang-Di on -2636-02-15 (gregorian).static StdCalendarElement<Integer,ChineseCalendar>
Represents the Chinese day of month.static StdCalendarElement<Weekday,ChineseCalendar>
Represents the Chinese day of week.static StdCalendarElement<Integer,ChineseCalendar>
Represents the Chinese day of year.static ChronoElement<ChineseEra>
Represents the Chinese era.static StdCalendarElement<Integer,ChineseCalendar>
Represents the ordinal index of a Chinese month in the range1-12/13
.static TextElement<EastAsianMonth>
Represents the Chinese month.static ChronoElement<SolarTerm>
Represents the solar term as one of 24 possible stations of the sun on the ecliptic.static OrdinalWeekdayElement<ChineseCalendar>
Element with the ordinal day-of-week within given calendar month.static TextElement<CyclicYear>
Represents the Chinese year related to the current sexagesimal cycle.static StdCalendarElement<Integer,ChineseCalendar>
Represents the Chinese year related to the Chinese era. -
Method Summary
Modifier and TypeMethodDescriptionstatic TimeAxis<ChineseCalendar.Unit,ChineseCalendar>
axis()
Returns the associated time axis.static Weekmodel
Obtains the standard week model of this calendar.static boolean
isValid(EastAsianYear year, EastAsianMonth month, int dayOfMonth)
Queries if given parameter values form a well defined calendar date.static ChineseCalendar
Obtains the current calendar date in system time.static ChineseCalendar
of(EastAsianYear year, EastAsianMonth month, int dayOfMonth)
Creates a new instance of a Chinese calendar date.static ChineseCalendar
ofNewYear(int gregorianYear)
Creates a new instance of a Chinese calendar date on traditional New Year.static ChineseCalendar
ofQingMing(int gregorianYear)
Creates a new instance of a Chinese calendar date on first day of QingMing-festival.Methods inherited from class net.time4j.calendar.EastAsianCalendar
at, atTime, equals, findLeapMonth, getDayOfMonth, getDayOfWeek, getDayOfYear, getDaysSinceEpochUTC, getMonth, getSexagesimalDay, getSexagesimalMonth, getSolarTerm, getYear, hashCode, isLeapYear, lengthOfMonth, lengthOfYear, toString, withBeginOfNextLeapMonth
Methods inherited from class net.time4j.engine.Calendrical
compareTo, isAfter, isBefore, isSimultaneous, minus, plus
Methods inherited from class net.time4j.engine.TimePoint
max, min, minus, minus, plus, plus, until, until
Methods inherited from class net.time4j.engine.ChronoEntity
contains, get, get, getInt, getMaximum, getMinimum, getRegisteredElements, getTimezone, hasTimezone, isValid, isValid, isValid, matches, with, with, with, with
Methods inherited from interface net.time4j.engine.CalendarDate
transform, transform, transform, transform, transform, transform
Methods inherited from interface net.time4j.format.LocalizedPatternSupport
getFormatPattern, getFormatPattern, useDynamicFormatPattern
Methods inherited from interface net.time4j.engine.Temporal
isAfterAll, isAfterOrEqual, isBeforeAll, isBeforeOrEqual
-
Field Details
-
ERA
Represents the Chinese era.
This element is effectively read-only. Its value cannot be changed in a direct and meaningful way.
- See Also:
YEAR_OF_ERA
-
CYCLE
Represents the cycle number related to the introduction of sexagesimal cycles by the legendary yellow emperor Huang-Di on -2636-02-15 (gregorian).
This kind of counting is NOT in common use in China and only offered for technical reasons. Prefer just the cyclic year together with the related gregorian year instead.
-
YEAR_OF_ERA
@FormattableElement(format="y") public static final StdCalendarElement<Integer,ChineseCalendar> YEAR_OF_ERARepresents the Chinese year related to the Chinese era.
This kind of year counting is NOT in common use in China today and only offered for historical reasons. Prefer the cyclic year instead.
- See Also:
ERA
,YEAR_OF_CYCLE
-
YEAR_OF_CYCLE
Represents the Chinese year related to the current sexagesimal cycle.
This is the standard way to specify a Chinese year.
-
SOLAR_TERM
Represents the solar term as one of 24 possible stations of the sun on the ecliptic.
When manipulating then this element behaves as if the next solar term on or after new year is set. The behaviour is equivalent to
date.with(solarTerm.sinceNewYear())
. Please be aware of the fact that the resulting date might be sometimes in the next calendar year. An alternative being more consistent with gregorian year cycles is given by the expressiondate.with(solarTerm.sinceLichun())
. Example:ChineseCalendar date = PlainDate.of(2017, 12, 22).transform(ChineseCalendar.axis()); date = date.with(ChineseCalendar.SOLAR_TERM, SolarTerm.MINOR_03_QINGMING_015); System.out.println(date.transform(PlainDate.axis())); // 2017-04-04
- See Also:
SolarTerm.sinceNewYear()
,SolarTerm.sinceLichun()
-
MONTH_OF_YEAR
@FormattableElement(format="M", alt="L") public static final TextElement<EastAsianMonth> MONTH_OF_YEARRepresents the Chinese month.
-
MONTH_AS_ORDINAL
Represents the ordinal index of a Chinese month in the range
1-12/13
.This element can be used in conjunction with
ordinal formatting
. -
DAY_OF_MONTH
@FormattableElement(format="d") public static final StdCalendarElement<Integer,ChineseCalendar> DAY_OF_MONTHRepresents the Chinese day of month.
Months have either 29 or 30 days.
-
DAY_OF_YEAR
@FormattableElement(format="D") public static final StdCalendarElement<Integer,ChineseCalendar> DAY_OF_YEARRepresents the Chinese day of year.
-
DAY_OF_WEEK
@FormattableElement(format="E") public static final StdCalendarElement<Weekday,ChineseCalendar> DAY_OF_WEEKRepresents the Chinese day of week.
If the day-of-week is set to a new value then Time4J handles the Chinese calendar week as starting on Sunday (like in China).
-
WEEKDAY_IN_MONTH
@FormattableElement(format="F") public static final OrdinalWeekdayElement<ChineseCalendar> WEEKDAY_IN_MONTHElement with the ordinal day-of-week within given calendar month.
-
-
Method Details
-
ofNewYear
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
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
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 cyclesmonth
- the month which might be a leap monthdayOfMonth
- the day of month to be checked- Returns:
- new instance of
ChineseCalendar
- Throws:
IllegalArgumentException
- in case of any inconsistencies
-
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
Queries if given parameter values form a well defined calendar date.
- Parameters:
year
- the year to be checkedmonth
- the month to be checkeddayOfMonth
- the day of month to be checked- Returns:
true
if valid elsefalse
-
getDefaultWeekmodel
Obtains the standard week model of this calendar.
The Chinese calendar usually starts on Sunday.
- Returns:
- Weekmodel
-
axis
Returns the associated time axis.
- Returns:
- chronology
-