MenoData / Time4J

Advanced date, time and interval library for Java with sun/moon-astronomy and calendars like Chinese, Coptic, Ethiopian, French Republican, Hebrew, Hijri, Historic Christian, Indian National, Japanese, Julian, Korean, Minguo, Persian, Thai, Vietnamese
GNU Lesser General Public License v2.1
424 stars 62 forks source link

How to get leap months in chinese calendar #913

Closed dearming623 closed 3 years ago

dearming623 commented 3 years ago

The library works very well.

Can you provide a method to get the leap month of the year and the number of days of the leap month.

MenoData commented 3 years ago

For length of month in days (leap month or not), just look at the method lengthOfMonth() in the super class EastAsianCalendar. Another standardized (but more complicated) approach would be: chineseCalendar.getMaximum(ChineseCalendar.DAY_OF_MONTH).

About finding leap month in a given year, this is more complicated because there is no simple algorithmic formula to find it. It happens all 2-3 years once and can match almost every month to be doubled. At least you can easily determine if a given year contains a leap month at all by calling the method isLeapYear(). So a kind of search iterating over every month in given leap year would give the leap month in question. Something like (untested):

ChineseCalendar chineseCalendar = ChineseCalendar.ofNewYear(2020);
EastAsianMonth m;

while (
  !(m = chineseCalendar.getMonth()).isLeap() 
  && (chineseCalendar.getInt(CommonElements.RELATED_GREGORIAN_YEAR) == 2020)
) {
  chineseCalendar = chineseCalendar.plus(1, ChineseCalendar.Unit.MONTHS);
}

if (m.isLeap()) {
  System.out.println("Leap month found in 2020:" + m);
}

Good luck, By the way, I am offline for the next two weeks (far away from phone and internet in my holidays).

MenoData commented 3 years ago

I have now added two extra methods to the super class EastAsianCalendar with following signatures:

// Query for finding a leap month within the current calendar year
public Optional<EastAsianMonth> findLeapMonth()

// Moving the current date to begin of next leap month
public D withBeginOfNextLeapMonth()