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

com.tyme.lunar.LunarDay Maven / Gradle / Ivy

There is a newer version: 1.1.8
Show newest version
package com.tyme.lunar;

import com.tyme.AbstractTyme;
import com.tyme.culture.Direction;
import com.tyme.culture.Duty;
import com.tyme.culture.Phase;
import com.tyme.culture.Week;
import com.tyme.culture.fetus.FetusDay;
import com.tyme.culture.star.nine.NineStar;
import com.tyme.culture.star.twelve.TwelveStar;
import com.tyme.culture.star.twentyeight.TwentyEightStar;
import com.tyme.festival.LunarFestival;
import com.tyme.sixtycycle.EarthBranch;
import com.tyme.sixtycycle.HeavenStem;
import com.tyme.sixtycycle.SixtyCycle;
import com.tyme.solar.SolarDay;
import com.tyme.solar.SolarTerm;

/**
 * 农历日
 *
 * @author 6tail
 */
public class LunarDay extends AbstractTyme {

  public static final String[] NAMES = {"初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十", "廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十"};

  /**
   * 农历月
   */
  protected LunarMonth month;

  /**
   * 日
   */
  protected int day;

  /**
   * 初始化
   *
   * @param year  农历年
   * @param month 农历月,闰月为负
   * @param day   农历日
   */
  protected LunarDay(int year, int month, int day) {
    LunarMonth m = LunarMonth.fromYm(year, month);
    if (day < 1 || day > m.getDayCount()) {
      throw new IllegalArgumentException(String.format("illegal day %d in %s", day, m));
    }
    this.month = m;
    this.day = day;
  }

  /**
   * 从农历年月日初始化
   *
   * @param year  农历年
   * @param month 农历月,闰月为负
   * @param day   农历日
   */
  public static LunarDay fromYmd(int year, int month, int day) {
    return new LunarDay(year, month, day);
  }

  /**
   * 农历月
   *
   * @return 农历月
   */
  public LunarMonth getMonth() {
    return month;
  }

  /**
   * 日
   *
   * @return 日
   */
  public int getDay() {
    return day;
  }

  public String getName() {
    return NAMES[day - 1];
  }

  @Override
  public String toString() {
    return month + getName();
  }

  public LunarDay next(int n) {
    if (n == 0) {
      return fromYmd(month.getYear().getYear(), month.getMonthWithLeap(), day);
    }
    int d = day + n;
    LunarMonth lm = month;
    int daysInMonth = lm.getDayCount();
    boolean forward = n > 0;
    int add = forward ? 1 : -1;
    while (forward ? (d > daysInMonth) : (d <= 0)) {
      if (forward) {
        d -= daysInMonth;
      }
      lm = lm.next(add);
      daysInMonth = lm.getDayCount();
      if (!forward) {
        d += daysInMonth;
      }
    }
    return fromYmd(lm.getYear().getYear(), lm.getMonthWithLeap(), d);
  }

  /**
   * 是否在指定农历日之前
   *
   * @param target 农历日
   * @return true/false
   */
  public boolean isBefore(LunarDay target) {
    int aYear = month.getYear().getYear();
    LunarMonth targetMonth = target.getMonth();
    int bYear = targetMonth.getYear().getYear();
    if (aYear == bYear) {
      int aMonth = month.getMonth();
      int bMonth = targetMonth.getMonth();
      if (aMonth == bMonth) {
        if (month.isLeap() && !targetMonth.isLeap()) {
          return false;
        }
        return day < target.getDay();
      }
      return aMonth < bMonth;
    }
    return aYear < bYear;
  }

  /**
   * 是否在指定农历日之后
   *
   * @param target 农历日
   * @return true/false
   */
  public boolean isAfter(LunarDay target) {
    int aYear = month.getYear().getYear();
    LunarMonth targetMonth = target.getMonth();
    int bYear = targetMonth.getYear().getYear();
    if (aYear == bYear) {
      int aMonth = month.getMonth();
      int bMonth = targetMonth.getMonth();
      if (aMonth == bMonth) {
        if (month.isLeap() && !targetMonth.isLeap()) {
          return true;
        }
        return day > target.getDay();
      }
      return aMonth > bMonth;
    }
    return aYear > bYear;
  }

  /**
   * 星期
   *
   * @return 星期
   */
  public Week getWeek() {
    return getSolarDay().getJulianDay().getWeek();
  }

  /**
   * 当天的年干支
   *
   * @return 干支
   */
  public SixtyCycle getYearSixtyCycle() {
    int solarYear = getSolarDay().getMonth().getYear().getYear();
    SolarTerm spring = SolarTerm.fromIndex(solarYear, 3);
    LunarYear lunarYear = month.getYear();
    SixtyCycle year = lunarYear.getSixtyCycle();
    if (lunarYear.getYear() < solarYear) {
      year = year.next(1);
    }
    if (getSolarDay().isBefore(spring.getJulianDay().getSolarDay())) {
      year = year.next(-1);
    }
    return year;
  }

  /**
   * 当天的月干支
   *
   * @return 干支
   */
  public SixtyCycle getMonthSixtyCycle() {
    SolarTerm term = getSolarDay().getTerm();
    if (term.isQi()) {
      term = term.next(-1);
    }
    return term.getJulianDay().getSolarDay().getLunarDay().getMonth().getSixtyCycle();
  }

  /**
   * 干支
   *
   * @return 干支
   */
  public SixtyCycle getSixtyCycle() {
    int offset = (int) month.getFirstJulianDay().next(day - 12).getDay();
    return SixtyCycle.fromName(HeavenStem.fromIndex(offset).getName() + EarthBranch.fromIndex(offset).getName());
  }

  /**
   * 建除十二值神
   *
   * @return 建除十二值神
   */
  public Duty getDuty() {
    return Duty.fromIndex(getSixtyCycle().getEarthBranch().getIndex() - getMonthSixtyCycle().getEarthBranch().getIndex());
  }

  /**
   * 黄道黑道十二神
   *
   * @return 黄道黑道十二神
   */
  public TwelveStar getTwelveStar() {
    return TwelveStar.fromIndex(getSixtyCycle().getEarthBranch().getIndex() + (8 - getMonthSixtyCycle().getEarthBranch().getIndex() % 6) * 2);
  }

  /**
   * 九星
   *
   * @return 九星
   */
  public NineStar getNineStar() {
    SolarDay solar = getSolarDay();
    SolarTerm dongZhi = SolarTerm.fromIndex(solar.getMonth().getYear().getYear(), 0);
    SolarTerm xiaZhi = dongZhi.next(12);
    SolarTerm dongZhi2 = dongZhi.next(24);
    SolarDay dongZhiSolar = dongZhi.getJulianDay().getSolarDay();
    SolarDay xiaZhiSolar = xiaZhi.getJulianDay().getSolarDay();
    SolarDay dongZhiSolar2 = dongZhi2.getJulianDay().getSolarDay();
    int dongZhiIndex = dongZhiSolar.getLunarDay().getSixtyCycle().getIndex();
    int xiaZhiIndex = xiaZhiSolar.getLunarDay().getSixtyCycle().getIndex();
    int dongZhiIndex2 = dongZhiSolar2.getLunarDay().getSixtyCycle().getIndex();
    SolarDay solarShunBai = dongZhiSolar.next(dongZhiIndex > 29 ? 60 - dongZhiIndex : -dongZhiIndex);
    SolarDay solarShunBai2 = dongZhiSolar2.next(dongZhiIndex2 > 29 ? 60 - dongZhiIndex2 : -dongZhiIndex2);
    SolarDay solarNiZi = xiaZhiSolar.next(xiaZhiIndex > 29 ? 60 - xiaZhiIndex : -xiaZhiIndex);
    int offset = 0;
    if (!solar.isBefore(solarShunBai) && solar.isBefore(solarNiZi)) {
      offset = solar.subtract(solarShunBai);
    } else if (!solar.isBefore(solarNiZi) && solar.isBefore(solarShunBai2)) {
      offset = 8 - solar.subtract(solarNiZi);
    } else if (!solar.isBefore(solarShunBai2)) {
      offset = solar.subtract(solarShunBai2);
    } else if (solar.isBefore(solarShunBai)) {
      offset = 8 + solarShunBai.subtract(solar);
    }
    return NineStar.fromIndex(offset);
  }

  /**
   * 太岁方位
   *
   * @return 方位
   */
  public Direction getJupiterDirection() {
    int index = getSixtyCycle().getIndex();
    if (index % 12 < 6) {
      return Direction.fromIndex(new int[]{2, 8, 4, 6, 0}[index / 12]);
    }
    return month.getYear().getJupiterDirection();
  }

  /**
   * 逐日胎神
   *
   * @return 逐日胎神
   */
  public FetusDay getFetusDay() {
    return FetusDay.fromLunarDay(this);
  }

  /**
   * 月相
   *
   * @return 月相
   */
  public Phase getPhase() {
    return Phase.fromIndex(day - 1);
  }

  /**
   * 公历日
   *
   * @return 公历日
   */
  public SolarDay getSolarDay() {
    return month.getFirstJulianDay().next(day - 1).getSolarDay();
  }

  /**
   * 二十八宿
   *
   * @return 二十八宿
   */
  public TwentyEightStar getTwentyEightStar() {
    return TwentyEightStar.fromIndex(new int[]{10, 18, 26, 6, 14, 22, 2}[getSolarDay().getWeek().getIndex()]).next(-7 * getSixtyCycle().getEarthBranch().getIndex());
  }

  /**
   * 农历传统节日,如果当天不是农历传统节日,返回null
   *
   * @return 农历传统节日
   */
  public LunarFestival getFestival() {
    LunarMonth m = getMonth();
    return LunarFestival.fromYmd(m.getYear().getYear(), m.getMonthWithLeap(), day);
  }

  @Override
  public boolean equals(Object o) {
    if (!(o instanceof LunarDay)) {
      return false;
    }
    LunarDay target = (LunarDay) o;
    return month.equals(target.getMonth()) && day == target.getDay();
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy