All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tyme.festival.LunarFestival Maven / Gradle / Ivy

There is a newer version: 1.1.7
Show newest version
package com.tyme.festival;

import com.tyme.AbstractTyme;
import com.tyme.enums.FestivalType;
import com.tyme.lunar.LunarDay;
import com.tyme.solar.SolarTerm;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 农历传统节日(依据国家标准《农历的编算和颁行》GB/T 33661-2017)
 *
 * @author 6tail
 */
public class LunarFestival extends AbstractTyme {

  public static final String[] NAMES = {"春节", "元宵节", "龙头节", "上巳节", "清明节", "端午节", "七夕节", "中元节", "中秋节", "重阳节", "冬至节", "腊八节", "除夕"};

  public static String DATA = "@0000101@0100115@0200202@0300303@04107@0500505@0600707@0700715@0800815@0900909@10124@1101208@122";

  /**
   * 类型
   */
  protected FestivalType type;

  /**
   * 索引
   */
  protected int index;

  /**
   * 农历日
   */
  protected LunarDay day;

  /**
   * 节气
   */
  protected SolarTerm solarTerm;

  /**
   * 名称
   */
  protected String name;

  public LunarFestival(FestivalType type, LunarDay day, SolarTerm solarTerm, String data) {
    this.type = type;
    this.day = day;
    this.solarTerm = solarTerm;
    index = Integer.parseInt(data.substring(1, 3), 10);
    name = NAMES[index];
  }

  public static LunarFestival fromIndex(int year, int index) {
    if (index < 0 || index >= NAMES.length) {
      throw new IllegalArgumentException(String.format("illegal index: %d", index));
    }
    Matcher matcher = Pattern.compile(String.format("@%02d\\d+", index)).matcher(DATA);
    if (!matcher.find()) {
      return null;
    }
    String data = matcher.group();
    FestivalType type = FestivalType.fromCode(data.charAt(3) - '0');
    switch (type) {
      case DAY:
        return new LunarFestival(type, LunarDay.fromYmd(year, Integer.parseInt(data.substring(4, 6), 10), Integer.parseInt(data.substring(6), 10)), null, data);
      case TERM:
        SolarTerm solarTerm = SolarTerm.fromIndex(year, Integer.parseInt(data.substring(4), 10));
        return new LunarFestival(type, solarTerm.getJulianDay().getSolarDay().getLunarDay(), solarTerm, data);
      case EVE:
        return new LunarFestival(type, LunarDay.fromYmd(year + 1, 1, 1).next(-1), null, data);
      default:
        return null;
    }
  }

  public static LunarFestival fromYmd(int year, int month, int day) {
    Matcher matcher = Pattern.compile(String.format("@\\d{2}0%02d%02d", month, day)).matcher(DATA);
    if (matcher.find()) {
      return new LunarFestival(FestivalType.DAY, LunarDay.fromYmd(year, month, day), null, matcher.group());
    }
    matcher = Pattern.compile("@\\d{2}1\\d{2}").matcher(DATA);
    while (matcher.find()) {
      String data = matcher.group();
      SolarTerm solarTerm = SolarTerm.fromIndex(year, Integer.parseInt(data.substring(4), 10));
      LunarDay lunarDay = solarTerm.getJulianDay().getSolarDay().getLunarDay();
      if (lunarDay.getYear() == year && lunarDay.getMonth() == month && lunarDay.getDay() == day) {
        return new LunarFestival(FestivalType.TERM, lunarDay, solarTerm, data);
      }
    }
    matcher = Pattern.compile("@\\d{2}2").matcher(DATA);
    if (!matcher.find()) {
      return null;
    }
    LunarDay lunarDay = LunarDay.fromYmd(year, month, day);
    LunarDay nextDay = lunarDay.next(1);
    return nextDay.getMonth() == 1 && nextDay.getDay() == 1 ? new LunarFestival(FestivalType.EVE, lunarDay, null, matcher.group()) : null;
  }

  public LunarFestival next(int n) {
    if (n == 0) {
      return fromYmd(day.getYear(), day.getMonth(), day.getDay());
    }
    int size = NAMES.length;
    int t = index + n;
    int offset = indexOf(t, size);
    if (t < 0) {
      t -= size;
    }
    return fromIndex(day.getYear() + t / size, offset);
  }

  /**
   * 类型
   *
   * @return 节日类型
   */
  public FestivalType getType() {
    return type;
  }

  /**
   * 索引
   *
   * @return 索引
   */
  public int getIndex() {
    return index;
  }

  /**
   * 农历日
   *
   * @return 农历日
   */
  public LunarDay getDay() {
    return day;
  }

  /**
   * 节气,非节气返回null
   *
   * @return 节气
   */
  public SolarTerm getSolarTerm() {
    return solarTerm;
  }

  public String getName() {
    return name;
  }

  @Override
  public String toString() {
    return String.format("%s %s", day, name);
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy